Java Keymaster SDK
Overview
The Java Keymaster SDK lets JVM applications create and manage DIDs, issue credentials, and handle challenge/response flows by calling a Gatekeeper REST service.
Who this is for
- Java and Kotlin backend services (including Spring Boot).
- Android/JVM clients that need Keymaster functionality.
- Teams that want a Java-native alternative to the JS SDK.
What this page covers
- Install and setup (Gradle/Maven).
- Configuration and runtime notes.
- Core workflows for IDs, credentials, challenges, assets, and groups.
- Crypto helpers and low-level APIs.
- Tests.
Install
Choose your build tool and add the Keymaster SDK dependencies.
- Gradle (Groovy or Kotlin DSL)
- Maven
dependencies {
implementation("org.keychain:keymaster:<version>")
implementation("org.keychain:gatekeeper:<version>") // Gatekeeper REST client
// Optional direct modules
implementation("org.keychain:crypto:<version>")
implementation("org.keychain:cid:<version>")
}
<dependencies>
<dependency>
<groupId>org.keychain</groupId>
<artifactId>keymaster</artifactId>
<version>${keymaster.version}</version>
</dependency>
<dependency>
<groupId>org.keychain</groupId>
<artifactId>gatekeeper</artifactId>
<version>${keymaster.version}</version>
</dependency>
<!-- Optional direct modules -->
<dependency>
<groupId>org.keychain</groupId>
<artifactId>crypto</artifactId>
<version>${keymaster.version}</version>
</dependency>
<dependency>
<groupId>org.keychain</groupId>
<artifactId>cid</artifactId>
<version>${keymaster.version}</version>
</dependency>
</dependencies>
Configuration
Gatekeeper URL
Keymaster talks to a Gatekeeper REST service. By default, the client connects to:
http://localhost:4224
To override, set KC_GATEKEEPER_URL in the environment before creating a client.
Registry
localis recommended for development and live tests.hyperswarmis commonly used for production networks.
Wallet storage and passphrase
The SDK stores an encrypted wallet file on disk. You must provide:
- A wallet file path (or directory + filename)
- A passphrase to encrypt the mnemonic
Hello Keymaster
Minimal setup that creates an ID and resolves it back:
import java.nio.file.Path;
import java.nio.file.Paths;
import org.keychain.gatekeeper.GatekeeperClient;
import org.keychain.gatekeeper.GatekeeperClientOptions;
import org.keychain.keymaster.Keymaster;
import org.keychain.keymaster.model.WalletEncFile;
import org.keychain.keymaster.store.WalletJson;
import org.keychain.keymaster.store.WalletStore;
Path dataDir = Paths.get(System.getProperty("user.home"), ".keymaster");
WalletStore<WalletEncFile> store = new WalletJson<>(WalletEncFile.class, dataDir, "wallet.json");
GatekeeperClientOptions options = new GatekeeperClientOptions();
options.baseUrl = "http://localhost:4224";
GatekeeperClient gatekeeper = new GatekeeperClient(options);
Keymaster keymaster = new Keymaster(store, gatekeeper, "passphrase", "local");
String did = keymaster.createId("Alice");
System.out.println("DID: " + did);
System.out.println(keymaster.resolveDID(did).didDocument.id);
IDs
Create an ID and resolve it:
String did = keymaster.createId("Alice");
System.out.println("DID: " + did);
System.out.println(keymaster.resolveDID(did).didDocument.id);
Set the current ID and list IDs in the wallet:
keymaster.setCurrentId("Alice");
System.out.println(keymaster.listIds());
Wallet and ID management
Wallet lifecycle
Create a new wallet, then load it:
String mnemonic = "red orange yellow green blue indigo violet pink white black brown grey";
keymaster.newWallet(mnemonic, true);
WalletFile wallet = keymaster.loadWallet();
System.out.println(wallet.current);
Update and save the wallet using mutateWallet to avoid race conditions when multiple threads
read and write the wallet at the same time:
keymaster.mutateWallet(w -> {
w.extras = Map.of("owner", "team-keymaster");
});
Names and aliases
Validate and manage friendly names:
keymaster.validateName("Alice");
keymaster.addName("alice-main", "did:test:123");
System.out.println(keymaster.getName("alice-main"));
keymaster.removeName("alice-main");
ID maintenance
Rename or remove IDs in the wallet:
keymaster.renameId("Alice", "Alice-1");
keymaster.removeId("Alice-1");
Backup and recovery
Back up the current ID and wallet:
keymaster.backupId();
String backupDid = keymaster.backupWallet("local");
System.out.println(backupDid);
Recover a wallet or ID from a backup DID:
WalletFile recoveredWallet = keymaster.recoverWallet(backupDid);
String recoveredId = keymaster.recoverId(backupDid);
Export an encrypted wallet payload for storage:
WalletEncFile encrypted = keymaster.exportEncryptedWallet();
Assets and schemas
Create and update assets:
String assetDid = keymaster.createAsset(Map.of("name", "mockData"));
Map<String, Object> data = (Map<String, Object>) keymaster.resolveAsset(assetDid);
data.put("status", "active");
keymaster.updateAsset(assetDid, data);
Transfer an asset to a different controller:
String alice = keymaster.createId("Alice");
String bob = keymaster.createId("Bob");
String assetDid = keymaster.createAsset(Map.of("name", "asset-1"));
keymaster.transferAsset(assetDid, bob);
Clone an asset into another registry or controller:
String cloned = keymaster.cloneAsset(assetDid, "local", alice);
Schema helpers:
String schemaDid = keymaster.createSchema(emailSchema);
Object schema = keymaster.getSchema(schemaDid);
boolean ok = keymaster.testSchema(schemaDid);
Map<String, Object> template = keymaster.createTemplate(schemaDid);
List assets and schemas:
System.out.println(keymaster.listAssets());
System.out.println(keymaster.listSchemas());
Credentials
Create a schema, bind a credential, issue it, and publish with reveal:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.keychain.keymaster.PublishCredentialOptions;
Map<String, Object> emailSchema = new HashMap<>();
emailSchema.put("$schema", "http://json-schema.org/draft-07/schema#");
Map<String, Object> properties = new HashMap<>();
Map<String, Object> email = new HashMap<>();
email.put("format", "email");
email.put("type", "string");
properties.put("email", email);
emailSchema.put("properties", properties);
emailSchema.put("required", List.of("email"));
emailSchema.put("type", "object");
String aliceDid = keymaster.createId("Alice");
String schemaDid = keymaster.createSchema(emailSchema);
Map<String, Object> bound = keymaster.bindCredential(schemaDid, aliceDid);
@SuppressWarnings("unchecked")
Map<String, Object> credential = (Map<String, Object>) bound.get("credential");
credential.put("email", "alice@example.com");
String credentialDid = keymaster.issueCredential(bound);
PublishCredentialOptions publish = new PublishCredentialOptions();
publish.reveal = true;
keymaster.publishCredential(credentialDid, publish);
Manage issued and held credentials:
System.out.println(keymaster.listIssued("Alice"));
System.out.println(keymaster.listCredentials("Alice"));
Accept, update, and revoke credentials:
keymaster.acceptCredential(credentialDid);
@SuppressWarnings("unchecked")
Map<String, Object> vc = (Map<String, Object>) keymaster.getCredential(credentialDid);
Map<String, Object> cred = (Map<String, Object>) vc.get("credential");
cred.put("email", "alice+updated@example.com");
keymaster.updateCredential(credentialDid, vc);
keymaster.revokeCredential(credentialDid);
Unpublish or remove a credential from the wallet:
keymaster.unpublishCredential(credentialDid);
keymaster.removeCredential(credentialDid);
Groups
Create a group and add members:
String groupDid = keymaster.createGroup("engineering");
String memberDid = keymaster.createId("Bob");
keymaster.addGroupMember(groupDid, memberDid);
keymaster.removeGroupMember(groupDid, memberDid);
Check membership and list groups:
boolean isMember = keymaster.testGroup(groupDid, memberDid);
System.out.println(isMember);
System.out.println(keymaster.listGroups());