Skip to content
UniKVS
Esc
↑↓navigate↵open⌘Jpreview
On this page

@unikvs/checksum

How to use @unikvs/checksum middleware, which hashes byte sequences and verifies them against expectations.

Overview

Middleware that hashes byte sequences and verifies them against expected values.Middleware

It passes data through unchanged and only verifies when a checksum var holds an expected hash. Six variants exist: MD5, SHA-1, SHA-224, SHA-256, SHA-384, and SHA-512.

  • Each concrete class’s name matches the class name (e.g. "ChecksumSha256").
  • isOpen is always true.

Install with:

npm install @unikvs/checksum @noble/hashes@2.0.0
pnpm add @unikvs/checksum @noble/hashes@2.0.0
yarn add @unikvs/checksum @noble/hashes@2.0.0
bun add @unikvs/checksum @noble/hashes@2.0.0
nub add @unikvs/checksum @noble/hashes@2.0.0
aube add @unikvs/checksum @noble/hashes@2.0.0

Usage

ChecksumSha256 implements IMiddleware. Pass it to UniKvs with use().

import { ChecksumSha256 } from "@unikvs/checksum";

The other five work the same way. Constructor arguments:

PropType
required?boolean

Whether to throw when no checksum var is present. Defaults to `false`.

Typeboolean

The following stores data with an expected SHA-256 hash and verifies it on reads:

import { ChecksumSha256 } from "@unikvs/checksum";
import { Memory } from "@unikvs/memory";
import * as unikvs from "unikvs";

const kvs = new unikvs.Builder<{ file: unikvs.Value<Uint8Array> }>()
  .use(new ChecksumSha256())
  .persist(new Memory())
  .build();

await kvs.open();

const data = new TextEncoder().encode("abc");
const sha256 = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";

await kvs.set("file", data, {
  vars: { "@unikvs/checksum:sha256": sha256 },
});
const file = await kvs.get("file", {
  vars: { "@unikvs/checksum:sha256": sha256 },
});
await kvs.close();

Checksum

Abstract base class for the six variants. Never use it directly; use a concrete class.

CHECKSUM_ON_HASH_VAR_NAME is the name of the callback var that receives the computed hash. Its value is CHECKSUM_VAR_NAME followed by :onHash.

ChecksumMd5

Middleware verifying with MD5. The checksum var is "@unikvs/checksum:md5".

ChecksumSha1

Middleware verifying with SHA-1. The checksum var is "@unikvs/checksum:sha1".

ChecksumSha224

Middleware verifying with SHA-224. The checksum var is "@unikvs/checksum:sha224".

ChecksumSha256

Middleware verifying with SHA-256. The checksum var is "@unikvs/checksum:sha256".

ChecksumSha384

Middleware verifying with SHA-384. The checksum var is "@unikvs/checksum:sha384".

ChecksumSha512

Middleware verifying with SHA-512. The checksum var is "@unikvs/checksum:sha512".

IHasher

Interface for incremental hash computation. Matches @noble/hashes hashers.

PropType
update(data: Uint8Array<ArrayBuffer>) => void

Feeds data into the hash computation.

Type(data: Uint8Array<ArrayBuffer>) => void
digest() => Uint8Array

Returns the computed hash.

Type() => Uint8Array

IHash

Interface holding a one-shot hash function and a create hasher factory.

PropType
create() => IHasher

Creates a hasher for incremental computation.

Type() => IHasher

ChecksumOnHash

Callback that receives the computed hash. Pass a function in the "<CHECKSUM_VAR_NAME>:onHash" var, separate from the checksum var. For SHA-256, that is "@unikvs/checksum:sha256:onHash".

The callback’s this is bound to the middleware instance. The first argument is the execution context and the second argument is the computed hash.

The callback is called when hashing and verification succeed. If you specify only the callback without an expected checksum, the middleware still computes the hash and calls the callback. If required is true and no expected checksum is present, it throws ChecksumRequiredError and does not call the callback.

The following example receives the SHA-256 hash during a write.

const hashes: string[] = [];

await kvs.set("file", data, {
  vars: {
    "@unikvs/checksum:sha256:onHash": function (
      this: ChecksumSha256,
      c: IPipelineContext,
      hash: string,
    ): void {
      hashes.push(hash);
    },
  },
});

If the callback value is not a function, the middleware throws ChecksumInvalidOnHashError. Exceptions or rejections thrown by the callback propagate as operation failures.

Data types

Method Input Output
encode Uint8Array<ArrayBuffer> Uint8Array<ArrayBuffer>
decode Uint8Array<ArrayBuffer> Uint8Array<ArrayBuffer>
encodeStream Uint8Array<ArrayBuffer> Uint8Array<ArrayBuffer>
decodeStream Uint8Array<ArrayBuffer> Uint8Array<ArrayBuffer>
  • encode and decode pass data through unchanged.
  • This middleware computes the hash (lowercase hex) when the matching checksum var holds a string or when the onHash callback is specified.
  • It throws when the value does not match the expectation.
  • It throws when no checksum var exists and required is true, even if the onHash callback is specified.
  • The onHash callback’s this is bound to the middleware instance. It receives the execution context as the first argument and the computed hash (lowercase hex) as the second argument. If the callback returns a Promise, the middleware waits for it.
  • encodeStream and decodeStream stream chunks downstream unchanged while updating the hash, verifying on completion, and calling the onHash callback.

Errors

Errors thrown by this package:

ChecksumMismatchError

Thrown when the computed hash does not match the expectation.

PropType
actualstring

Computed hash (lowercase hex).

Typestring
expectedstring

Expected hash from the checksum var.

Typestring

Meaning

Either the data or the expectation is wrong.

How to fix

Check which of the data and the expected hash is correct.

ChecksumRequiredError

Meaning

Thrown when required is true but no checksum var was given.

How to fix

Set the expected hash in the matching checksum var, or set required to false.

ChecksumInvalidVarNameError

Thrown when a checksum var name is not a string.

PropType
actualunknown

The given var-name value.

Typeunknown

Meaning

This is a usage error, so it extends InvalidUsageErrorBase. meta.actual keeps the given value as-is.

How to fix

This never happens when using the published concrete classes as-is. In a custom subclass, set CHECKSUM_VAR_NAME to a string.

ChecksumInvalidOnHashError

Thrown when the "<CHECKSUM_VAR_NAME>:onHash" value is not a function.

PropType
actualunknown

The given callback value.

Typeunknown

Meaning

This is a usage error, so it extends InvalidUsageErrorBase. meta.actual keeps the given value as-is.

How to fix

Set a function in the onHash var, or omit the var.

ChecksumInvalidRequiredError

Thrown when required is not a boolean.

PropType
actualunknown

The given `required` value.

Typeunknown

Meaning

This is a usage error, so it extends InvalidUsageErrorBase. meta.actual keeps the given value as-is.

How to fix

Pass true or false to required. It defaults to false.

Was this page helpful?