This repository contains a TypeScript implementation of the Ring Signature algorithm using Spontaneous Anonymous Group (SAG).
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.
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.
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);
Dependency | Version | repo | audit report | dependencies |
---|---|---|---|---|
@noble/hashes | ^1.3.2 | GitHub | Report | NPM |
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 |
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.
Let
Let
Let
Let
Let
Let
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}$ }
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.
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.
Let
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
- 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
Generates random responses r = {$r_{1}$, ... ,
For i =
- 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[];
}
- 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
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,
)
This method verifies if a ring signature is valid.
- Function:
RingSignature.verify.ts
- Location:
src/ringSignature.ts
- Description: Verify a RingSignature.
verify(): boolean
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.