Standard Library
namespace digest
Message digests and keyed message authentication: MD5, SHA-1, SHA-256 and HMAC-SHA-256.
since 0.1.0-alpha.1linuxwindowswasm
Overview
Each function hashes the bytes of a string and returns the digest as a string of raw bytes (16, 20 or 32 of them), not as text. Raw bytes are rarely printable, so pass the result to encoding::hexEncode or encoding::base64Encode to display or transmit it. MD5 and SHA-1 are provided for checksums and compatibility with existing formats; they are not safe against deliberate collisions, so use SHA-256 for anything security-related. The implementation is written in Leviathan itself, so hashing large inputs is slow compared to a native library.
Description
The digest namespace computes four hash functions over the bytes of a string:
| function | result length |
|---|---|
md5(data) |
16 bytes |
sha1(data) |
20 bytes |
sha256(data) |
32 bytes |
hmacSha256(key, message) |
32 bytes |
Each function returns the raw digest bytes as a string, not hexadecimal text. To print or compare
the result, pass it through encoding::hexEncode or encoding::base64Encode. A non-ASCII string is
hashed as its UTF-8 bytes.
The implementations are written in the language and are checked against the published test vectors (RFC 1321 for MD5, RFC 3174 and FIPS 180-4 for SHA-1 and SHA-256, RFC 4231 for HMAC-SHA-256). They are meant for entity tags, cookies and signatures, not for hashing large inputs: on the interpreters they are slow.
MD5 and SHA-1 are not collision resistant. Use them only where a protocol requires them, and use SHA-256 otherwise.
Known test vectors
console.writeln(encoding::hexEncode(digest::md5("abc")));
console.writeln(encoding::hexEncode(digest::sha1("abc")));
console.writeln(encoding::hexEncode(digest::sha256("abc")));
console.writeln(encoding::hexEncode(digest::sha256("")));
console.writeln(encoding::hexEncode(digest::hmacSha256("key", "The quick brown fox jumps over the lazy dog")));
900150983cd24fb0d6963f7d28e17f72
a9993e364706816aba3e25717850c26c9cd0d89d
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8
Rules
- Every digest function returns raw bytes. Its length is fixed by the algorithm, whatever the input.
hmacSha256(key, message)takes the key first.- The functions are deterministic and take no seed.
Examples
Digest lengths and an entity tag
console.writeln(digest::md5("abc").length());
console.writeln(digest::sha1("abc").length());
console.writeln(digest::sha256("abc").length());
string body = "<h1>hello</h1>";
string etag = encoding::hexEncode(digest::sha256(body));
console.writeln(etag.length());
console.writeln(encoding::base64Encode(digest::sha256("abc")));
16
20
32
64
ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=
The padding boundary of SHA-256 is the usual place for an implementation to go wrong. This 56-byte message from FIPS 180-4 straddles it:
A padding-boundary vector
string msg = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
console.writeln(msg.length());
console.writeln(encoding::hexEncode(digest::sha256(msg)));
56
248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1
Examples
Hex digests of the same message
string msg = "abc";
console.writeln(encoding::hexEncode(digest::md5(msg)));
console.writeln(encoding::hexEncode(digest::sha1(msg)));
console.writeln(encoding::hexEncode(digest::sha256(msg)));
console.writeln(digest::sha256(msg).length());
900150983cd24fb0d6963f7d28e17f72
a9993e364706816aba3e25717850c26c9cd0d89d
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
32
Functions
hmacSha256
hmacSha256(string key, string msg) -> stringCompute an HMAC-SHA-256 authentication code.
The code proves that whoever produced it knew key, and that msg has not changed. A key longer than 64 bytes is hashed first, as the HMAC standard requires.
Parameters
- key
- The secret key; its bytes are used.
- msg
- The message to authenticate.
Returns
The 32-byte authentication code as a raw-byte string.
Examples
string mac = digest::hmacSha256("Jefe", "what do ya want for nothing?");
console.writeln(encoding::hexEncode(mac));
5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843
See also: sha256
md5
md5(string msg) -> stringCompute the MD5 digest of a string.
MD5 is broken for security purposes; use it only for checksums and where a format requires it.
Parameters
- msg
- The message; its bytes are hashed.
Returns
The 16-byte digest as a raw-byte string.
Examples
console.writeln(encoding::hexEncode(digest::md5("abc")));
console.writeln(encoding::hexEncode(digest::md5("")));
console.writeln(digest::md5("abc").length());
900150983cd24fb0d6963f7d28e17f72
d41d8cd98f00b204e9800998ecf8427e
16
See also: sha256
sha1
sha1(string msg) -> stringCompute the SHA-1 digest of a string.
SHA-1 is broken for security purposes; use it only where a format requires it.
Parameters
- msg
- The message; its bytes are hashed.
Returns
The 20-byte digest as a raw-byte string.
Examples
console.writeln(encoding::hexEncode(digest::sha1("abc")));
console.writeln(encoding::base64Encode(digest::sha1("abc")));
a9993e364706816aba3e25717850c26c9cd0d89d
qZk+NkcGgWq6PiVxeFDCbJzQ2J0=
See also: sha256
sha256
sha256(string msg) -> stringCompute the SHA-256 digest of a string.
Parameters
- msg
- The message; its bytes are hashed.
Returns
The 32-byte digest as a raw-byte string. Use encoding::hexEncode to get the usual 64-character hexadecimal form.
Examples
console.writeln(encoding::hexEncode(digest::sha256("abc")));
console.writeln(encoding::hexEncode(digest::sha256("")));
console.writeln(digest::sha256("hello").length());
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
32
See also: hmacSha256, hexEncode
See also
- encoding — Text encodings for byte strings: hexadecimal, base64, URL-safe base64, and percent-encoding.
- sha256 — Compute the SHA-256 digest of a string.
- hmacSha256 — Compute an HMAC-SHA-256 authentication code.