国密算法库的 MoonBit 移植
///|
test "sm3 digest" {
// 一次性摘要
let digest = @sm3.sm3_sum(b"abc")
assert_eq(
@byteutil.bytes_to_hex(digest),
"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
)
// 多段拼接摘要,等价于把各段连接后再计算
assert_eq(
@byteutil.bytes_to_hex(@sm3.sm3_sum_multi([b"a", b"b", b"c"])),
@byteutil.bytes_to_hex(digest),
)
// 流式接口,对齐 Go 的 hash.Hash(write 返回新的上下文,链式调用)
let h = @sm3.new().write(b"a").write(b"bc")
assert_eq(h.size(), 32)
assert_eq(h.block_size(), 64)
assert_eq(@byteutil.bytes_to_hex(h.sum()), @byteutil.bytes_to_hex(digest))
// reset 之后可以复用
assert_eq(
@byteutil.bytes_to_hex(h.reset().write(b"abc").sum()),
@byteutil.bytes_to_hex(digest),
)
}///|
test "sm4 block and modes" {
let key = @byteutil.hex_to_bytes("0123456789abcdeffedcba9876543210")
// GM/T 0002-2012 附录 A 标准向量
let block = @sm4.new_cipher(key)
assert_eq(block.block_size(), 16)
let ct = block.encrypt(key)
assert_eq(@byteutil.bytes_to_hex(ct), "681edf34d206965e86b3e94f536e4246")
assert_eq(
@byteutil.bytes_to_hex(block.decrypt(ct)),
@byteutil.bytes_to_hex(key),
)
// ECB / CBC 模式 + PKCS7 填充
let msg = b"hello sm4, moonbit!"
let iv = @byteutil.hex_to_bytes("000102030405060708090a0b0c0d0e0f")
let padded = @byteutil.pkcs7_pad(msg, 16)
let ecb = @sm4.sm4_encrypt_ecb(key, padded)
let ecb_plain = @byteutil.pkcs7_unpad(@sm4.sm4_decrypt_ecb(key, ecb))
assert_true(@byteutil.bytes_eq(ecb_plain, msg))
let cbc = @sm4.sm4_encrypt_cbc(key, iv, padded)
let cbc_plain = @byteutil.pkcs7_unpad(@sm4.sm4_decrypt_cbc(key, iv, cbc))
assert_true(@byteutil.bytes_eq(cbc_plain, msg))
// CFB / OFB(128 位反馈,同样按整块处理)
let cfb = @sm4.sm4_encrypt_cfb(key, iv, padded)
let cfb_plain = @byteutil.pkcs7_unpad(@sm4.sm4_decrypt_cfb(key, iv, cfb))
assert_true(@byteutil.bytes_eq(cfb_plain, msg))
let ofb = @sm4.sm4_encrypt_ofb(key, iv, padded)
let ofb_plain = @byteutil.pkcs7_unpad(@sm4.sm4_decrypt_ofb(key, iv, ofb))
assert_true(@byteutil.bytes_eq(ofb_plain, msg))
// GCM 认证加密
let nonce = @byteutil.hex_to_bytes("000102030405060708090a0b")
let aad = b"header"
let (gcm_ct, tag) = @sm4.sm4_gcm_encrypt(key, nonce, msg, aad)
// 解密校验:tag 不符会抛 SM4Error::InvalidTag,不返回明文
let plain = @sm4.sm4_gcm_decrypt(key, nonce, gcm_ct, aad, tag)
assert_true(@byteutil.bytes_eq(plain, msg))
}///|
test "sm2 sign and encrypt" {
let sk = @sm2.generate_key(@sm2.os_rand())
let pub_key = @sm2.derive_public_key(sk)
let uid = @sm2.default_uid()
let msg = b"hello sm2"
// 裸 (r, s) 签名与 ASN.1 DER 签名
let (r, s) = @sm2.sm2_sign(sk, msg, uid, @sm2.os_rand())
assert_true(@sm2.sm2_verify(pub_key, msg, uid, r, s))
let der = @sm2.sign_digit_to_sign_data(r, s)
let (r2, s2) = @sm2.sign_data_to_sign_digit(der)
assert_true(@byteutil.bytes_eq(r, r2) && @byteutil.bytes_eq(s, s2))
assert_true(
@sm2.sm2_verify_der(
pub_key,
msg,
uid,
@sm2.sm2_sign_der(sk, msg, uid, @sm2.os_rand()),
),
)
// C1C3C2 / C1C2C3 两种密文排布与 ASN.1 密文
let ct = @sm2.sm2_encrypt(pub_key, msg, @sm2.os_rand(), @sm2.C1C3C2)
assert_true(@byteutil.bytes_eq(@sm2.sm2_decrypt(sk, ct, @sm2.C1C3C2), msg))
assert_true(
@byteutil.bytes_eq(
@sm2.sm2_decrypt_asn1(
sk,
@sm2.sm2_encrypt_asn1(pub_key, msg, @sm2.os_rand()),
),
msg,
),
)
// 公钥压缩 / 解压
let compressed = @sm2.compress_point(pub_key)
assert_eq(compressed.length(), 33)
assert_true(@sm2.is_on_curve(@sm2.decompress_point(compressed)))
}///|
test "sm2 za and digest verify" {
let sk = @sm2.generate_key(@sm2.os_rand())
let pub_key = @sm2.derive_public_key(sk)
let uid = @sm2.default_uid()
let msg = b"hello sm2 digest"
// ZA 与 e = SM3(ZA ‖ M) 现在可以从外部取得
let za = pub_key.za(uid)
assert_eq(za.length(), 32)
let digest = pub_key.sm3_digest(msg, uid) // uid 为空时等价于 default_uid()
assert_true(@byteutil.bytes_eq(digest, pub_key.sm3_digest(msg, b"")))
// 对「已算好的摘要」验签(对应 Go 的 sm2.Verify)
let (r, s) = @sm2.sm2_sign(sk, msg, uid, @sm2.os_rand())
assert_true(@sm2.sm2_verify_digest(pub_key, digest, r, s))
}///|
test "sm4 key pem" {
let key : @sm4.SM4Key = b"0123456789abcdef"
// 不加密
let pem = @sm4.write_key_to_pem(key, b"", None)
assert_true(@byteutil.bytes_eq(@sm4.read_key_from_pem(pem, b""), key))
// 口令加密:块类型为 SM4 ENCRYPTED KEY,内容为 AES-256-CBC 密文
let enc = @sm4.write_key_to_pem(key, b"sm4-pwd", @sm4.os_rand())
let block = @byteutil.pem_decode(enc)
assert_eq(block.type_, "SM4 ENCRYPTED KEY")
assert_true(@byteutil.bytes_eq(@sm4.read_key_from_pem(enc, b"sm4-pwd"), key))
}///|
test "sm2 key exchange" {
let (priv_a, rpriv_a) = (
@sm2.generate_key(@sm2.os_rand()),
@sm2.generate_key(@sm2.os_rand()),
)
let (priv_b, rpriv_b) = (
@sm2.generate_key(@sm2.os_rand()),
@sm2.generate_key(@sm2.os_rand()),
)
let pub_a = @sm2.derive_public_key(priv_a)
let pub_b = @sm2.derive_public_key(priv_b)
let rpub_a = @sm2.derive_public_key(rpriv_a)
let rpub_b = @sm2.derive_public_key(rpriv_b)
let ida = b"1234567812345678"
let idb = b"1234567812345678"
let (ka, s1a, s2a) = @sm2.key_exchange_a(
16, ida, idb, priv_a, pub_b, rpriv_a, rpub_b,
)
let (kb, s1b, s2b) = @sm2.key_exchange_b(
16, ida, idb, priv_b, pub_a, rpriv_b, rpub_a,
)
assert_true(@byteutil.bytes_eq(ka, kb)) // 协商出相同的 16 字节会话密钥
assert_true(@byteutil.bytes_eq(s1a, s1b) && @byteutil.bytes_eq(s2a, s2b)) // 密钥确认值一致
}moon version --all # 确认工具链版本
moon fmt --check # 格式检查
moon check --deny-warn # 类型 / 语法检查(警告视为错误)
moon test --deny-warn # 运行测试
moon build --target wasm-gc # 编译(wasm-gc 后端)
moon build --target native # 编译(native 后端)
moon run cmd/sm2 # 运行 sm2 example 入口程序
moon run cmd/sm3 # 运行 sm3 example 入口程序
moon run cmd/sm4 # 运行 sm4 example 入口程序