// Hex Editor — Hash / Checksum
// MD5 / SHA1 / SHA256 / SHA224 / SM3 digests, returned as lowercase hex strings.
// Wraps moonbitlang/x/crypto (pure MoonBit, works on both native and wasm-gc).
///|
const HEX_LOWER = "0123456789abcdef"
///|
/// Format a byte array as a lowercase hex string.
fn to_lower_hex(data : FixedArray[Byte]) -> String {
let sb = StringBuilder()
for i = 0; i < data.length(); i = i + 1 {
let b = data[i].to_int()
sb.write_char(HEX_LOWER.get_char((b >> 4) & 0xF).unwrap())
sb.write_char(HEX_LOWER.get_char(b & 0xF).unwrap())
}
sb.to_string()
}
///|
pub struct HashResult {
name : String
value : String
} derive(Debug)
///|
/// MD5 digest (hex, lowercase). MD5 is cryptographically broken — prefer SHA-256.
pub fn md5_hex(data : Bytes) -> String {
to_lower_hex(@crypto.md5(data))
}
///|
/// SHA-1 digest (hex, lowercase). SHA-1 is cryptographically broken — prefer SHA-256.
pub fn sha1_hex(data : Bytes) -> String {
to_lower_hex(@crypto.sha1(data))
}
///|
/// SHA-256 digest (hex, lowercase).
pub fn sha256_hex(data : Bytes) -> String {
to_lower_hex(@crypto.sha256(data))
}
///|
/// SHA-224 digest (hex, lowercase).
pub fn sha224_hex(data : Bytes) -> String {
to_lower_hex(@crypto.sha224(data))
}
///|
/// SM3 digest (Chinese national standard, hex, lowercase).
pub fn sm3_hex(data : Bytes) -> String {
to_lower_hex(@crypto.sm3(data))
}
///|
/// Compute all supported digests at once.
pub fn hash_all(data : Bytes) -> Array[HashResult] {
[
{ name: "MD5", value: md5_hex(data), },
{ name: "SHA1", value: sha1_hex(data), },
{ name: "SHA256", value: sha256_hex(data), },
{ name: "SHA224", value: sha224_hex(data), },
{ name: "SM3", value: sm3_hex(data), },
]
}
///|
test "hash vectors" {
assert_eq(md5_hex(b"abc"), "900150983cd24fb0d6963f7d28e17f72")
assert_eq(md5_hex(b""), "d41d8cd98f00b204e9800998ecf8427e")
assert_eq(sha1_hex(b"abc"), "a9993e364706816aba3e25717850c26c9cd0d89d")
assert_eq(
sha256_hex(b"abc"),
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
)
assert_eq(
sha256_hex(b""),
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
)
assert_eq(
sha224_hex(b"abc"),
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
)
assert_eq(
sm3_hex(b"abc"),
"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
)
let all = hash_all(b"abc")
assert_eq(all.length(), 5)
assert_eq(all[0].name, "MD5")
assert_eq(all[0].value, "900150983cd24fb0d6963f7d28e17f72")
}