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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@cypher-laboratory/alicesring-sag

v0.2.0

Published

A TypeScript implementation of SAG ring signatures.

Downloads

104

Readme

types-Ring-Signature

This repository contains a TypeScript implementation of the Ring Signature algorithm using Spontaneous Anonymous Group (SAG).

About the implementation

The implementation is based on the SAG algorithm and uses the Elliptic Curve Cryptography (ECC) to generate the keys and sign the message.

We used the implementation proposed in Zero to Monero (p.36) as a reference.

Audit

The audit of this library was conducted by the company CryptoExperts https://www.cryptoexperts.com/ on March 13th, 2024. All vulnerabilities identified in the course of the audit have been fixed in agreement and under the supervision of CryptoExperts.

Usage

import { RingSignature , Curve , CurveName , Point } from '@cypherlab/types-ring-signature';

const curve: Curve = new Curve(CurveName.SECP256K1);
const ring: Point[] = []; // your ring of public keys
const message = 'Hello World!';

const signerPrivateKey = BigInt('your private key');

// Sign
const signature: RingSignature = RingSignature.sign(
  ring,
  signerPrivateKey,
  message,
  curve,
);

// Verify
console.log(
  "Is signature verified? ", signature.verify()
);

// Export to jsonString
const jsonString = signature.toJsonString();

// Import from jsonString
const retrievedFromJson = RingSignature.fromJsonString(jsonString);

Dependencies

| Dependency | Version | repo |audit report |dependencies| |-------------------|---------|-----------------------------------------|-------------------------------------------------|------------| | @noble/hashes | ^1.3.2 |GitHub|Report|NPM|

Dev Dependencies

| Dev Dependency | Version | Repository | |-------------------------------------|----------|-------------------------------------------------------------------------------------| | @types/jest | ^29.5.7 | GitHub | | @types/node | ^20.8.7 | GitHub | | @typescript-eslint/eslint-plugin | ^5.61.0 | GitHub | | @typescript-eslint/parser | ^5.61.0 | GitHub | | eslint | ^8.44.0 | GitHub | | jest | ^29.7.0 | GitHub | | prettier | ^3.0.0 | GitHub | | ts-jest | ^29.1.1 | GitHub | | ts-node | ^10.9.1 | GitHub |

Spontaneous Anonymous Group (SAG) Signatures

Group Setup

When setting up a group for cryptographic purposes, such as for a Spontaneous Anonymous Group (SAG) signature scheme, there are two primary methods to establish the group members' public keys:

  • using existing public keys of the members from publicly available data such as blockchains. This method is suitable for scenarios where the group members have a common caracteristics, such as being part of the same organization or having a specific role. For example, a group of members of a company's board of directors can be identified by their public keys, which are publicly available on the company's website.
  • using a group key generation algorithm to generate the public keys of the members. This method is suitable for scenarios where the group members are not known in advance, such as in a voting system. For example, a group of voters can be identified by their public keys, which are generated by the voting system's key generation algorithm.

Signature Generation

Let $l$ be the number of members in the group.
Let $R$ be a set of public keys of the group members such as $R$ = { $K_{0}$ , $K_{1}$ , ..., $K_{n}$ } where n be the number of members in the group minus 1 ($l = n + 1$).
Let $m$ be the digest of the message to be signed.
Let $H$ be a hash function.
Let $k$ be a random integer in the range $[1, N-1]$. This is the private key of the signer.
Let $\pi$ be the signer position in the group. This is a random integer in the range $[0, n]$.

The signer computes the following:

  • Generates a random integer $\alpha$ in the range [1, N-1]
  • Generates random responses r = { $r_{0}$ , $r_{1}$ , ... , $r_{\pi-1}$, $r_{\pi+1}$, ... , $r_{n}$ } where $r_{i}$ ($0 <= i <= n$ excluding $\pi$) is a random integer in the range $[1, N-1]$
  • Computes $c_{\pi+1} = H(R, m, [\alpha G])$
  • For $j$ in $[\pi + 1, l + \pi]$ computes the following:
    • $i = mod(j, l)$ -> allows to loop over the group members
    • $s = i - 1$ if $i > 0$ else $l - 1$ -> $s = i - 1$ except when $i = 0$. In this case, $s = l - 1$
    • $c_{i+1} = H(R, m, [r_{s}G + c_{s}K_{s}])$
  • Define the signer's response to verify $\alpha = r_{\pi} + c_{\pi}k$ ($mod$ $N$)

The signature contains the following:

  • the ring of public keys $R$
  • the challenge $c_{1}$
  • the responses $r$ = { $r_{0}$ , $r_{1}$ , ... , $r_{n}$ }

Signature Verification

Known data:

  • the ring of public keys $R$
  • the seed $c_{0}$
  • the responses $r$ = { $r_{0}$ , $r_{1}$ , ... , $r_{n}$ }
  • the message $m$

The signature is valid if and only if the signature has been generated using one of the group member's private keys.

The verifier computes the following:

  • For $i = 2$ to $n$, with $i$ wrapping around to 1 after $n$:
    • $c_{i}$' = $H( R, m, [ r_{i-1} G$ + $c_{i-1}$' $K_{i-1}$]) if $i ≠ 1$ else $c_{i}$' = $H(R, m, [r_{1}G + c_{1}K_{1}])$
  • If $c_{1}$' = $c_{1}$ then the signature is valid, else it is invalid.

Detailed implementation

RingSignature.sign

This method is designed to compute a ring signature by directly utilizing a private key as input. It's tailored for scenarios where you do not use a wallet for key management. The RingSignature.sign function needs the private key to generate the ring signature.

1. Sort the ring by x ascending (and y ascending if x is equal)

Let $\pi$ be the signer position in the group. This is an integer in the range $[0, n]$.

2. Generate Random Number $\alpha$

It will be use as the nonce.

  • Function: randomBigint
  • Location: src/utils/randomNumber.ts
  • Description: Generates a random bigint in the range [1, max[.
export function randomBigint(max: bigint): bigint

3. Compute $c_{\pi+1}$

$c_{\pi+1} = H(R, m, [\alpha G])$

  • Function: computeC
  • Location: src/ringSignatures.ts
  • Description: Compute a c value.
  • Remarks:
    • This function is used to compute the c value of a ring-signature.
    • Either 'alpha' or all the other keys of 'params' must be set..
  private static computeC(
    ring: Point[],
    messageDigest: bigint,
    params: {
      previousR?: bigint;
      previousC?: bigint;
      previousPubKey?: Point;
      alpha?: bigint;
    },
    curve: Curve,
    config?: SignatureConfig,
  ): bigint 

4. Compute the challenges.

Generates random responses r = {$r_{1}$, ... , $r_{\pi-1}$, $r_{\pi+1}$, ... , $r_{n}$ } where $r_{i}$ ($0 <= i <= n$ excluding $\pi$) is a random integer in the range $[1, N-1]$
For i = ${\pi+1}$, ${\pi+2}$ , ..., n, 1, 2, ..., ${\pi-1}$ calculate, replacing n + 1 → 1,

$c_{i+1} = H(R, m, [r_{s}G - c_{s}K_{s}])$

  • Function: RingSignature.signature
  • Location: src/ringSignature.ts
  • Description: Generate an incomplete ring signature.
  private static signature(
    curve: Curve,
    ring: Point[],
    ceePiPlusOne: bigint,
    signerIndex: number,
    messageDigest: bigint,
    config?: SignatureConfig,
  ): {
    ring: Point[];
    cees: bigint[];
    signerIndex: number;
    responses: bigint[];
  }

5. Compute the signer response $r_{\pi}$

$r_{\pi}$ such that $\alpha = r_{\pi} - c_{\pi}k$ ($mod$ $N$).

  • Function: piSignature
  • Location: src/signature/piSignature.ts
  • Description: Compute the signature from the actual signer.
export function piSignature(
  alpha: bigint,
  c: bigint,
  signerPrivKey: bigint,
  curve: Curve,
): bigint 

6. Return the ring signature

Return the ring-signature.

  • Function: constructor
  • Location: src/ringSignature.ts
  • Description: Ring signature class constructor.
  constructor(
    message: string,
    ring: Point[],
    c: bigint,
    responses: bigint[],
    curve: Curve,
    config?: SignatureConfig,
  ) 

RingSignature.verify

This method verifies if a ring signature is valid.

1. Verify the ring signature

  • Function: RingSignature.verify.ts
  • Location: src/ringSignature.ts
  • Description: Verify a RingSignature.
  verify(): boolean

Sponsors

We would like to thank the XRPL Foundation https://xrpl.org/ for their support and funding, which have allowed this audited library to be developed for the benefit of many.