Pure-MoonBit crypto primitives: SHA-1/2 (incl. SHA-512/224/256), SHA-3, Keccak-256, SHAKE/cSHAKE, BLAKE2b/BLAKE2s/BLAKE3 (+keyed), RIPEMD-160, HMAC/Poly1305/CMAC/KMAC/GMAC, AES-CBC/GCM/CTR/CCM/KW/SIV, ChaCha20/XChaCha20 + Salsa20, HKDF/PBKDF2/scrypt/Argon2, RSA (PKCS1-v1.5/OAEP/PSS), ECDSA P-256, Ed25519/Ed25519ctx/Ed25519ph, X25519, HOTP/TOTP (SHA-1/256/512), SipHash, CRC32/CRC32C/CRC-64/Adler-32, Base64/Hex, sealed-box envelope, Chinese national (GM) cryptography: SM2/SM3/SM4 and ZUC-128/ZUC-256 with 128-EEA3/128-EIA3 (3GPP TS 35.221/222/223), post-quantum: ML-KEM/ML-DSA/SLH-DSA (FIPS 203/204/205), LMS/HSS, XMSS/XMSS^MT, Falcon-512/1024
The implementations are correct and tested but have not been formally audited. See Security & performance boundaries.
git remote add gitlink https://www.gitlink.org.cn/CC01/mooncry_mirror.git
git push gitlink mastermoon add cc06b/mooncrymoon new myapp
cd myapp
moon add cc06b/mooncryimport {
"cc06b/mooncry/lib",
}
pkgtype(kind: "executable")fn main {
// SHA-256 one-shot
let digest = @lib.sha256(b"Hello, world!")
println("SHA-256: " + @lib.bytes_to_hex(digest))
// AES-GCM round-trip (256-bit key, 96-bit nonce, with AAD)
let key = Bytes::make(32, b'\x00')
let iv = Bytes::make(12, b'\x00')
let (ciphertext, tag) = @lib.aes_gcm_encrypt(b"secret data", key, iv, b"aad")
let (plaintext, ok) = @lib.aes_gcm_decrypt(ciphertext, key, iv, b"aad", tag)
let status = if ok { "OK" } else { "FAIL" }
println("AES-GCM round-trip: " + status)
println("Recovered: " + @lib.bytes_to_hex(plaintext))
// Sealed-box envelope: HKDF-SHA256 derives the AES-256-GCM key from a
// master key + context, then encrypts into a versioned envelope.
let master = Bytes::make(32, b'\x07')
let nonce = Bytes::make(12, b'\x01')
let envelope = @lib.sealed_box_seal(master, nonce, b"plaintext", b"aad", b"tenant-1")
match @lib.sealed_box_open(master, envelope, b"aad", b"tenant-1") {
Ok(pt) => println("Sealed box: " + @lib.bytes_to_hex(pt))
Err(msg) => println("Sealed box failed: " + msg)
}
}moon run cmd/mainSHA-256: 315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3
AES-GCM round-trip: OK
Recovered: 7365637265742064617461| Function | Description |
|---|---|
| md5(data : Bytes) -> Bytes | MD5 one-shot, 16-byte digest |
| sha224 / sha256 / sha384 / sha512(data : Bytes) -> Bytes | SHA-2 family (FIPS 180-4) |
| sha512_224 / sha512_256(data : Bytes) -> Bytes | SHA-512/224 / SHA-512/256 (FIPS 180-4 §5.3.6) |
| ripemd160(data : Bytes) -> Bytes | RIPEMD-160, 20-byte digest |
| sha3_224 / sha3_256 / sha3_384 / sha3_512(data : Bytes) -> Bytes | SHA-3 (FIPS 202) |
| keccak_256(data : Bytes) -> Bytes | Keccak-256 (legacy 0x01 padding, Ethereum), 32 bytes |
| shake_128 / shake_256(data : Bytes, out_len : Int) -> Bytes | SHAKE XOF, out_len bytes |
| cshake_128 / cshake_256(data, n, s : Bytes, out_len : Int) -> Bytes | cSHAKE (SP 800-185); N=S="" ⇒ SHAKE |
| kmac_128 / kmac_256(key, data, s : Bytes, out_len : Int) -> Bytes | KMAC fixed-length MAC (SP 800-185) |
| kmac_xof_128 / kmac_xof_256(key, data, s : Bytes, out_len : Int) -> Bytes | KMACXOF variable-length variant |
| blake2b(data : Bytes, out_len : Int) -> Bytes | BLAKE2b (RFC 7693), out_len 1..64 |
| blake2b_keyed(data, key : Bytes, out_len : Int) -> Bytes | keyed BLAKE2b (MAC), key 1..64 |
| blake2s(data : Bytes, out_len : Int) -> Bytes | BLAKE2s (RFC 7693), out_len 1..32 |
| blake2s_keyed(data, key : Bytes, out_len : Int) -> Bytes | keyed BLAKE2s (MAC), key 1..32 |
| blake3(data : Bytes) -> Bytes | BLAKE3, 32-byte digest |
| blake3_xof(data : Bytes, out_len : Int) -> Bytes | BLAKE3 XOF (arbitrary-length) |
| sm3(data : Bytes) -> Bytes | SM3 (GB/T 32905), 32-byte digest |
| sm3_new() / sm3_update(h, data) / sm3_finalize(h) | SM3 streaming hasher |
| sm3_clone(h) -> Sm3Hasher | Deep-copy an SM3 hasher (prefix reuse) |
| sm4_encrypt(key, block) / sm4_decrypt(key, block) | SM4 (GB/T 32907) single-block with a 16-byte key |
| sm4_expand_key(key) + sm4_encrypt_block(rk, data, off) / sm4_decrypt_block(rk, data, off) | SM4 with reusable round keys; rk must be the 32 words sm4_expand_key returns and off must leave a whole 16-byte block in data |
| sm2_public_key(sk) -> Bytes | SM2 public key (uncompressed 65 bytes) from a 32-byte secret key |
| sm2_sign(sk, msg, id, rand) -> Bytes | SM2 signature (r||s, 64 bytes); rand(32) supplies the nonce k |
| sm2_sign_with_k(sk, msg, id, k) -> Bytes | SM2 sign with explicit nonce (deterministic; aborts on degenerate k) |
| sm2_verify(pk, msg, id, sig) -> Bool | SM2 verify (rejects off-curve keys and out-of-range r/s) |
| sm4_ctr(key, iv, data) / sm4_cbc_encrypt / sm4_cbc_decrypt | SM4 modes (CTR 128-bit BE counter; CBC raw, no padding) |
| sm4_gcm_encrypt(pt, key, iv, aad) / sm4_gcm_decrypt(ct, key, iv, aad, tag) | SM4-GCM AEAD (12-byte IV, 16-byte tag; RFC 8998 TLS building block) |
| zuc_init(key, iv) -> ZucState / zuc_next_word(st) | ZUC-128 core: 16-byte key/IV, then one 32-bit keystream word per call |
| zuc_keystream(key, iv, nwords) -> Bytes | ZUC-128 keystream as 4*nwords big-endian bytes |
| zuc_xor(key, iv, data) -> Bytes | ZUC-128 in raw stream mode (any length, no padding); not the 3GPP mode |
| zuc_eea3_encrypt(key, count, bearer, direction, nbits, data) / zuc_eea3_decrypt | 128-EEA3 (TS 35.222, f8) over an exact bit length; count : UInt, bearer 0..31, direction 0/1 |
| zuc_eia3_mac(key, count, bearer, direction, nbits, data) -> Bytes | 128-EIA3 (TS 35.223, f9): 4-byte big-endian MAC-I |
| zuc_eia3_verify(key, count, bearer, direction, nbits, data, mac) -> Bool | Constant-time MAC-I check; false (not a trap) on a wrong-length tag |
| zuc256_init(key, iv) -> ZucState / zuc256_keystream(key, iv, nwords) / zuc256_xor(key, iv, data) | ZUC-256 (32-byte key, 23-byte IV) — same engine as ZUC-128, different key schedule |
| zuc256_mac(key, iv, macbits, nbits, data) -> Bytes | ZUC-256 MAC with a 32/64/128-bit tag over an exact bit length |
| zuc256_mac_verify(key, iv, macbits, nbits, data, mac) -> Bool | Constant-time check; false (not a trap) on a wrong-length tag |
| hmac_sm3(key, msg) -> Bytes | HMAC-SM3 (RFC 2104, 64-byte block, 32-byte MAC) |
| sm2_encrypt(pk, msg, rand) / sm2_encrypt_with_k(pk, msg, k) | SM2 encryption (GB/T 32918.4), raw C1||C3||C2; sm2_encrypt_or / sm2_encrypt_with_k_or for a peer-supplied pk |
| sm2_decrypt(sk, ct) -> (Bytes, Bool) | SM2 decryption (false on tamper/wrong key, GCM convention) |
| sm2_ct_to_der(ct) / sm2_ct_from_der(der) | openssl-compatible ASN.1 DER ciphertext conversion; the decoder is strict DER (see below), and sm2_ct_to_der_or reports a malformed raw ciphertext instead of aborting |
| sm2_sig_to_der(sig) / sm2_sig_from_der(der) | SM2 signature raw r||s DER SEQUENCE{r,s}; the decoder is strict DER (see below), sm2_sig_to_der_or never traps |
| hkdf_sm3(ikm, salt, info, out_len) / hkdf_sm3_extract / hkdf_sm3_expand | HKDF-SM3 (RFC 5869) |
| pbkdf2_sm3(password, salt, iterations, dk_len) | PBKDF2-HMAC-SM3 (RFC 2898) |
| sm2_sk_to_pem / sm2_sk_from_pem / sm2_pk_to_pem / sm2_pk_from_pem | SM2 key PEM (PKCS#8 / SPKI, openssl-identical); sm2_pk_to_pem_or for a peer-supplied point |
| sm2_sk_to_pkcs8_der / sm2_pkcs8_der_to_sk / sm2_pk_to_spki_der / sm2_spki_der_to_pk | SM2 key DER forms; sm2_pk_to_spki_der_or never traps on a malformed point |
| sm2_seal(pk, msg, rand) / sm2_open(sk, env) | SM2 sealed envelope: enc_key(125)||iv(12)||SM4-GCM ct||tag(16); sm2_seal_or never traps on a bad pk |
| hmac_sha256 / hmac_sha512(key, msg : Bytes) -> Bytes | HMAC (RFC 2104) |
| hmac_sha3_256 / hmac_sha3_512(key, msg : Bytes) -> Bytes | HMAC over SHA-3 (RFC 2104 + FIPS 202) |
| hmac_sha3_224 / hmac_sha3_384(key, msg : Bytes) -> Bytes | HMAC over SHA3-224/384 (RFC 2104 + FIPS 202) |
| poly1305(key, msg : Bytes) -> Bytes | Poly1305 MAC (RFC 8439), 16-byte tag |
| cmac_aes(data, key : Bytes) -> Bytes | AES-CMAC (NIST SP 800-38B), 16-byte tag |
| aes_encrypt_cbc / aes_decrypt_cbc(data, key, iv) -> Bytes | AES-CBC (IV prepended, PKCS#7) |
| aes_gcm_encrypt(pt, key, iv, aad) -> (Bytes, Bytes) | AES-GCM encrypt → (ct, 16-byte tag) |
| aes_gcm_decrypt(ct, key, iv, aad, tag) -> (Bytes, Bool) | AES-GCM decrypt, constant-time tag verify |
| aes_ccm_encrypt(pt, key, nonce, aad, mac_len) -> Bytes | AES-CCM AEAD (SP 800-38C) → ct ‖ tag |
| aes_ccm_decrypt(input, key, nonce, aad, mac_len) -> Bytes | AES-CCM decrypt, aborts on tag mismatch |
| gmac(key, iv, aad) -> Bytes | GMAC (SP 800-38D), 16-byte tag |
| gmac_verify(key, iv, aad, tag) -> Bool | GMAC constant-time tag verify |
| gmac_new(key, iv) -> GmacState | Incremental GMAC (chunked AAD, 12-byte IV) |
| gmac_new_iv(key, iv) -> GmacState | Incremental GMAC, any IV length (SP 800-38D) |
| gmac_update(st, aad_chunk) | Feed an AAD chunk |
| gmac_finalize(st) -> Bytes | Incremental GMAC 16-byte tag |
| gmac_iv(key, iv, aad) -> Bytes | GMAC with any IV length (SP 800-38D) |
| gmac_iv_verify(key, iv, aad, tag) -> Bool | GMAC any-IV constant-time verify |
| gmac_stream_verify(key, iv, aad, tag) -> Bool | Constant-time check of a 16-byte tag produced by the incremental GMAC |
| aes_ctr(data, key, iv) -> Bytes | AES-CTR encrypt/decrypt (symmetric) |
| aes_kw_wrap(kek, key_data) -> Bytes / aes_kw_unwrap(kek, wrapped) -> Result[Bytes, String] | AES Key Wrap (RFC 3394): wrap returns the 8·(n+1)-byte IV ‖ blocks; unwrap is Err on an integrity failure |
| aes_siv_encrypt(key, plaintext, ads : Array[Bytes]) -> Bytes / aes_siv_decrypt(envelope, key, ads) -> Result[Bytes, String] | AES-SIV (RFC 5297), nonce-misuse-resistant; key 32/48/64 bytes, output is IV(16) ‖ ct, and ads is the vector of associated-data strings |
| chacha20_xor(input, key, nonce, counter) -> Bytes | ChaCha20 encrypt/decrypt (symmetric) |
| salsa20_keystream_block(key, nonce, counter) -> Bytes | Salsa20 keystream block (64 bytes) |
| salsa20_xor(key, nonce, counter, data) -> Bytes | Salsa20 stream cipher encrypt/decrypt (symmetric) |
| chacha20_poly1305_encrypt(key, nonce, aad, pt) -> Bytes | ChaCha20-Poly1305 AEAD → ct ‖ tag |
| chacha20_poly1305_decrypt(key, nonce, aad, input) -> Bytes | AEAD decrypt, aborts on tag mismatch |
| hchacha20(key, in16 : Bytes) -> Bytes | HChaCha20 subkey derivation (draft-irtf-cfrg-xchacha §2.2) |
| xchacha20_xor(input, key, nonce24, counter) -> Bytes | XChaCha20 stream cipher, 24-byte nonce (symmetric) |
| xchacha20_poly1305_encrypt(key, nonce24, aad, pt) -> Bytes | XChaCha20-Poly1305 AEAD → ct ‖ tag |
| xchacha20_poly1305_decrypt(key, nonce24, aad, input) -> Bytes | XChaCha20-Poly1305 AEAD decrypt, aborts on tag mismatch |
| hotp(key, counter, digits) / hotp_sha256 / hotp_sha512(...) -> String | HOTP (RFC 4226) with HMAC-SHA1/256/512; digits 1..=9 (the RFC recommends 6..=8) |
| totp(key, unix_time, step, digits) / totp_sha256 / totp_sha512(...) -> String | TOTP (RFC 6238); step in seconds ≥ 1, digits 1..=9 |
| ed25519ctx_sign(seed, msg, ctx) / ed25519ctx_verify(pk, msg, sig, ctx) | Ed25519ctx (RFC 8032), ctx 1..255 bytes |
| ed25519ph_sign(seed, msg, ctx) / ed25519ph_verify(pk, msg, sig, ctx) | Ed25519ph (RFC 8032), SHA-512 prehash |
| ed25519ph_sign_hashed(seed, ph_hash, ctx) / ed25519ph_verify_hashed(pk, ph_hash, sig, ctx) | the same, when the caller already holds the 64-byte SHA-512 prehash |
| adler32(data : Bytes) -> Bytes | Adler-32 (RFC 1950), 4-byte big-endian |
| hkdf_sha256(salt, ikm, info, len) -> Bytes | HKDF-SHA256 (RFC 5869) |
| hkdf_sha512(salt, ikm, info, len) -> Bytes | HKDF-SHA512 (RFC 5869) |
| pbkdf2_hmac_sha256(password, salt, iterations, len) -> Bytes | PBKDF2-HMAC-SHA256 (RFC 8018) |
| pbkdf2_hmac_sha512(password, salt, iterations, len) -> Bytes | PBKDF2-HMAC-SHA512 (RFC 8018) |
| pbkdf2_hmac_sha1(password, salt, iterations, len) -> Bytes | PBKDF2-HMAC-SHA1 (RFC 8018) |
| hkdf_sha3_256(salt, ikm, info, len) -> Bytes | HKDF-SHA3-256 (RFC 5869 over FIPS 202) |
| pbkdf2_hmac_sha3_256(password, salt, iterations, len) -> Bytes | PBKDF2-HMAC-SHA3-256 (RFC 8018 over FIPS 202) |
| scrypt(password, salt, n, r, p, dklen) -> Bytes | scrypt memory-hard KDF (RFC 7914), n power of two |
| argon2id(password, salt, t_cost, m_cost, parallelism, hash_len) -> Bytes | Argon2id (RFC 9106), the recommended variant |
| argon2(…, type) / argon2i(…) / argon2d(…) | the generic form with an explicit type (0 = d, 1 = i, 2 = id) and the two pure variants |
| rsa_pkcs1_v15_encrypt(msg, n, e, rand_ps) -> Bytes | RSAES-PKCS1-v1.5 encrypt (RFC 8017 §7.2); rand_ps must be k−msglen−3 nonzero bytes |
| rsa_pkcs1_v15_encrypt_or(msg, n, e, rand_ps) -> Result[Bytes, String] | same, reporting a degenerate peer modulus / a zero byte in rand_ps as Err |
| rsa_pkcs1_v15_decrypt(ct, n, d) -> Bytes | RSAES-PKCS1-v1.5 decrypt |
| rsa_pkcs1_v15_sign(msg, n, d) -> Bytes | RSASSA-PKCS1-v1.5 sign (SHA-256) |
| rsa_pkcs1_v15_verify(msg, sig, n, e) -> Bool | RSASSA-PKCS1-v1.5 verify |
| rsa_oaep_encrypt(msg, n, e, seed, label) -> Bytes | RSAES-OAEP encrypt (SHA-256) |
| rsa_oaep_decrypt(ct, n, d, label) -> Bytes | RSAES-OAEP decrypt |
| rsa_oaep_encrypt_with(msg, n, e, seed, label, hash) -> Bytes | OAEP encrypt, chosen hash + MGF1 |
| rsa_oaep_encrypt_or / rsa_oaep_encrypt_with_or | the two above as Result: a peer modulus < 2 or a message too long for it is an Err, not a trap |
| rsa_oaep_decrypt_with(ct, n, d, label, hash) -> Bytes | OAEP decrypt, chosen hash |
| rsa_pss_sign(msg, n, d, salt) -> Bytes | RSASSA-PSS sign (SHA-256) |
| rsa_pss_verify(msg, sig, n, e, salt_len) -> Bool | RSASSA-PSS verify |
| rsa_pkcs1_v15_sign_crt(msg, p, q, dp, dq, qinv) -> Bytes | PKCS1-v1.5 sign via CRT (~2.6x, byte-identical) |
| rsa_pkcs1_v15_decrypt_crt(ct, p, q, dp, dq, qinv) -> Bytes | PKCS1-v1.5 decrypt via CRT |
| rsa_oaep_decrypt_crt(ct, p, q, dp, dq, qinv, label) -> Bytes | OAEP decrypt via CRT |
| rsa_pss_sign_crt(msg, p, q, dp, dq, qinv, salt) -> Bytes | PSS sign via CRT |
| rsa_pkcs1_v15_sign_with(msg, n, d, hash) -> Bytes | PKCS1-v1.5 sign, hash = SHA-1/256/384/512 |
| rsa_pkcs1_v15_verify_with(msg, sig, n, e, hash) -> Bool | PKCS1-v1.5 verify, chosen hash |
| rsa_pss_sign_with(msg, n, d, salt, hash) -> Bytes | PSS sign, chosen hash + MGF1 |
| rsa_pss_verify_with(msg, sig, n, e, salt_len, hash) -> Bool | PSS verify, chosen hash |
| rsa_pkcs1_v15_sign_with_crt(msg, p, q, dp, dq, qinv, hash) -> Bytes | v1.5 sign, CRT + chosen hash |
| rsa_pss_sign_with_crt(msg, p, q, dp, dq, qinv, salt, hash) -> Bytes | PSS sign, CRT + chosen hash |
| ed25519_public_key(seed) -> Bytes | Derive 32-byte Ed25519 public key |
| ed25519_sign(seed, message) -> Bytes | Ed25519 sign (RFC 8032), 64-byte sig |
| ed25519_verify(public_key, message, sig) -> Bool | Ed25519 verify |
| ecdsa_p256_public_key(sk) -> Bytes | ECDSA P-256 public key (uncompressed) |
| ecdsa_p256_sign(sk, message) -> Bytes | ECDSA P-256 sign (RFC 6979, SHA-256) |
| ecdsa_p256_sign_low_s(sk, message) -> Bytes | P-256 sign, low-S canonical (WebCrypto) |
| ecdsa_p256_verify(pk, message, sig) -> Bool | ECDSA P-256 verify |
| ecdsa_secp256k1_public_key(sk) -> Bytes | ECDSA secp256k1 public key (uncompressed) |
| ecdsa_secp256k1_sign(sk, message) -> Bytes | ECDSA secp256k1 sign (RFC 6979, SHA-256) |
| ecdsa_secp256k1_sign_low_s(sk, message) -> Bytes | secp256k1 sign, BIP-62 low-S canonical |
| ecdsa_secp256k1_verify(pk, message, sig) -> Bool | ECDSA secp256k1 verify |
| x25519(scalar, u) -> Bytes | X25519 scalar mult (RFC 7748), DH shared secret |
| x25519_or(scalar, u) -> Result[Bytes, String] | X25519 without aborting on a wrong-length peer share |
| dh_shared_is_zero(shared) -> Bool | True for the all-zero X25519/X448 output a low-order peer point produces (RFC 7748 §6.1) — never use that as a key |
| x25519_public_key(private_key) -> Bytes | Derive X25519 public key (base u=9) |
| ed448_public_key(seed) -> Bytes | Derive 57-byte Ed448 public key |
| ed448_sign(seed, message) -> Bytes | Ed448 sign (RFC 8032), 114-byte sig |
| ed448_sign_ctx(seed, message, ctx) -> Bytes | Ed448 sign with context |
| ed448_verify(pk, message, sig) -> Bool | Ed448 verify (cofactor equation) |
| ed448_verify_ctx(pk, message, sig, ctx) -> Bool | Ed448 verify with context |
| x448(scalar, u) -> Bytes | X448 scalar mult (RFC 7748), DH shared secret |
| x448_or(scalar, u) -> Result[Bytes, String] | X448 without aborting on a wrong-length peer share |
| x448_public_key(private_key) -> Bytes | Derive X448 public key (base u=5) |
| ml_kem_512_keygen(d, z) -> (ek, dk) | ML-KEM-512 keygen (FIPS 203, deterministic in d,z) |
| ml_kem_512_encaps(ek, m) -> (K, c) | ML-KEM-512 encapsulation |
| ml_kem_512_decaps(dk, c) -> Bytes | ML-KEM-512 decapsulation (implicit rejection) |
| ml_kem_768_keygen / encaps / decaps | ML-KEM-768 (same shapes) |
| ml_kem_1024_keygen / encaps / decaps | ML-KEM-1024 (same shapes) |
| ml_kem_768_hybrid_seal(ek, m, aad, msg) | ML-KEM-768 hybrid encryption (HKDF + ChaCha20-Poly1305) |
| ml_kem_768_hybrid_open(dk, blob, aad) -> Option[Bytes] | hybrid decryption; None on any failure |
| ml_kem_768_hybrid_seal_init + ml_kem_hybrid_stream_update/final | streaming hybrid seal |
| ml_kem_{512,768,1024}_hybrid_seal_or / _hybrid_seal_init_or | the seal path as Result — ek is the recipient's key, i.e. peer-supplied |
| poly1305_new / poly1305_update / poly1305_finalize | incremental Poly1305 |
| aes_gcm_siv_encrypt(key, nonce, aad, pt) | AES-GCM-SIV (RFC 8452, nonce-misuse-resistant) |
| aes_gcm_siv_decrypt(key, nonce, aad, ct) -> Option[Bytes] | AES-GCM-SIV decryption |
| xwing_keygen(seed) -> (pk, sk) | X-Wing hybrid KEM keygen (ML-KEM-768 + X25519) |
| xwing_encaps(pk, eseed) -> (ss, ct) | X-Wing encapsulation (derandomized) |
| xwing_decaps(ct, sk) -> Bytes | X-Wing decapsulation |
| turbo_shake_128(data, d, out_len) | TurboSHAKE128 (RFC 9861, Keccak-p[1600,12]); domain byte d 1..=127 |
| kangaroo_twelve_128(m, c, out_len) | KangarooTwelve KT128 (tree hash + customization) |
| turbo_shake_256 / kangaroo_twelve_256 | 256-bit capacity variants |
| hpke_setup_s(suite, mode, pk_r, ikm_e, info, psk, psk_id, sk_s) | HPKE sender setup (RFC 9180, all 4 modes) |
| hpke_seal(ctx, aad, pt) / hpke_open(ctx, aad, ct) | HPKE authenticated encryption (auto sequence numbers) |
| hpke_export(ctx, exporter_context, len) | HPKE exporter |
| hpke_x25519_* / hpke_p256_* / hpke_p521_* / hpke_x448_* | HPKE cipher-suite selectors (all RFC-vectored suites) |
| hpke_p384_hkdf_sha384_aes256gcm | DHKEM(P-384) suite (differential vectors) |
| hpke_derive_key_pair(suite, ikm) -> (pk, sk) | DHKEM DeriveKeyPair (rejection-sampling for the NIST curves, up to 255 tries) |
| hpke_encap / hpke_decap(suite, …) | DHKEM base Encap/Decap; returns (shared_secret, enc) |
| hpke_auth_encap(suite, pk_r, sk_s, ikm_e) / hpke_auth_decap(suite, enc, sk_r, pk_r, pk_s) | DHKEM auth modes (RFC 9180 §5.1.3), kem_context = enc ‖ pkRm ‖ pkSm; same (shared_secret, enc) order |
| hpke_setup_r(suite, mode, sk_r, pk_r, enc, info, psk, psk_id, pk_s) | HPKE receiver setup (all 4 modes) |
| hmac_sha384 / hkdf_sha384 / hkdf_sha384_extract | SHA-384 MAC/KDF family |
| ml_dsa_44_keygen(seed) -> (pk, sk) | ML-DSA-44 keygen (FIPS 204, deterministic in seed) |
| ml_dsa_44_sign(sk, msg, rnd, ctx) -> Bytes | ML-DSA-44 sign (pure; rnd = 0^32 = deterministic) |
| ml_dsa_44_verify(pk, msg, sig, ctx) -> Bool | ML-DSA-44 verify |
| ml_dsa_65_keygen / sign / verify | ML-DSA-65 (same shapes) |
| ml_dsa_87_keygen / sign / verify | ML-DSA-87 (same shapes) |
| ml_dsa_44_sign_prehash(sk, msg, rnd, ctx, ph) | HashML-DSA-44 sign (FIPS 204 Alg 4, OID-tagged pre-hash); 65/87 have the same shape |
| ml_dsa_44_verify_prehash(pk, msg, sig, ctx, ph) | HashML-DSA-44 verify (FIPS 204 Alg 5); 65/87 have the same shape |
| ml_dsa_44_sign_mu(sk, mu, rnd) / verify_mu(pk, mu, sig) | ML-DSA external-mu interface (Alg 7/8); 65/87 have the same shape |
| dsa_prehash_variants / dsa_prehash_sha2_256 / ... | 12 pre-hash selectors (SHA2/SHA3 family + SHAKE-128/256) |
| slh_keygen(slh_sha2_128s, sk_seed, sk_prf, pk_seed) | SLH-DSA keygen (FIPS 205, deterministic in the three seeds) |
| slh_sign(params, sk, msg, ctx) / slh_sign_hedged(...) | SLH-DSA pure signing (deterministic / hedged) |
| slh_verify(params, pk, msg, sig, ctx) | SLH-DSA verification |
| slh_sign_prehash / slh_verify_prehash | HashSLH-DSA (OID-tagged pre-hash, 12 hash functions) |
| slh_sign_raw / slh_verify_raw | raw-M' internal interface |
| slh_sha2_128s ... slh_shake_256f | all 12 SLH-DSA parameter sets |
| lms_keygen / lms_sign / lms_verify | LMS (RFC 8554) stateful Merkle signatures; lms_public_key regenerates pk from SEED/I |
| hss_keygen / hss_sign / hss_verify | HSS multi-level LMS (L=1..8); hss_keygen_with for explicit parameter chains |
| hss_public_key(sk) -> Bytes | The HSS public key blob (typecode ‖ L ‖ root ‖ I) for a private key |
| xmss_params(func, n, full_height, ...) | XMSS/XMSS^MT parameter sets (RFC 8391): SHA2/SHAKE128/SHAKE256, n in {24,32,64}; d=1 is plain XMSS, d>1 multi-tree |
| xmss_keygen_from_seed / xmss_sign / xmss_verify | XMSS from 48-byte seed; xmss_set_index manages the leaf counter; xmss_public_key regenerates pk |
| xmss_wots_pkgen / xmss_wots_sign / xmss_wots_pk_from_sig | WOTS+ one-time primitives (exposed for verification tooling) |
| falcon512_keypair_from_seed(seed) -> (pk, sk) | Falcon-512 keygen (NTRU solve; deterministic in the 48-byte seed) |
| falcon512_sign(sk, msg, rand) -> Bytes | Falcon-512 signing (rand supplies nonce+seed like randombytes) |
| falcon512_sign_padded(sk, msg, rand) -> Bytes | Falcon-512 padded form (fixed 666 bytes) |
| falcon512_verify(pk, msg, sig) -> Bool | Falcon-512 verification (compact + padded forms) |
| falcon1024_keypair_from_seed / sign / sign_padded / verify | Falcon-1024 (same shapes; padded = 1280 bytes) |
| crc32 / crc32c(data : Bytes) -> Bytes | CRC-32 (IEEE) / CRC-32C, 4-byte big-endian |
| crc64_xz / crc64_go_iso(data : Bytes) -> Bytes | CRC-64/XZ / CRC-64/GO-ISO, 8-byte big-endian |
| siphash_2_4(key, data : Bytes) -> Bytes | SipHash-2-4 (64-bit), key 16 bytes → 8 bytes |
| sealed_box_seal(master_key, nonce, pt, aad, ctx) -> Bytes | AEAD envelope (HKDF + AES-256-GCM) |
| sealed_box_open(master_key, envelope, aad, ctx) -> Result[Bytes, String] | Open envelope, Err on auth failure |
| base64_encode(data : Bytes) -> String | Base64 encode (RFC 4648) |
| base64_decode(encoded : String) -> Bytes | Base64 decode |
| base64_decode_or(encoded : String) -> Result[Bytes, String] | Base64 decode, Err on malformed input |
| bytes_to_hex(data : Bytes) -> String | Bytes → lowercase hex |
| hex_to_bytes(hex : String) -> Bytes | hex → Bytes (aborts on bad input) |
| hex_to_bytes_or(hex : String) -> Result[Bytes, String] | hex → Bytes, Err on bad input |
| chacha20_poly1305_decrypt_or(key, nonce, aad, input) -> Result[Bytes, String] | ChaCha20-Poly1305 decrypt, Err instead of aborting on a bad tag |
| xchacha20_poly1305_decrypt_or(key, nonce24, aad, input) -> Result[Bytes, String] | XChaCha20-Poly1305 decrypt, graceful |
| aes_ccm_decrypt_or(input, key, nonce, aad, mac_len) -> Result[Bytes, String] | AES-CCM decrypt, graceful |
| aes_decrypt_cbc_or(data, key, iv) -> Result[Bytes, String] | AES-CBC decrypt with strict PKCS#7 (the lenient original cannot tell tampering from plaintext) |
| sm4_cbc_decrypt_or(key, iv, data) -> Result[Bytes, String] | SM4-CBC decrypt, graceful |
| rsa_oaep_decrypt_or / _with_or / _crt_or -> Result[Bytes, String] | RSA-OAEP decrypt, uniform Err for every failure cause |
| rsa_pkcs1_v15_decrypt_or / _crt_or -> Result[Bytes, String] | RSA PKCS#1 v1.5 decrypt, uniform Err |
| ml_kem_512/768/1024_encaps_or(ek, m) -> Result[(Bytes, Bytes), String] | ML-KEM encapsulation, Err on a wrong-length peer ek |
| ml_kem_512/768/1024_decaps_or(dk, c) -> Result[Bytes, String] | ML-KEM decapsulation, Err on wrong lengths (invalid c still gets the implicit-rejection key) |
| xwing_encaps_or(pk, eseed) / xwing_decaps_or(ct, sk) -> Result[_, String] | X-Wing, graceful on wrong-length peer material |
| hpke_valid_pk(suite, pk) -> Bool | Validate a peer HPKE public key / enc (length + on-curve for the NIST KEMs) |
| hpke_encap_or / auth_encap_or / decap_or / auth_decap_or / setup_s_or / setup_r_or | HPKE with peer keys validated up front, Err instead of aborting. The encap pair returns (shared_secret, enc) — the reverse of RFC 9180's pseudocode, and both halves are Bytes, so a swap compiles and fails silently |
| bytes_equal(a, b : Bytes) -> Bool | Constant-time comparison |
| Group | Names | Why it is public |
|---|---|---|
| Falcon internals | falcon_xof_*, falcon_hash_to_point, falcon_{modq,trim,comp}_{encode,decode}, falcon_fft / falcon_ifft / falcon_poly_*_fft, falcon_mkgauss, modp_*, zint_*, fp_*, falcon_prng_init, prng_get_u64 / prng_get_u8, falcon_gaussian0_sampler, falcon_sampler*, falcon_mq_ntt / falcon_mq_intt, falcon_to_ntt_monty, falcon_is_short, falcon_compute_public | the port was verified layer by layer against the C reference (XOF, codecs, FFT, the NTRU solver, the sampler); those tests still run and need the layer boundaries visible |
| P-256 debug probes | p256_dbg_mul / p256_dbg_ref_mul / p256_dbg_gmul / p256_dbg_ref_gmul | the differential test of the native field against the reference one (lib/p256_dbg_test.mbt) |
| Test RNG | falcon_test_rng_init / _bytes / _set_ctr | a deterministic SHAKE256 stream so the Falcon KATs reproduce byte for byte |
| XMSS leaf helper | xmss_gen_leaf_wots | lets a test regenerate one leaf without building a whole tree |
moon bench| Algorithm | 1 KiB (approx.) |
|---|---|
| MD5 | ~6.5 µs |
| SHA-256 | ~10 µs |
| SHA-512 | ~10 µs |
| SHA3-256 | ~4.5 µs (unrolled Keccak) |
| SHA3-512 | ~6.9 µs |
| SHAKE128 1KiB (out=32) | ~6.1 µs |
| SHAKE256 1KiB (out=64) | ~6.4 µs |
| BLAKE2b | ~20 µs |
| BLAKE3 | ~31 µs (tree-Merkle) |
| HMAC-SHA256 | ~16 µs |
| HMAC-SHA3-256 | ~11 µs |
| HMAC-SHA3-512 | ~13 µs |
| AES-128-CMAC | ~62 µs |
| SipHash-2-4 | ~2.4 µs |
| CRC32 / CRC32C | ~2.3 / ~2.3 µs |
| sealed_box_seal | ~111 µs (HKDF + AES-256-GCM) |
| scrypt (N=1024,r=8,p=1,dk32) | ~21 ms (memory-hard KDF) |
| Argon2id (t=1,m=64,p=1,dk16) | ~561 µs (memory-hard KDF) |
| ECDSA P-256 sign | ~3.3 ms (native field) |
| ECDSA P-256 verify | ~4.1 ms (native field) |
| AES-256-SIV encrypt 1KiB | ~182 µs (S2V + AES-CTR) |
| AES-128-KW wrap 32B | ~35 µs |
| ChaCha20 | ~32 µs |
| ZUC-128 stream (raw XOR) | ~17 µs |
| ZUC-256 stream (raw XOR) | ~18 µs |
| 128-EEA3 encrypt | ~18 µs |
| 128-EIA3 MAC (32-bit tag) | ~24 µs |
| ZUC-256 MAC (128-bit tag) | ~34 µs |
| AES-256-CBC | ~78 µs (T-table) |
| AES-256-GCM | ~99 µs (T-table + GHASH 4-bit tables) |
| Base64 encode | ~7.8 µs |
| Hex encode | ~6.7 µs |
moon testmoon check --deny-warn
moon fmt --check
moon info
moon test --deny-warn
moon bench # run the benchmark suitemoon login # one time, with the account that owns cc06b
moon publish # publishes the current versionInstall
Download zipPure-MoonBit crypto primitives: SHA-1/2 (incl. SHA-512/224/256), SHA-3, Keccak-256, SHAKE/cSHAKE, BLAKE2b/BLAKE2s/BLAKE3 (+keyed), RIPEMD-160, HMAC/Poly1305/CMAC/KMAC/GMAC, AES-CBC/GCM/CTR/CCM/KW/SIV, ChaCha20/XChaCha20 + Salsa20, HKDF/PBKDF2/scrypt/Argon2, RSA (PKCS1-v1.5/OAEP/PSS), ECDSA P-256, Ed25519/Ed25519ctx/Ed25519ph, X25519, HOTP/TOTP (SHA-1/256/512), SipHash, CRC32/CRC32C/CRC-64/Adler-32, Base64/Hex, sealed-box envelope, Chinese national (GM) cryptography: SM2/SM3/SM4 and ZUC-128/ZUC-256 with 128-EEA3/128-EIA3 (3GPP TS 35.221/222/223), post-quantum: ML-KEM/ML-DSA/SLH-DSA (FIPS 203/204/205), LMS/HSS, XMSS/XMSS^MT, Falcon-512/1024