Java SDK Guide
Dependencies
Add to your pom.xml (Maven):
xml
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>Or build.gradle (Gradle):
gradle
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.google.code.gson:gson:2.10.1'
}Basic Usage
java
import okhttp3.*;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
public class KeyClaimClient {
private static final String API_BASE_URL = "https://keyclaim.org/api";
private final String apiKey;
private final String secret;
private final OkHttpClient client;
private final Gson gson;
public KeyClaimClient(String apiKey, String secret) {
this.apiKey = apiKey;
this.secret = secret != null ? secret : apiKey;
this.client = new OkHttpClient();
this.gson = new Gson();
}
// Step 1: Create a challenge
public ChallengeResponse createChallenge(int ttl) throws Exception {
JsonObject requestBody = new JsonObject();
requestBody.addProperty("key", apiKey);
requestBody.addProperty("ttl", ttl);
RequestBody body = RequestBody.create(
requestBody.toString(),
MediaType.parse("application/json")
);
Request request = new Request.Builder()
.url(API_BASE_URL + "/challenge/create")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new Exception("Failed to create challenge: " + response.code());
}
String responseBody = response.body().string();
return gson.fromJson(responseBody, ChallengeResponse.class);
}
}
// Step 2: Generate response from challenge
// Option A: Simple echo (for testing)
public String generateResponseSimple(String challenge) {
return challenge;
}
// Option B: HMAC-SHA256 (recommended)
public String generateResponseHMAC(String challenge) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(
secret.getBytes(StandardCharsets.UTF_8),
"HmacSHA256"
);
mac.init(secretKeySpec);
byte[] hash = mac.doFinal(challenge.getBytes(StandardCharsets.UTF_8));
// Convert to hex string
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
// Option C: SHA256 Hash
public String generateResponseHash(String challenge) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest((challenge + secret).getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
// Step 3: Validate the response
public ValidationResponse validate(String challenge, String response) throws Exception {
JsonObject requestBody = new JsonObject();
requestBody.addProperty("key", apiKey);
requestBody.addProperty("challenge", challenge);
requestBody.addProperty("response", response);
RequestBody body = RequestBody.create(
requestBody.toString(),
MediaType.parse("application/json")
);
Request request = new Request.Builder()
.url(API_BASE_URL + "/challenge/validate")
.post(body)
.build();
try (Response httpResponse = client.newCall(request).execute()) {
String responseBody = httpResponse.body().string();
ValidationResponse result = gson.fromJson(responseBody, ValidationResponse.class);
if (!httpResponse.isSuccessful()) {
result.valid = false;
}
return result;
}
}
// Complete example
public ValidationResponse validateChallenge(String challenge, String method) throws Exception {
String response;
switch (method) {
case "echo":
response = generateResponseSimple(challenge);
break;
case "hmac":
response = generateResponseHMAC(challenge);
break;
case "hash":
response = generateResponseHash(challenge);
break;
default:
throw new IllegalArgumentException("Unknown method: " + method);
}
return validate(challenge, response);
}
// Response classes
public static class ChallengeResponse {
public String challenge;
public int expires_in;
}
public static class ValidationResponse {
public boolean valid;
public String error;
public String signature;
}
}Usage Example
java
public class Example {
public static void main(String[] args) {
try {
KeyClaimClient client = new KeyClaimClient(
"kc_your_api_key",
"your-secret-key"
);
// Create challenge
KeyClaimClient.ChallengeResponse challengeResp = client.createChallenge(30);
String challenge = challengeResp.challenge;
System.out.println("Challenge: " + challenge);
// Generate response
String response = client.generateResponseHMAC(challenge);
System.out.println("Response: " + response);
// Validate
KeyClaimClient.ValidationResponse result = client.validate(challenge, response);
System.out.println("Valid: " + result.valid);
if (result.valid) {
System.out.println("✓ Challenge validated successfully!");
if (result.signature != null) {
System.out.println("Signature: " + result.signature);
}
} else {
System.out.println("✗ Validation failed: " + result.error);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}Response Generation Methods
Method 1: Echo (Testing)
java
public String generateResponseEcho(String challenge) {
return challenge;
}Method 2: HMAC-SHA256 (Recommended)
java
public String generateResponseHMAC(String challenge) throws Exception {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(
secret.getBytes(StandardCharsets.UTF_8),
"HmacSHA256"
);
mac.init(secretKeySpec);
byte[] hash = mac.doFinal(challenge.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash);
}
private String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}Method 3: SHA256 Hash
java
public String generateResponseHash(String challenge) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest((challenge + secret).getBytes(StandardCharsets.UTF_8));
return bytesToHex(hash);
}Explore Other Documentation
Choose your preferred programming language

Node.js Documentation
JavaScript/TypeScript integration guide
View Guide→

Python Documentation
Python 3.7+ integration guide
View Guide→

PHP Documentation
PHP 7.4+ integration guide
View Guide→

Kotlin Documentation
Kotlin/JVM integration guide
View Guide→
C# Documentation
.NET/C# integration guide
View Guide→

Go Documentation
Go 1.18+ integration guide
View Guide→
