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
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) |
| 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 |
| aes_ctr(data, key, iv) -> Bytes | AES-CTR encrypt/decrypt (symmetric) |
| 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_sha256 / hotp_sha512(key, counter, digits) -> String | HOTP (RFC 4226) with HMAC-SHA256/512 |
| totp_sha256 / totp_sha512(key, unix_time, step, digits) -> String | TOTP (RFC 6238) with HMAC-SHA256/512 |
| 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 |
| 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 |
| rsa_pkcs1_v15_encrypt(msg, n, e, rand_ps) -> Bytes | RSAES-PKCS1-v1.5 encrypt (RFC 8017 §7.2) |
| 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_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_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_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 |
| 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]) |
| 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_x448_* | HPKE cipher-suite selectors (all RFC-vectored suites) |
| 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) |
| ml_dsa_44_verify_prehash(pk, msg, sig, ctx, ph) | HashML-DSA-44 verify (FIPS 204 Alg 5) |
| ml_dsa_44_sign_mu(sk, mu, rnd) / verify_mu(pk, mu, sig) | ML-DSA-44 external-mu interface (Alg 7/8) |
| 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 |
| 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 |
| bytes_equal(a, b : Bytes) -> Bool | Constant-time comparison |
moon bench| Algorithm | 1 KiB (approx.) |
|---|---|
| MD5 | ~8.5 µs |
| SHA-256 | ~16 µs |
| SHA-512 | ~14 µs |
| SHA3-256 | ~140 µs |
| SHAKE128 1KiB (out=32) | ~80 µs |
| SHAKE256 1KiB (out=64) | ~92 µs |
| BLAKE2b | ~27 µs |
| BLAKE3 | ~46 µs |
| HMAC-SHA256 | ~23 µs |
| HMAC-SHA3-256 | ~213 µs |
| HMAC-SHA3-512 | ~338 µs |
| AES-128-CMAC | ~347 µs |
| SipHash-2-4 | ~4.2 µs |
| CRC32 / CRC32C | ~4.7 µs |
| sealed_box_seal | ~588 µs (HKDF + AES-256-GCM) |
| scrypt (N=1024,r=8,p=1,dk32) | ~84 ms (memory-hard KDF) |
| Argon2id (t=1,m=64,p=1,dk16) | ~1 ms (memory-hard KDF) |
| ECDSA P-256 sign | ~13 ms (Jacobian, was ~270 ms affine) |
| ECDSA P-256 verify | ~24 ms (Jacobian, was ~540 ms affine) |
| AES-256-SIV encrypt 1KiB | ~950 µs (S2V + AES-CTR) |
| AES-128-KW wrap 32B | ~146 µs |
| ChaCha20 | ~48 µs |
| ChaCha20-Poly1305 encrypt | ~73 µs (was ~456 µs) |
| Poly1305 MAC | ~7 µs (was ~387 µs, BigInt) |
| AES-256-CBC | ~315 µs (table-based GF mul) |
| AES-256-GCM | ~487 µs (GHASH 4-bit tables) |
| Base64 encode | ~10 µ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