@Override
    public int invoke(ToolInvocation invocation) {
        try {
            var arguments   = invocation.arguments();
            var privOutPath = Paths.get(CliUtils.optionOrThrow(arguments, PRIVATE_OUT_FILE_OPTION));
            var pubOutPath  = Paths.get(CliUtils.optionOrThrow(arguments, PUBLIC_OUT_FILE_OPTION));
            verifyNotSameKeyPaths(privOutPath, pubOutPath);

            boolean allowOverwrite = arguments.hasOption(OVERWRITE_EXISTING_OPTION);
            handleExistingFileIfAny(privOutPath, allowOverwrite);
            handleExistingFileIfAny(pubOutPath,  allowOverwrite);

            var keyPair = KeyUtils.generateX25519KeyPair();
            var privKey = (XECPrivateKey) keyPair.getPrivate();
            var pubKey  = (XECPublicKey) keyPair.getPublic();

            var privFilePerms = PosixFilePermissions.fromString("rw-------");
            Files.createFile( privOutPath, PosixFilePermissions.asFileAttribute(privFilePerms));
            Files.writeString(privOutPath, KeyUtils.toBase58EncodedX25519PrivateKey(privKey) + "\n");
            Files.writeString(pubOutPath,  KeyUtils.toBase58EncodedX25519PublicKey(pubKey) + "\n");

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return 0;
    }
Tooling to generate random X25519 key pairs.

@author vekterli
vespaclient-java/src/main/java/com/yahoo/vespa/security/tool/crypto/KeygenTool.java