7. Hash Functions
The hash/ library computes digests of DUST values.
Table of Contents
7.1. Hash values ↑
#hash holds a digest together with the algorithm that produced it. It uses
RON's #prefix value notation, and its payload is itself a tagged element: the
tag names the algorithm and its value is the digest in lowercase hexadecimal.
#hash #sha256 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
{"#hash": {"#sha256": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"}}
Import validates the payload: the algorithm tag must name one hash/digest defines,
and the digest must be lowercase hexadecimal of that algorithm's length.
Invalid payloads produce #err <invalid tag>; once readers use the cell
decoders, an invalid payload is a parse error, invalid tag, at the tag.
#hash #sha256 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
#hash #sha256 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
#hash #sha256 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
Two #hash values are equal when both the algorithm and the digest are equal,
so digests of the same input under different algorithms are unequal rather
than a type mismatch. A #hash value never equals a string.
7.2. hash/digest ↑
Function(hash/digest algorithm value) → hash
Returns a #hash of value under algorithm, a name from this table:
| Algorithm | Digest | Kind |
|---|---|---|
sha256 |
32 bytes | SHA-2, cryptographic |
sha512 |
64 bytes | SHA-2, cryptographic |
sha3-256 |
32 bytes | SHA-3, cryptographic |
sha3-512 |
64 bytes | SHA-3, cryptographic |
xxh3-64 |
8 bytes | XXH3 64-bit, non-cryptographic |
xxh3-128 |
16 bytes | XXH3 128-bit, non-cryptographic |
Every DUST value can be hashed. The digest covers the value's canonical DUST form: the bytes the DUST formatter writes for it, encoded as UTF-8, without the single terminal file newline. Internal newlines and newlines inside string contents are kept. Arguments evaluate before hashing, and a quoted form hashes its resulting data. The canonical form follows the formatter exactly:
- A top-level list of two or more forms omits its brackets, so
(hash/digest sha256 [1 2])digests the bytes of1and2on separate lines; a one-element list keeps its brackets, and an empty list is empty. - Maps keep their braces and sort their keys, so maps with the same members hash identically regardless of member order.
- Integer
1and float1.0have different forms and digests. #utcand#durpayloads use their canonical spelling, so every spelling of the same instant or duration hashes identically.- Comments are excluded: documenting a form never changes its digest.
- A function hashes as its canonical form: a closure as its
fnsource, and a library function as its constant reference, such as:strings/case. Values captured by a closure are not part of its form. - Unicode text is not normalized.
A form whose known tag has an invalid payload, such as #link true, is
rejected when it is read, so it cannot reach hash/digest.
The string abc has canonical form abc, so its digests match the standard
test vectors for those three bytes, while the empty string has canonical form
"":
| Call | Result |
|---|---|
(hash/digest sha256 abc) |
#hash #sha256 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad |
(hash/digest sha3-256 abc) |
#hash #sha3-256 3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532 |
(hash/digest xxh3-64 abc) |
#hash #xxh3-64 78af5f94892f3950 |
The XXH3 variants are for keys, bucketing, deduplication, and change detection,
never for integrity against an adversary. xxh3-128 makes accidental
collisions negligible where 64 bits are too few, such as content addressing. An unknown algorithm produces
#err <algorithm hash unknown>.
(hash/digest sha256 null) (hash/digest sha256 abc) (hash/digest sha256 "") (hash/digest sha256 1) (hash/digest sha256 1.0) (hash/digest sha256 [é 猫]) (hash/digest sha256 `.name) (hash/digest sha256 ``1) (hash/digest sha256 #link 1) (hash/digest sha256 #utc 1970-01-01T00:00:00Z) (hash/digest sha256 #dur PT1S) (hash/digest sha256 []) (hash/digest sha256 {a 1 b 2}) (hash/digest sha256 #utc 1970-01-01T00:00:00.0000001Z) (hash/digest sha256 #dur PT0.0000001S)
#hash #sha256 74234e98afe7498fb5daf1f36ac2d78acc339464f950703b8c019892f982b90b #hash #sha256 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad #hash #sha256 12ae32cb1ec02d01eda3581b127c1fee3b0dc53572ed6baf239721a03d82e126 #hash #sha256 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b #hash #sha256 d0ff5974b6aa52cf562bea5921840c032a860a91a3512f7fe8f768f6bbe005f6 #hash #sha256 251304c0f0e98b997852859fc1e885ec256ad7845938663a88f5983d237f385c #hash #sha256 468f0dd394cbd3e8506524aa28faec25309cd9704c695aea1f9218e4f395b283 #hash #sha256 d135669e0056d96659a6969caa40dad4576a10121eaad744521e9a09cdca6a83 #hash #sha256 e64ae69a6b69823b59a98efc4eee9036bfd5dd2b4c171bd6b040bb649cd6d5e3 #hash #sha256 e6a04092b64d10308bda75ec4bbf7e5e9459b42fb8f2a425e319e304c445b078 #hash #sha256 9db6bc3f734529a972f45f22b2620c5151e35c2e5c5ec5714b31a55e4c6d4ff5 #hash #sha256 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 #hash #sha256 53a6fbfea11bafdfe07457e9d925dedda5ca93811d422d4af322379990194d45 #hash #sha256 69211abbe894a3a02fce9a6a6d217ec326d939097bda56b2621500f826569af8 #hash #sha256 85fcc02259a4615aee0271b48d9ecae27a581a0e50d2550fabc4ac15e5e220b0
(hash/digest sha512 abc) (hash/digest sha3-256 abc) (hash/digest sha3-512 abc) (hash/digest xxh3-64 abc) (hash/digest xxh3-128 abc)
#hash #sha512 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f #hash #sha3-256 3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532 #hash #sha3-512 b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0 #hash #xxh3-64 78af5f94892f3950 #hash #xxh3-128 06b05ab6733a618578af5f94892f3950
(= (hash/digest sha256 {a 1 b 2}) (hash/digest sha256 {a 1 b 2})) (comparison/not= (hash/digest sha256 1) (hash/digest sha256 1.0)) (comparison/not= (hash/digest sha256 é) (hash/digest sha256 é))
true true true
(comparison/not= (hash/digest sha256 abc) (hash/digest sha3-256 abc)) (comparison/not= (hash/digest xxh3-64 abc) (hash/digest xxh3-128 abc)) (= (hash/digest xxh3-64 abc) #hash #xxh3-64 78af5f94892f3950)
true true true
(hash/digest sha256 (fn [] 1))
#hash #sha256 06d0dff99f70155bfd64b168de5c36cede11e9c14ddf87358cbb89ea9f08ce69
(hash/digest sha256 [(fn [] 1)])
#hash #sha256 b6ca49a321d2250ae8533a020a3fbf07d9942b3af2e67728b342ed4b73f86d0e