Usage Guide
Usage Guide
This guide provides examples for using GlaSSLess cryptographic operations.
Message Digest (Hashing)
import java.security.MessageDigest;
import java.security.Security;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
MessageDigest md = MessageDigest.getInstance("SHA-256", PROVIDER_NAME);
byte[] hash = md.digest("Hello, World!".getBytes());
Symmetric Encryption (AES-GCM)
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.SecureRandom;
import java.security.Security;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Generate a key
KeyGenerator keyGen = KeyGenerator.getInstance("AES", PROVIDER_NAME);
keyGen.init(256);
SecretKey key = keyGen.generateKey();
// Generate IV
byte[] iv = new byte[12];
SecureRandom random = SecureRandom.getInstance("NativePRNG", PROVIDER_NAME);
random.nextBytes(iv);
// Encrypt
Cipher cipher = Cipher.getInstance("AES_256/GCM/NoPadding", PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, iv));
byte[] ciphertext = cipher.doFinal("Secret message".getBytes());
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, iv));
byte[] plaintext = cipher.doFinal(ciphertext);
Digital Signatures (ECDSA)
import java.security.*;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Generate key pair
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("EC", PROVIDER_NAME);
keyPairGen.initialize(256);
KeyPair keyPair = keyPairGen.generateKeyPair();
// Sign
Signature signer = Signature.getInstance("SHA256withECDSA", PROVIDER_NAME);
signer.initSign(keyPair.getPrivate());
signer.update("Data to sign".getBytes());
byte[] signature = signer.sign();
// Verify
Signature verifier = Signature.getInstance("SHA256withECDSA", PROVIDER_NAME);
verifier.initVerify(keyPair.getPublic());
verifier.update("Data to sign".getBytes());
boolean valid = verifier.verify(signature);
Deterministic ECDSA (RFC 6979)
Deterministic ECDSA uses RFC 6979 to derive the nonce deterministically from the message and private key, eliminating the risk of nonce reuse vulnerabilities. The same message and key always produce the same signature. Signatures are verifiable by standard ECDSA verifiers.
import java.security.*;
import java.security.spec.ECGenParameterSpec;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Generate key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", PROVIDER_NAME);
kpg.initialize(new ECGenParameterSpec("secp256r1"));
KeyPair keyPair = kpg.generateKeyPair();
// Sign with deterministic ECDSA
Signature signer = Signature.getInstance("SHA256withDetECDSA", PROVIDER_NAME);
signer.initSign(keyPair.getPrivate());
signer.update("Data to sign".getBytes());
byte[] signature = signer.sign();
// Signing again produces the same signature (deterministic)
signer.initSign(keyPair.getPrivate());
signer.update("Data to sign".getBytes());
byte[] signature2 = signer.sign();
assert java.util.Arrays.equals(signature, signature2);
// Verify (works with both DetECDSA and standard ECDSA verifiers)
Signature verifier = Signature.getInstance("SHA256withECDSA", PROVIDER_NAME);
verifier.initVerify(keyPair.getPublic());
verifier.update("Data to sign".getBytes());
boolean valid = verifier.verify(signature);
Available algorithms: SHA224withDetECDSA, SHA256withDetECDSA, SHA384withDetECDSA, SHA512withDetECDSA, SHA3-256withDetECDSA, SHA3-384withDetECDSA, SHA3-512withDetECDSA.
Nonce-Misuse Resistant Encryption (AES-GCM-SIV)
AES-GCM-SIV (RFC 8452) provides authenticated encryption that remains secure even if a nonce is accidentally reused. Unlike AES-GCM, nonce reuse only leaks whether the same plaintext was encrypted twice, without compromising authenticity. Requires OpenSSL 3.2+.
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import java.security.SecureRandom;
import java.security.Security;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Generate a key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();
// Generate 12-byte nonce
byte[] nonce = new byte[12];
new SecureRandom().nextBytes(nonce);
// Encrypt
Cipher cipher = Cipher.getInstance("AES_256/GCM-SIV/NoPadding", PROVIDER_NAME);
cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, nonce));
byte[] ciphertext = cipher.doFinal("Secret message".getBytes());
// Decrypt
cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(128, nonce));
byte[] plaintext = cipher.doFinal(ciphertext);
Available key sizes: AES_128/GCM-SIV/NoPadding, AES_192/GCM-SIV/NoPadding, AES_256/GCM-SIV/NoPadding.
Key Derivation (HKDF)
import javax.crypto.KDF;
import javax.crypto.SecretKey;
import javax.crypto.spec.HKDFParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Input keying material
byte[] ikm = "input-key-material".getBytes();
byte[] salt = "salt-value".getBytes();
byte[] info = "context-info".getBytes();
KDF hkdf = KDF.getInstance("HKDF-SHA256", PROVIDER_NAME);
SecretKey derived = hkdf.deriveKey("AES",
HKDFParameterSpec.expandOnly(new SecretKeySpec(ikm, "HKDF"), info, 32));
HMAC
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.Security;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
byte[] key = "secret-key".getBytes();
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256", PROVIDER_NAME);
mac.init(keySpec);
byte[] hmac = mac.doFinal("Message".getBytes());
Post-Quantum Key Encapsulation (ML-KEM)
Requires OpenSSL 3.5+.
import javax.crypto.KEM;
import java.security.*;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Generate ML-KEM key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM-768", PROVIDER_NAME);
KeyPair keyPair = kpg.generateKeyPair();
// Encapsulation (sender side)
KEM kem = KEM.getInstance("ML-KEM-768", PROVIDER_NAME);
KEM.Encapsulator encapsulator = kem.newEncapsulator(keyPair.getPublic());
KEM.Encapsulated encapsulated = encapsulator.encapsulate();
byte[] ciphertext = encapsulated.encapsulation();
SecretKey sharedSecretSender = encapsulated.key();
// Decapsulation (receiver side)
KEM.Decapsulator decapsulator = kem.newDecapsulator(keyPair.getPrivate());
SecretKey sharedSecretReceiver = decapsulator.decapsulate(ciphertext);
// Both parties now have the same shared secret
Post-Quantum Digital Signatures (ML-DSA)
Requires OpenSSL 3.5+.
import java.security.*;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Generate ML-DSA key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-DSA-65", PROVIDER_NAME);
KeyPair keyPair = kpg.generateKeyPair();
// Sign
Signature signer = Signature.getInstance("ML-DSA-65", PROVIDER_NAME);
signer.initSign(keyPair.getPrivate());
signer.update("Data to sign".getBytes());
byte[] signature = signer.sign();
// Verify
Signature verifier = Signature.getInstance("ML-DSA-65", PROVIDER_NAME);
verifier.initVerify(keyPair.getPublic());
verifier.update("Data to sign".getBytes());
boolean valid = verifier.verify(signature);
Hash-Based Signatures (LMS Verification)
LMS (Leighton-Micali Signature) is a stateful hash-based post-quantum signature scheme (RFC 8554 / NIST SP 800-208). GlaSSLess supports verification only -- signing and key generation are not supported because LMS is a stateful scheme where each private key can only sign a limited number of messages. Requires OpenSSL 3.6+.
import java.security.*;
import java.security.spec.X509EncodedKeySpec;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Load an LMS public key (X.509/SubjectPublicKeyInfo DER encoding)
byte[] publicKeyBytes = ...; // LMS public key in SPKI format
KeyFactory kf = KeyFactory.getInstance("LMS", PROVIDER_NAME);
PublicKey publicKey = kf.generatePublic(new X509EncodedKeySpec(publicKeyBytes));
// Verify an LMS signature
Signature verifier = Signature.getInstance("LMS", PROVIDER_NAME);
verifier.initVerify(publicKey);
verifier.update(message);
boolean valid = verifier.verify(signature);
|
NOTE
|
LMS keys are also registered under the aliases |
Hybrid Key Encapsulation (X25519MLKEM768)
Hybrid KEMs combine classical and post-quantum cryptography. Requires OpenSSL 3.5+.
import javax.crypto.KEM;
import java.security.*;
import net.glassless.provider.GlaSSLessProvider;
Security.addProvider(new GlaSSLessProvider());
// Server generates hybrid key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("X25519MLKEM768", PROVIDER_NAME);
KeyPair serverKeyPair = kpg.generateKeyPair();
// Client encapsulates shared secret using server's public key
KEM kem = KEM.getInstance("X25519MLKEM768", PROVIDER_NAME);
KEM.Encapsulator encapsulator = kem.newEncapsulator(serverKeyPair.getPublic());
KEM.Encapsulated encapsulated = encapsulator.encapsulate();
byte[] ciphertext = encapsulated.encapsulation(); // Send to server
SecretKey clientSecret = encapsulated.key(); // 64-byte shared secret
// Server decapsulates to recover the same shared secret
KEM.Decapsulator decapsulator = kem.newDecapsulator(serverKeyPair.getPrivate());
SecretKey serverSecret = decapsulator.decapsulate(ciphertext);
// Both parties now have identical shared secrets
|
NOTE
|
JDK 25's JSSE does not yet support hybrid named groups for TLS 1.3. See Post-Quantum Cryptography for workarounds and detailed documentation. |
TLS 1.3 Key Derivation
GlaSSLess provides TLS 1.3 KDF implementations for deriving traffic keys:
import javax.crypto.KDF;
import javax.crypto.SecretKey;
import net.glassless.provider.internal.kdf.TLS13KDFParameterSpec;
// Extract PRK from input key material
TLS13KDFParameterSpec extractParams = TLS13KDFParameterSpec
.forExtract(inputKeyMaterial, salt, 32)
.build();
KDF kdf = KDF.getInstance("TLS13-KDF-SHA256", PROVIDER_NAME);
byte[] prk = kdf.deriveData(extractParams);
// Expand to derive traffic key
TLS13KDFParameterSpec expandParams = TLS13KDFParameterSpec
.forExpand(prk, "key", handshakeHash, 16)
.build();
SecretKey trafficKey = kdf.deriveKey("AES", expandParams);
FIPS Mode
When OpenSSL is configured with FIPS mode enabled, GlaSSLess automatically detects this and excludes non-FIPS-approved algorithms from registration.
GlaSSLessProvider provider = new GlaSSLessProvider();
boolean fipsMode = provider.isFIPSMode();
System.out.println("FIPS Mode: " + (fipsMode ? "ENABLED" : "DISABLED"));