Hash API

Streaming and one-shot cryptographic hash digests: MD5, SHA-1, and SHA-256 over Buffers.

Overview

The global identifier Hash is a namespace. Its statics either build a stateful Hash instance (Hash.create(algo)) for streaming use, or return a digest in one call (Hash.digest(algo, buf)). Hashes here are unkeyed and produce a fixed-size digest; for keyed HMAC digests, RSA signing, certificate handling, or random bytes, use the Crypto native instead.

Inputs and outputs are Buffers: update(buf) consumes a Buffer, and finish() / Hash.digest(...) return a Buffer containing the raw digest bytes. Digest output is the algorithm's standard big-endian byte order. Use b.hex() to format a digest as a lowercase hex string, or b.size() to confirm the length matches the algorithm (16/20/32 bytes for MD5/SHA-1/SHA-256).

Algorithms

The algo argument selects the hash algorithm. Strings are matched case-insensitively, so "SHA256" works too.

AlgorithmDigest sizeNotes
"md5"16 bytesBroken for collision resistance; safe only for non-security uses such as file fingerprinting and change detection.
"sha1"20 bytesAlso broken for collision resistance.
"sha256"32 bytesRecommended default for general integrity and fingerprinting.
Choice of algorithm: SHA-256 is the right default. MD5 and SHA-1 are exposed for compatibility with existing checksum files only; do not use them in any security context.

Statics

Hash.create(algo)

Builds a new hash context already started for algo. The returned instance is ready to accept update(...) calls.

Returns: A new Hash instance.

Hash.digest(algo, buf)

Returns the digest of buf under algo in one call. It is equivalent to creating an instance, feeding buf once, and returning the result. Preferred when the entire input is already in memory; use the streaming form for large or multi-chunk inputs such as file hashing.

Returns: A Buffer containing the raw digest bytes.

one-shot digest
var d = Hash.digest("sha256", Buffer.fromString("hello"))
print(d.hex())
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Empty input: Hash.digest(algo, Buffer.fromString("")) returns the well-known digest of the empty string for that algorithm. For SHA-256 that is e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.

Instance Methods

Returned by Hash.create(algo); methods are invoked as h.method(...). A fresh instance is ready to receive update(...) calls. After finish() the instance is sealed: further update(...) calls return false until reset() is called, which restarts the same algorithm with empty state.

h.update(buf)

Feeds buf into the digest. Returns true on success, false if the context has already been finish()ed, in which case call reset() first. Empty buffers are accepted as a no-op success.

h.finish()

Returns the digest of all bytes fed so far and seals the context. Subsequent update() calls return false until reset() is called. Calling finish() again on a sealed context returns an empty Buffer.

Returns: A Buffer containing the raw digest bytes.

h.reset()

Re-initialises the same algorithm with empty state, making the instance reusable for another hashing round. Returns true on success.

streaming digest
var h = Hash.create("sha256")
h.update(Buffer.fromString("hel"))
h.update(Buffer.fromString("lo"))
print(h.finish().hex())
// 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824

Errors

Unknown algorithm strings, missing arguments, or non-Buffer inputs raise a Zym runtime error of the form Hash.method(args) .... The streaming update(buf) returning false is not an error in the runtime sense. It indicates the context was already finalized.

Examples

Hashing a Large File in Chunks

var f = File.open("/path/to/big.bin", "r")
var h = Hash.create("sha256")
while (true) {
    var chunk = f.readBytes(64 * 1024)
    if (chunk.size() == 0) { break }
    h.update(chunk)
}
f.close()
print(h.finish().hex())

Reusing a Context

var h = Hash.create("sha1")
h.update(Buffer.fromString("first"))
print(h.finish().hex())   // sha1("first")

h.reset()
h.update(Buffer.fromString("second"))
print(h.finish().hex())   // sha1("second")

Comparing Digests in Constant Time

var trusted = Hash.digest("sha256", Buffer.fromString("expected"))
var actual  = Hash.digest("sha256", Buffer.fromString("expected"))
var c = Crypto.create()
print(c.constantTimeCompare(trusted, actual))   // true