
Pure constant-time cryptographic primitives with per-primitive native fallback, NIST CAVP/Wycheproof verification, compile-time constant-time lint, timing harness, typed keys and no-throw API.
MeshLink-crypto provides pure-Kotlin, constant-time cryptographic primitives for Kotlin Multiplatform, with per-primitive native fallback.
MeshLink-crypto provides twelve RFC/FIPS-standard cryptographic primitives as pure-Kotlin, constant-time implementations. Each primitive also has a native fallback path. The library selects per-primitive at each call site. Callers never choose a provider. ML-DSA-44 (FIPS 204) is implemented as pure-Kotlin only — native integration is pending.
The library targets JVM, Android (API 21+), and iOS (arm64 + simulator). JS and WebAssembly targets are out of scope. Built with Kotlin 2.4.10.
| Primitive | RFC | Pure-K | Native fallback |
|---|---|---|---|
| SHA-256 | RFC 6234 §5.1 | Yes | JCA, CommonCrypto |
| SHA-512 | RFC 6234 §5.2 | Yes | JCA, CommonCrypto |
| SHA3-256 | FIPS 202 §6.1 | Yes | JCA (JDK 9+, API 28+); Pure-K (iOS) |
| SHA3-512 | FIPS 202 §6.2 | Yes | JCA (JDK 9+, API 28+); Pure-K (iOS) |
| HMAC-SHA256 | RFC 2104 | Yes | JCA Mac, CCHmac |
| HKDF-SHA256 | RFC 5869 | Yes | Platform HMAC |
| X25519 | RFC 7748 §5 | Yes | JCA KeyAgreement, Security.framework |
| Ed25519 | RFC 8032 §5.1 | Yes | JCA Signature, Security.framework |
| ChaCha20-Poly1305 | RFC 8439 | Yes | JCA Cipher, CryptoKit (iOS) |
| SHAKE256 | FIPS 202 §8.4 | Yes | Pure-K only (no native) |
| SHAKE128 | FIPS 202 §8.3 | Yes | Pure-K only (no native) |
| ML-DSA-44 | FIPS 204 §7 | Yes | Pure-K only (in development) |
| ML-KEM-512 | FIPS 203 | Yes | Pure-K only (Wycheproof-verified) |
The library has three layers of dispatch, per primitive:
java.security, javax.crypto).The pure-Kotlin path is the only code that holds secrets and is authored in-house. It is held to three verification gates:
hashlib and cross-checked with the XKCP reference implementation).ConstantTimeRule) that bans data-dependent branches and secret-indexed array access at compile time.See Architecture for the full design and Constant-Time Discipline for the security model.
| Reference | URL | Purpose in this repo |
|---|---|---|
| FIPS 202 | NIST FIPS 202 standard | Defines SHA-3, SHAKE128 (§8.3), SHAKE256 (§8.4) — the spec for our Keccak/XOF primitives |
| NIST CAVP | Cryptographic Algorithm Validation Program | Known Answer Test vectors for SHAKE128/SHAKE256 — correctness oracle for primitives without a Wycheproof corpus |
| XKCP / Keccak Team | eXtending Keccak Code Package | Reference implementation for Keccak-f[1600] round constants, rotation constants, and SimpleFIPS202.c — our implementation is verified byte-identical to XKCP parameters |
| Wycheproof | Google's crypto test-vector corpus | Correctness oracle for primitives with a corpus: AES-GCM, Ed25519, HKDF-SHA256, HMAC-SHA256, X25519, ChaCha20-Poly1305, ML-DSA-44, ML-KEM-512 |
Python hashlib |
Python standard library | Cross-check reference: SHAKE128/SHAKE256 outputs verified against hashlib.shake_128/shake_256 (FIPS 202-compliant, byte-identical to CAVP) |
| RFC 6234 | SHA-2 Hashed Data | Defines SHA-256 (§5.1) and SHA-512 (§5.2) — our SHA-2 implementations |
| RFC 2104 | HMAC | Defines HMAC-SHA256 — our HMAC implementation |
| RFC 5869 | HKDF | Defines HKDF-SHA256 (Extract + Expand) — our KDF implementation |
| RFC 7748 | Curve25519 / X25519 | Defines X25519 key agreement — our key exchange primitive |
| RFC 8032 | EdDSA | Defines Ed25519 signing — our signature primitive |
| RFC 8439 | ChaCha20/Poly1305 | Defines ChaCha20-Poly1305 AEAD — our encryption primitive |
| FIPS 204 | ML-DSA (CRYSTALS-Dilithium) | Defines ML-DSA-44 post-quantum signature scheme — our post-quantum signature primitive |
| FIPS 203 | ML-KEM (CRYSTALS-Kyber) | Defines ML-KEM-512 key-encapsulation mechanism — our post-quantum KEM primitive |
| FIPS 203 | ML-KEM (CRYSTALS-Kyber) | Defines ML-KEM-512/768/1024 key-encapsulation mechanisms — referenced for future PQC KEM support; spec stored in docs/rfcs/crypto/fips203.pdf
|
| RFC 9688 | SHA3 in CMS | Use of SHA3 one-way hash functions in CMS — reference for SHA3 integration (not yet implemented) |
| RFC 9180 | HPKE | Hybrid Public Key Encryption — reference for PQC KEM integration (HPKE-ML-KEM, not yet implemented) |
| RFC 9629 | KEM in CMS | Using Key Encapsulation Mechanism (KEM) Algorithms in CMS — reference for future PQC KEM support |
| RFC 9861 | KangarooTwelve / TurboSHAKE | Defines KangarooTwelve and TurboSHAKE XOFs based on Keccak — reference for Keccak family extensions |
| RFC 9794 | PQ hybrid terminology | Terminology for post-quantum traditional hybrid schemes — reference for PQ transition design |
| RFC 9958 | PQC for engineers | Practical guidance on post-quantum cryptography deployment — engineering reference |
import ch.trancee.meshlink.crypto.Crypto
import ch.trancee.meshlink.crypto.SecretKey
// Sample data (replace with your own key material)
val ikm = ByteArray(32) { 0x01 } // input keying material
val salt = ByteArray(16) { 0x00 } // public salt (empty is also valid)
val info = byteArrayOf(0x01, 0x02) // public context string
val plaintext = "Hello, world!".encodeToByteArray()
// Hash — RFC 6234
val digest = Crypto.sha256(plaintext).getOrThrow()
// Derive a session key with HKDF — RFC 5869
val sessionKey = Crypto.hkdfSha256(ikm, salt, info, outputLength = 32).getOrThrow()
// Encrypt — ChaCha20-Poly1305 (RFC 8439). Nonce is generated internally.
SecretKey(sessionKey).use { key ->
val encrypted = Crypto.chacha20Poly1305Encrypt(key, plaintext).getOrThrow()
// encrypted = nonce(12) || ciphertext || tag(16)
val decrypted = Crypto.chacha20Poly1305Decrypt(key, encrypted).getOrThrow()
}See How to Get Started for adding the dependency to your project.
@Secret, the detekt rule, and the timing harness./gradlew check --rerun-tasks --no-build-cache locally.Code of conduct: be respectful. Security issues are reported via SECURITY.md.
See LICENSE.
MeshLink-crypto provides pure-Kotlin, constant-time cryptographic primitives for Kotlin Multiplatform, with per-primitive native fallback.
MeshLink-crypto provides twelve RFC/FIPS-standard cryptographic primitives as pure-Kotlin, constant-time implementations. Each primitive also has a native fallback path. The library selects per-primitive at each call site. Callers never choose a provider. ML-DSA-44 (FIPS 204) is implemented as pure-Kotlin only — native integration is pending.
The library targets JVM, Android (API 21+), and iOS (arm64 + simulator). JS and WebAssembly targets are out of scope. Built with Kotlin 2.4.10.
| Primitive | RFC | Pure-K | Native fallback |
|---|---|---|---|
| SHA-256 | RFC 6234 §5.1 | Yes | JCA, CommonCrypto |
| SHA-512 | RFC 6234 §5.2 | Yes | JCA, CommonCrypto |
| SHA3-256 | FIPS 202 §6.1 | Yes | JCA (JDK 9+, API 28+); Pure-K (iOS) |
| SHA3-512 | FIPS 202 §6.2 | Yes | JCA (JDK 9+, API 28+); Pure-K (iOS) |
| HMAC-SHA256 | RFC 2104 | Yes | JCA Mac, CCHmac |
| HKDF-SHA256 | RFC 5869 | Yes | Platform HMAC |
| X25519 | RFC 7748 §5 | Yes | JCA KeyAgreement, Security.framework |
| Ed25519 | RFC 8032 §5.1 | Yes | JCA Signature, Security.framework |
| ChaCha20-Poly1305 | RFC 8439 | Yes | JCA Cipher, CryptoKit (iOS) |
| SHAKE256 | FIPS 202 §8.4 | Yes | Pure-K only (no native) |
| SHAKE128 | FIPS 202 §8.3 | Yes | Pure-K only (no native) |
| ML-DSA-44 | FIPS 204 §7 | Yes | Pure-K only (in development) |
| ML-KEM-512 | FIPS 203 | Yes | Pure-K only (Wycheproof-verified) |
The library has three layers of dispatch, per primitive:
java.security, javax.crypto).The pure-Kotlin path is the only code that holds secrets and is authored in-house. It is held to three verification gates:
hashlib and cross-checked with the XKCP reference implementation).ConstantTimeRule) that bans data-dependent branches and secret-indexed array access at compile time.See Architecture for the full design and Constant-Time Discipline for the security model.
| Reference | URL | Purpose in this repo |
|---|---|---|
| FIPS 202 | NIST FIPS 202 standard | Defines SHA-3, SHAKE128 (§8.3), SHAKE256 (§8.4) — the spec for our Keccak/XOF primitives |
| NIST CAVP | Cryptographic Algorithm Validation Program | Known Answer Test vectors for SHAKE128/SHAKE256 — correctness oracle for primitives without a Wycheproof corpus |
| XKCP / Keccak Team | eXtending Keccak Code Package | Reference implementation for Keccak-f[1600] round constants, rotation constants, and SimpleFIPS202.c — our implementation is verified byte-identical to XKCP parameters |
| Wycheproof | Google's crypto test-vector corpus | Correctness oracle for primitives with a corpus: AES-GCM, Ed25519, HKDF-SHA256, HMAC-SHA256, X25519, ChaCha20-Poly1305, ML-DSA-44, ML-KEM-512 |
Python hashlib |
Python standard library | Cross-check reference: SHAKE128/SHAKE256 outputs verified against hashlib.shake_128/shake_256 (FIPS 202-compliant, byte-identical to CAVP) |
| RFC 6234 | SHA-2 Hashed Data | Defines SHA-256 (§5.1) and SHA-512 (§5.2) — our SHA-2 implementations |
| RFC 2104 | HMAC | Defines HMAC-SHA256 — our HMAC implementation |
| RFC 5869 | HKDF | Defines HKDF-SHA256 (Extract + Expand) — our KDF implementation |
| RFC 7748 | Curve25519 / X25519 | Defines X25519 key agreement — our key exchange primitive |
| RFC 8032 | EdDSA | Defines Ed25519 signing — our signature primitive |
| RFC 8439 | ChaCha20/Poly1305 | Defines ChaCha20-Poly1305 AEAD — our encryption primitive |
| FIPS 204 | ML-DSA (CRYSTALS-Dilithium) | Defines ML-DSA-44 post-quantum signature scheme — our post-quantum signature primitive |
| FIPS 203 | ML-KEM (CRYSTALS-Kyber) | Defines ML-KEM-512 key-encapsulation mechanism — our post-quantum KEM primitive |
| FIPS 203 | ML-KEM (CRYSTALS-Kyber) | Defines ML-KEM-512/768/1024 key-encapsulation mechanisms — referenced for future PQC KEM support; spec stored in docs/rfcs/crypto/fips203.pdf
|
| RFC 9688 | SHA3 in CMS | Use of SHA3 one-way hash functions in CMS — reference for SHA3 integration (not yet implemented) |
| RFC 9180 | HPKE | Hybrid Public Key Encryption — reference for PQC KEM integration (HPKE-ML-KEM, not yet implemented) |
| RFC 9629 | KEM in CMS | Using Key Encapsulation Mechanism (KEM) Algorithms in CMS — reference for future PQC KEM support |
| RFC 9861 | KangarooTwelve / TurboSHAKE | Defines KangarooTwelve and TurboSHAKE XOFs based on Keccak — reference for Keccak family extensions |
| RFC 9794 | PQ hybrid terminology | Terminology for post-quantum traditional hybrid schemes — reference for PQ transition design |
| RFC 9958 | PQC for engineers | Practical guidance on post-quantum cryptography deployment — engineering reference |
import ch.trancee.meshlink.crypto.Crypto
import ch.trancee.meshlink.crypto.SecretKey
// Sample data (replace with your own key material)
val ikm = ByteArray(32) { 0x01 } // input keying material
val salt = ByteArray(16) { 0x00 } // public salt (empty is also valid)
val info = byteArrayOf(0x01, 0x02) // public context string
val plaintext = "Hello, world!".encodeToByteArray()
// Hash — RFC 6234
val digest = Crypto.sha256(plaintext).getOrThrow()
// Derive a session key with HKDF — RFC 5869
val sessionKey = Crypto.hkdfSha256(ikm, salt, info, outputLength = 32).getOrThrow()
// Encrypt — ChaCha20-Poly1305 (RFC 8439). Nonce is generated internally.
SecretKey(sessionKey).use { key ->
val encrypted = Crypto.chacha20Poly1305Encrypt(key, plaintext).getOrThrow()
// encrypted = nonce(12) || ciphertext || tag(16)
val decrypted = Crypto.chacha20Poly1305Decrypt(key, encrypted).getOrThrow()
}See How to Get Started for adding the dependency to your project.
@Secret, the detekt rule, and the timing harness./gradlew check --rerun-tasks --no-build-cache locally.Code of conduct: be respectful. Security issues are reported via SECURITY.md.
See LICENSE.