Files
emdash-cms--emdash/packages/plugin-cli/src/multihash.ts
T
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

46 lines
1.7 KiB
TypeScript

/**
* Multibase-encoded multihash helpers.
*
* The registry RFC requires artifact checksums in multibase-multihash format:
*
* <multibase-prefix><varint hash-code><varint length><digest bytes>
*
* For sha2-256 (the only hash function clients MUST support), `code = 0x12`,
* `length = 0x20` (32 bytes), both fitting in a single varint byte. We encode
* the result with the base32 multibase prefix `b` (lowercase, no padding),
* which is the recommended encoding per the RFC and the most CID-friendly
* choice.
*
* Concretely, a sha2-256 multihash is `0x12 0x20 || digest32` (34 bytes
* total) and the multibase output is `b` + base32(those 34 bytes).
*/
import { toBase32 } from "@atcute/multibase";
import { sha256 } from "@oslojs/crypto/sha2";
/** multihash code for sha2-256 (single-byte varint). */
const SHA256_CODE = 0x12;
/** sha2-256 digest length in bytes (single-byte varint). */
const SHA256_LENGTH = 0x20;
/**
* Compute the multibase-multihash sha2-256 checksum of the given bytes.
*
* @returns the base32-multibase string, e.g. `bciq...`. The output is the
* single-character multibase prefix `b` followed by base32 encoding of
* 34 bytes (2-byte multihash header + 32-byte digest), totalling 56
* characters.
*/
export function sha256Multihash(bytes: Uint8Array): string {
const digest = sha256(bytes);
if (digest.length !== SHA256_LENGTH) {
throw new Error(`expected sha256 digest to be ${SHA256_LENGTH} bytes, got ${digest.length}`);
}
const multihash = new Uint8Array(2 + digest.length);
multihash[0] = SHA256_CODE;
multihash[1] = SHA256_LENGTH;
multihash.set(digest, 2);
// Multibase prefix `b` indicates base32 lowercase, no padding.
return `b${toBase32(multihash)}`;
}