shamir
@noy-db/on-shamir·pnpm add @noy-db/on-shamirMulti-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)])