stable

shamir

k-of-n Shamir Secret Sharing of the vault KEK — any k of n shares reconstruct it; fewer than k leak nothing.

@noy-db/on-shamir · pnpm add @noy-db/on-shamir Multi-party k-of-n secret sharing of the KEK.

What it does

splitKEK(kek, { k, n }) runs Shamir Secret Sharing over GF(2^8), byte-wise, on a CryptoKey, returning n RawShare structures; any k of them reconstruct the key via combineKEK(shares) — fewer than k leaks zero bits. Pure TypeScript (~120 LoC), zero cryptographic dependencies beyond Web Crypto's getRandomValues and subtle.importKey. Shares serialize to Base32 (encodeShareBase32 / decodeShareBase32, with a human-readable SHAMIR_S{x}_K{k}N{n}__ prefix) or JSON (encodeShareJSON / decodeShareJSON) for storage inside other on-* keyring entries. Low-level splitSecret / combineSecret operate on raw Uint8Array bytes for custom integrations.

The defining feature is composability: each share can itself sit behind any other on-* method — share 1 behind WebAuthn, share 2 behind OIDC, share 3 printed on paper. Not constant-time by design; the threat model assumes a trusted combine device.

Usage

import { splitKEK, combineKEK, encodeShareBase32, decodeShareBase32 } from '@noy-db/on-shamir'

const shares = await splitKEK(currentKEK, { k: 2, n: 3 })
const shareStrings = shares.map(encodeShareBase32)
// distribute: shareStrings[0] behind WebAuthn, [1] behind OIDC, [2] on paper

const kek = await combineKEK([decodeShareBase32(a), decodeShareBase32(b)])

See also