npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@substrate-system/shamirs-secret-sharing

v0.0.2

Published

Shamir's Secret Sharing for the browser

Readme

Shamir's Secret Sharing

tests types module semantic versioning Common Changelog install size gzip size dependencies license

Shamir's Secret Sharing for the browser. Take your private key, and split it into multiple "shards", and distribute the shards among other devices. The other devices could be your friends, or simply other machines that you own.

See a live demo

Install

Install from npm:

npm i -S @substrate-system/shamirs-secret-sharing

Quick start

Split a secret into shares and reconstruct it later.

import { split, reconstruct } from '@substrate-system/shamirs-secret-sharing'

// Any bytes work. Here we use UTF-8 text for simplicity.
const secretBytes = new TextEncoder().encode('correct horse battery staple')

// Create 5 shares, any 3 can reconstruct
const shares = split(secretBytes, { min: 3, total: 5 })

// Pick any 3 shares to reconstruct
const recovered = reconstruct([shares[0], shares[2], shares[4]])

console.log(new TextDecoder().decode(recovered)) // "correct horse battery staple"

Ed25519 with Web Crypto

Generate an Ed25519 key pair with the Web Crypto API, export the private key, and split it into shares. Works in modern browsers and Node 20+.

import { split, reconstruct } from '@substrate-system/shamirs-secret-sharing'

// In modern browsers and Node 20+, globalThis.crypto is available.
// For wider compatibility, you can use:
// import { webcrypto as crypto } from '@substrate-system/one-webcrypto'

const crypto = globalThis.crypto

// 1) Generate Ed25519 key pair
const keypair = await crypto.subtle.generateKey(
{ name: 'Ed25519' },
true,                 // extractable: we will export the private key
['sign', 'verify']
)

// 2) Export the private key as PKCS#8 bytes
const pkcs8 = await crypto.subtle.exportKey('pkcs8', keypair.privateKey)
const privateKeyBytes = new Uint8Array(pkcs8)

// 3) Split into 5 shares where any 3 can reconstruct
const shares = split(privateKeyBytes, { min: 3, total: 5 })

// 4) Later, reconstruct from any 3 shares
const recovered = reconstruct([shares[0], shares[2], shares[4]])

// 5) (Optional) Import the reconstructed key back to a CryptoKey
const importedPrivateKey = await crypto.subtle.importKey(
'pkcs8',
recovered,
{ name: 'Ed25519' },
true,
['sign']
)

console.log('Reconstruction successful:', importedPrivateKey instanceof CryptoKey)

Use

Node/Browser ESM

import { split, reconstruct, type Share } from '@substrate-system/shamirs-secret-sharing'

const msg = 'hello shamir'
const secret = new TextEncoder().encode(msg)
const shares:Share[] = split(secret, { min: 2, total: 3 })

const restored = reconstruct([shares[0], shares[2]])
console.log(new TextDecoder().decode(restored)) // 'hello shamir'

CommonJS

const { split, reconstruct } = require('@substrate-system/shamirs-secret-sharing')

const secret = Buffer.from('my secret', 'utf8')
const shares = split(secret, { min: 2, total: 3 })
const restored = reconstruct([shares[0], shares[1]])
console.log(Buffer.from(restored).toString('utf8'))

Pre-built JS for browsers

This package exposes minified JS files too. Copy them to a location that is accessible to your web server, then link to them in HTML.

copy

cp ./node_modules/@substrate-system/shamirs-secret-sharing/dist/index.min.js ./public/sss.min.js

HTML

<script type="module" src="./sss.min.js"></script>

API

split

Return an array of Share objects. At least min number of distinct shares are needed to reconstruct the secret.

function split (
  secret:Uint8Array,
  options:{ min:number; total:number }
):Share[]
  • secret: The bytes to protect (any Uint8Array: text, keys, binary data).
  • options.min: Threshold k. Must be >= 2 and <= total.
  • options.total: Number of shares n to generate. Max 254.

reconstruct

Return the original Uint8Array secret. Throws if insufficient shares are provided.

function reconstruct(shares:Share[]):Uint8Array
  • shares: An array of shares with the same threshold and length.

Share

interface Share {
  x:number            // share index in [1..254]
  y:Uint8Array        // share bytes (same length as secret)
  threshold?:number   // k; included for convenience
}

Serialization:

import { toString as u8ToString } from 'uint8arrays/to-string'
import { fromString as u8FromString } from 'uint8arrays/from-string'

const encoded = u8ToString(share.y, 'base64')
const decoded = u8FromString(encoded, 'base64')

Limits and notes

  • Maximum shares: 254 (GF(256) constraint).
  • Threshold must be between 2 and total.
  • All shares must be from the same split call (same secret length and params).
  • Randomness: coefficients are generated using WebCrypto via @substrate-system/one-webcrypto for wide platform compatibility.
  • Performance: linear in secret length and number of shares.

FAQ

  • How big are shares? – Exactly the same length as the secret bytes plus small constant metadata (x, optional threshold).
  • Can I split strings? – Yes. Encode to bytes with TextEncoder, and decode with TextDecoder after reconstruction.
  • Is Node supported? – Yes. Use ESM or CJS as shown above.
  • Is there a demo UI? – Yes, see example/ and the hosted demo linked above.