Cryptography
klyn.cryptography provides secure random generation, message digests, HMAC, PBKDF2,
authenticated AES encryption, and RSA encryption and signatures. Prefer the concrete algorithm
classes so security choices remain visible in source code.
| Goal | Recommended API |
|---|---|
| Random token, key, IV, or salt | SecureRandom or a key generator |
| Content fingerprint | SHA256, SHA512, or a SHA-3 digest |
| Authenticate a message with a shared secret | Hmac |
| Derive key material from a password | PBKDF2 and PBEKeySpec |
| Encrypt application data symmetrically | Cipher.aesGcmEncrypt() |
| Sign data with an RSA private key | RSAPSSSignature |
Base64 and hexadecimal only represent bytes as text. They provide no confidentiality, integrity, password protection, or authenticity.
import klyn.cryptography
random = SecureRandom()
csrfToken = random.nextUrlBase64(32)
salt = random.nextBase64(16)
identifier = random.nextHex(16)
print(csrfToken)
Sizes are expressed in random bytes before encoding. nextUrlBase64() is convenient for
URLs and cookies; nextHex() is convenient for identifiers. Never substitute
klyn.math.Random for this class.
import klyn.cryptography
digest = SHA256().digestInfo("hello")
print(digest.hex)
print(digest.base64)
assert digest.sizeBits == 256
fileDigest = SHA3_256().digestFileInfo("release.kar")
print(fileDigest.hex)
digest() returns raw Byte[]; digestInfo() returns a
Digest with hexadecimal and Base64 representations. update() accepts several
text chunks and the buffer is reset after the digest is produced.
MD5 and SHA1 remain available for compatibility checks, not for signatures,
password storage, certificates, or adversarial integrity. Prefer SHA-256, SHA-512, or SHA-3 for new
code.
import klyn.cryptography
mac = Hmac(SHA256())
mac.init("application-secret")
signature = mac.doFinal("payload")
verifier = Hmac(SHA256())
verifier.init("application-secret")
assert verifier.verify("payload", signature.hex)
The key encoding defaults to UTF-8 and may be set to hex, base64, or
base64url. Use independent secret keys for independent protocols; do not reuse an
encryption key as an HMAC key.
import klyn.cryptography
random = SecureRandom()
salt = random.nextBase64(16)
spec = PBEKeySpec(
"correct horse battery staple",
salt,
iterations=100000,
sizeBytes=32,
saltEncoding="base64"
)
derivedKey = PBKDF2(SHA256()).generateSecret(spec)
print(derivedKey)
Store the salt, iteration count, output size, and algorithm with the derived value. Salts are public and must be unique; passwords and derived keys are secrets. Select the iteration count from a measured security policy and raise it as deployment hardware evolves.
import klyn.cryptography
generator = AESKeyGenerator()
generator.initialize(256)
key = generator.generateKey()
payload = Cipher.aesGcmEncrypt(
"confidential text",
key,
aad="article:42"
)
plainText = Cipher.aesGcmDecrypt(
payload,
key,
aad="article:42"
)
assert plainText == "confidential text"
assert payload.authenticated
The generated key and payload fields are transport-safe strings. A random nonce is generated when no IV is supplied. AES-GCM authenticates both ciphertext and optional additional data; decryption fails if the key, nonce, tag, ciphertext, or AAD differs.
CBC and CTR modes are available for protocol compatibility but do not authenticate their ciphertext by themselves. Use GCM for new application formats unless an externally specified protocol requires another construction and supplies its own integrity protection.
import klyn.cryptography
generator = RSAKeyPairGenerator()
generator.initialize(2048)
keys = generator.generateKeyPair()
signer = RSAPSSSignature(SHA256())
signer.initSign(keys.privateKeyPem)
token = signer.sign("release manifest")
verifier = RSAPSSSignature(SHA256())
verifier.initVerify(keys.publicKeyPem)
assert verifier.verify(token, "release manifest")
RSA keys are returned in PEM format. RSA-PSS is the preferred signature mode for new formats;
RSAPKCS1Signature supports protocols that require PKCS#1 v1.5 signatures. The separate
Cipher.rsaEncrypt() API defaults to OAEP with SHA-256 and is intended for small payloads,
not bulk data.
import klyn.cryptography
base64 = Base64.encodeText("Klyn")
hex = Hex.encodeText("Klyn")
assert Base64.decodeToText(base64) == "Klyn"
assert Hex.decodeToText(hex) == "Klyn"
These helpers are text-oriented. Crypto result objects already expose appropriate encoded fields; avoid decoding arbitrary binary ciphertext as text.
- Keep private keys, passwords, and symmetric keys out of source control and logs.
- Use independent keys for encryption, MAC, signing, and separate application domains.
- Never reuse an AES-GCM nonce with the same key.
- Authenticate before acting on decrypted or received data.
- Preserve the original
CryptoExceptionwhen an operation fails; do not return unauthenticated fallback data. - Rotate keys and version encrypted formats so older data can be migrated deliberately.