JSPM

@forgesworn/ring-sig

0.0.0-development
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 53
  • Score
    100M100P100Q94698F
  • License MIT

SAG and LSAG ring signatures on secp256k1 — prove group membership without revealing identity

Package Exports

  • @forgesworn/ring-sig

Readme

@forgesworn/ring-sig

SAG and LSAG ring signatures on secp256k1.

Prove group membership without revealing identity.

Use cases

  • Anonymous group membership proofs — prove you are one of N key holders without revealing which one
  • Whistleblowing — sign a statement as "a member of this organisation" without self-identifying
  • Privacy-preserving attestation — "a licensed professional verified this" without naming the professional
  • Double-action prevention (LSAG) — detect if the same key signs twice in the same context, without linking signatures across contexts

Install

npm install @forgesworn/ring-sig

Usage

SAG — Spontaneous Anonymous Group signatures

import { ringSign, ringVerify } from '@forgesworn/ring-sig';

// A ring of x-only public keys (32 bytes, hex)
const ring = [pubkey0, pubkey1, pubkey2, pubkey3];

// Sign as ring member at index 2
const sig = ringSign('my message', ring, 2, privateKey2);

// Anyone can verify the signature is from a ring member
const valid = ringVerify(sig); // true

LSAG — Linkable SAG (double-action detection via key images)

import { lsagSign, lsagVerify, computeKeyImage, hasDuplicateKeyImage } from '@forgesworn/ring-sig';

const electionId = 'vote-2026-q1';
const ring = [pubkey0, pubkey1, pubkey2];

// Sign
const sig = lsagSign('candidate-A', ring, 0, privateKey0, electionId);

// Verify
const valid = lsagVerify(sig); // true

// Detect double-signing: key images are deterministic per (key, electionId) pair
const keyImage = computeKeyImage(privateKey0, pubkey0, electionId);
const isDuplicate = hasDuplicateKeyImage(keyImage, existingKeyImages);

Domain separators

Both ringSign and lsagSign accept an optional domain parameter (defaults to 'sag-v1' / 'lsag-v1'). Pass a custom domain if you need cross-protocol isolation:

const sig = ringSign(message, ring, index, privateKey, 'my-app-v1');

Error classes

  • RingSignatureError — base class
  • ValidationError — malformed inputs, bounds exceeded
  • CryptoError — invalid keys, failed operations

Cryptography

  • SAG (Spontaneous Anonymous Group): Schnorr-based ring signature. Signature size is O(n) with the ring.
  • LSAG (Linkable SAG): Adds a deterministic key image I = x * H_p(P || context). Signatures by the same key in the same context produce identical key images, enabling double-action detection without cross-context linkability.
  • Domain separation: 'sag-v1', 'lsag-v1', 'secp256k1-hash-to-point-v1'
  • Maximum ring size: 1000 members

Licence

MIT