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/cggmp

v0.0.0

Published

Distributed key generation

Readme

cggmp

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

CGGMP

CGGMP (Canetti, Gennaro, Goldfeder, Makriyannis, Peled) distributed key generation protocol

CGGMP is a threshold signature protocol. Multiple parties are able to collaboratively generate a shared cryptographic key, and no single party ever sees the full private key.

3 rounds:

  1. Round 1: Each party generates a random polynomial, creates Feldman VSS commitments, generates a Paillier keypair for homomorphic encryption, and distributes encrypted shares to other parties along with zero-knowledge proofs.
  2. Round 2: Parties verify received shares against VSS commitments and open their Round 1 commitments to ensure all data was committed before shares were revealed
  3. Round 3: A complaint round where parties can identify and disqualify malicious participants who provided invalid shares

Upon completion, each party holds a secret share and all parties agree on the same public key. The secret shares can later be used in the CGGMP signing protocol to produce threshold signatures without reconstructing the private key.

install

npm i -S @substrate-system/cggmp

API

This exposes ESM and common JS via package.json exports field.

ESM

import '@substrate-system/cggmp'

Common JS

require('@substrate-system/cggmp')

use

JS

import '@substrate-system/cggmp'

pre-built JS

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/cggmp/dist/index.min.js ./public/cggmp.js

HTML

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

Example

Distributed Key Generation

Generate a threshold key where any 3 of 5 parties can sign. All parties are running locally for example purposes.

import { DKGCoordinator } from '@substrate-system/cggmp'

// Create a coordinator for 5 parties with threshold 3

const n = 5  // total parties
const t = 3  // threshold (minimum parties needed to sign)
const coordinator = await DKGCoordinator.init(n, t)
const outputs = coordinator.output!

// Each party now has:
//   - A secret share
//   - The shared public key (same for all parties)
//   - Public key shares for all parties
//   - Paillier encryption keys for all parties

for (const [partyId, output] of outputs) {
    console.log(`Party ${partyId}:`)
    console.log(`  Secret share: ${output.secretShare}`)
    console.log(`  Public key: ${Buffer.from(output.publicKey).toString('hex')}`)
    console.log(`  Has ${output.paillierKeys.size} Paillier keys`)
}

// All parties computed the same public key
const [output1, output2] = Array.from(outputs.values())
const samePublicKey = Buffer.from(output1.publicKey)
    .equals(Buffer.from(output2.publicKey))

console.log(`All parties agree on public key: ${samePublicKey}`)

Distributed Setup

In real life, each party runs on a separate machine.

[!IMPORTANT]
Parties must coordinate to establish their IDs.

import { DKGParty } from '@substrate-system/cggmp'

// Each party creates their own DKGParty instance
const party = new DKGParty({
    n: 5,
    t: 3,
    partyId: 1,  // This party's ID (1-5) (should coordinate with other parties)
    paillierBits: 2048
})

// Round 1: Generate and broadcast commitments
const { broadcast, p2pMessages } = await party.round1()

// Send broadcast to all parties via your network layer
await network.broadcast(broadcast)

// Send P2P messages to specific parties
for (const msg of p2pMessages) {
    await network.sendTo(msg.toParty, msg)
}

// Receive and process broadcasts from other parties
for (const otherBroadcast of await network.receiveBroadcasts()) {
    const success = party.processRound1Broadcast(otherBroadcast)
    if (!success) {
        throw new Error('Invalid broadcast received')
    }
}

// Receive and process P2P messages
for (const p2pMsg of await network.receiveP2PMessages()) {
    party.processRound1P2P(p2pMsg)
}

// Round 2: Verify shares and open commitments
const round2Broadcast = party.round2()
await network.broadcast(round2Broadcast)

// Process Round 2 broadcasts...
for (const otherBroadcast of await network.receiveBroadcasts()) {
    party.processRound2Broadcast(otherBroadcast)
}

// Round 3: Complaints (if any)
const round3Broadcast = party.round3()
await network.broadcast(round3Broadcast)

// Finalize and get output
const output = party.finalize()

// Now this party has:
// - output.secretShare: This party's secret share (keep private!)
// - output.publicKey: The shared public key
// - output.paillierKeys: Paillier keys for all parties

Threshold Signing

Threshold signing is not implemented in this library. To sign, any t parties (3 in the example above) could cooperate to sign messages without reconstructing the full private key. Each party would use their secretShare from the DKG output to participate in the signing protocol.