This repository contains two cryptographic primitives which can be further developed for the o1.js library.
- BLS
- Shamir Secret Sharing
BLS (Boneh–lynn–shacham) signature scheme is a digital signature scheme that is based on elliptic curve cryptography. This repository shows the attempt of trying to implement the BLS signature using o1js
. The basic ingredients are:
- Elliptic curve groups
$\mathbb{G}_1$ ,$\mathbb{G}_2$ and$\mathbb{G}_T$ (with their corresponding generators$g_1$ ,$g_2$ and$g_T$ ). - A random number
$x$ that will be used as the private key. - A hash function
$h$ . - A bilinear pairing
$e$ .
- Generate a random number
$x$ . - Compute the public key
$g_1^x$ . - Sign a message
$m$ by computing$h(m)^x$ . - Verify the signature by checking if
$e(h(m)^x,g_1) = e(h(m), g_1^x)$ .
For BLS, the elliptic curve that is canonically used is the BLS12-381 curve, so our first step consisted in creating this elliptic curve object via the API exposed by o1js
. However, we found that the API does not allow for the creation of curves whose base field is greater than 256 bits. Hence, we had to choose a different curve. Furthermore we noticed that the BLS12_381
parameters provided in the curve examples parameters for o1js
was not correct, so we opened a pull request fixing this.
The chosen alternative was AltBN128 (the same curve used for zkSnarks in Ethereum) because it is a pairing friendly curve that can be defined by o1js
. Using the o1js
API, we created the elliptic curve object as follows:
import {
Crypto,
createForeignCurve
} from "o1js";
export { AltBn128 };
const alt_bn128Params: Crypto.CurveParams = {
name: 'BN254',
modulus: 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47n,
order: 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n,
a: 0n,
b: 3n,
generator: {
x: 1n,
y: 2n,
},
};
class AltBn128 extends createForeignCurve(alt_bn128Params) {};
The next step was to create the elliptic curve groups
In the case of BLS12-381,
For
The field extension
As far as we know, there is no direct way to create the field extension $\mathbb{F}{p^2}$ using the o1js
API. So we attempted to create our custom class for this see this incomplete source code by considering arrays of the form [a, b]
as the elements of $\mathbb{F}{p^2}$.
And basically here is where we had to stop (due to time constraints).
The idea was then to extend the o1js
base class for elliptic curve so that it worked with extension fields... But that would have been a feat itself.
The next group, $\mathbb{G}T$ is the target group of the bilinear pairing, which is a curve defined over the extension field $\mathbb{F}{p^{12}}$. Since this field has a large number of elements, specifically $\left|\mathbb{F}{p^{12}}\right|=\left|\mathbb{F}{p}\right|^{12}=p^{12}$, one usually uses extension field towers to represent the elements of $\mathbb{F}{p^{12}}$ as elements of $\mathbb{F}{p^2}$.
Then, it would also be necessary to define curve twists (by some custom class) so that the bilinear pairing could be computed efficiently...
And finally we'd have to compute the pairing itself (the optimal Ate Pairing which requires computing roots of unity...). Most of these steps are not trivial, require some advanced understanding of elliptic curve cryptography and unfortunately aren't yet supported by the current o1js
API.
Understanding the pitfalls of implementing BLS was a key element for this project. The following references were used:
- Wikipedia BLS Digital Signature
- Attractive Subfamilies of BLS Curves for Implementing High-Security Pairings
- Stanford Cryptography BLS curves
- Pairing-friendly curves at the 128-bit security level
- BLS12-381 for the rest of us
- Aztec Yellowpaper
- Ethereum AltBN128 Ecc
- BN254 for the rest of us
- Co-factor clearing and subgroup membership testing on pairing-friendly curves
Shamir's Secret Sharing is a cryptographic technique for dividing a
The main idea resides in the construction of a polynomial of degree
and shares are created by computing
Using O1.js
, a zero-knowledge proof can be generated during the creation of each share, allowing share holders to prove their ownership without reconstructing the secret. This is particularly useful for verifying the authenticity of shares, especially for users with significant roles or influence, and therefore prevent fake share ownership claims.
npm run build
node build/src/ShamirSecret.js
- Chose a secret work or sentence, transform it into its ascii representation typed to number
// Create secret
const secret = "BOBER";
// Convert string to ascii numbers
const asciiNumbers = stringToAsciiNumber(secret);
console.log(`secret '${secret}' to number: ${asciiNumbers}`);
- Compute polynomial and return points
// Shares to break secret into
const k = 3;
// Compute polynomial and return points in plane
const points = generatePoints(asciiNumbers, k);
- Theoretical POC: Shares are encoded and the proof of generation is also returned. Each share is linked to a proof which can be passed to a
verifyShareProof()
function to prove that a user with a share also has its respective proof.
// Encode points into Base64 to represent shares
const encodedShares, proofs = encodeShares(points);
// Verify that user holds a real share by computing the proof
bool result = verifyShareProof(proofs);
result.assert(true);
// Decode shares and use Lagrange Interpolation to retrieve points
const retrievedPoints = decodeShares(encodedShares, proofs);
const reconstructedSecret = reconstructSecret(retrievedPoints, k);
console.log(`Reconstructed secret: ${reconstructedSecret.toString()}`);