Add one dependency and the framework starter handles the rest.
Both starters auto-configure all OPAQUE and OPRF endpoints with sensible defaults.
// build.gradle.kts
dependencies {
implementation("com.codeheadsystems:hofmann-springboot:<version>")
}
# application.yml
hofmann:
context: my-app-v1
server-key-seed-hex: ${SERVER_KEY_SEED_HEX}
oprf-seed-hex: ${OPRF_SEED_HEX}
oprf-master-key-hex: ${OPRF_MASTER_KEY_HEX}
jwt-secret-hex: ${JWT_SECRET_HEX}
argon2-memory-kib: 65536
argon2-iterations: 3
argon2-parallelism: 1
All endpoints are registered automatically. Override any bean with
@ConditionalOnMissingBean to plug in your own
CredentialStore, SessionStore, or SecureRandom.
// build.gradle.kts
dependencies {
implementation("com.codeheadsystems:hofmann-dropwizard:<version>")
}
// In your Application class
@Override
public void initialize(Bootstrap<MyConfig> bootstrap) {
bootstrap.addBundle(new HofmannBundle<>());
}
For production, supply persistent stores:
new HofmannBundle<>(credentialStore, sessionStore, null)
// npm install hofmann-client
import { OpaqueHttpClient } from 'hofmann-client';
// Auto-configures cipher suite and KSF params from server
const client = await OpaqueHttpClient.create('https://api.example.com');
// Register
await client.register('user@example.com', 'correct-horse-battery-staple');
// Authenticate
const session = await client.authenticate('user@example.com', 'correct-horse-battery-staple');
console.log(session.jwt); // Bearer token for subsequent API calls
The TypeScript client runs in the browser or Node.js. It handles the full OPAQUE
handshake including Argon2id key stretching on the client side.