This library is an implementation of BLS threshold signature, which supports the new BLS Signatures specified at Ethereum 2.0 Phase 0.
- 2024/Oct/23 Add a sample for Zig (See ffi/zig/).
- 2023/Aug/17 The performance of Sign is improved.
- 2022/Apr/20 The performance of MulVec got 2x speed for n >= 256, but const attribute of some arguments of MulVec and MultiVerify is removed.
- They may be normalized in processing but the value are not changed.
- 2021/Sep/16 update mcl and improve performance of isValidOrder, which is called from setStr/deserialize.
- 2021/Apr/28 add blsSetGeneratorOfPublicKey to change the generator.
- 2021/Jan/28 check zero public key on BLS_ETH mode
- 2020/Oct/07 add
blsMultiVerify
to process many verification all togather with multi thread.
- Windows Visual Studio / MSYS2(MinGW-w64)
- Linux
- macOS
- Android
- iOS
- WebAssembly
This library supports type-3 pairings such as BN curves and BLS curves. G1, G2, and GT are a cyclic group of prime order r.
e : G1 x G2 -> GT ; pairing
There are two ways for BLS signature.
type | SecretKey | PublicKey | Signature |
---|---|---|---|
default | Fr | G2 | G1 |
ETH2.0 spec (BLS_ETH=1) | Fr | G1 | G2 |
If you need ETH2.0 spec, then use this library with BLS_ETH=1
mode.
If you want to use the same parameters as Ethereum 2.0, just define BLS_ETH
.
If you want to use mcl/bls without BLS_ETH
, then check the following settings.
- Serialization/Deserialization between Fr/G1/G2 and byte sequences.
- call
blsSetETHserialization(1);
to use the same specification as ETH2.0. Serialize()
compresses a point of G1/G2.
- call
- The generator of G1/G2.
- call
blsPublicKeySetHexStr
.
- call
- Hash function from arbitrary byte sequences to G1/G2.
- call
blsSetMapToMode(MCL_MAP_TO_MODE_HASH_TO_CURVE);
to use the same specification as ETH2.0. - call
mclBnG1_setDst
to set up domain separation.
- call
For example, see initForDFINITY for DFINITY compatibility.
language | ETH2.0 spec (PublicKey = G1) | default (PublicKey = G2) |
---|---|---|
Go | bls-eth-go-binary | bls-go-binary |
WebAssembly (Node.js) | bls-eth-wasm | bls-wasm |
Rust | bls-eth-rust | - |
The compiled static libraries with BLS_ETH=1
mode for {windows, darwin}/amd64, linux/{amd64, arm64} and android/{arm64-v8a, armeabi-v7a}
are provided at bls-eth-go-binary/bls/lib.
#define BLS_ETH
#include <mcl/bn384_256.h>
#include <bls/bls.h>
Remark: BLS_ETH
must always be defined before including bls/bls.h
if you need ETH2.0 spec mode.
// init library at once before calling the other APIs
int err = blsInit(MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR);
if (err != 0) {
printf("blsInit err %d\n", err);
exit(1);
}
// use the latest eth2.0 spec
blsSetETHmode(BLS_ETH_MODE_LATEST);
Remark:
blsInit
and some functions which modify global settings such asblsSetETHmode
are NOT thread-safe. The other functions are all thread-safe.blsSetETHmode
is available for onlyBLS_ETH=1
mode.
Init a secret key sec
and create a public key pub
.
blsSecretKey sec;
blsPublicKey pub;
// init SecretKey sec by random number
blsSecretKeySetByCSPRNG(&sec);
// get PublicKey pub from SecretKey sec
blsGetPublicKey(&pub, &sec);
Make a signature sig
of a message msg[0..msgSize-1]
by the secret key sec
.
blsSignature sig;
char msg[] = "hello";
const size_t msgSize = strlen(msg);
blsSign(&sig, &sec, msg, msgSize);
msg
may contain \x00
if the correct msgSize
is specified.
Verify the signature sig
of the message msg[0..msgSize-1]
by the public key pub
.
// return 1 if it is valid else 0
int blsVerify(&sig, &pub, msg, msgSize);
Aggregate Signatures sigVec[0]
, ..., sigVec[n-1]
to aggSig
.
aggSig
is cleared if n = 0
.
void blsAggregateSignature(
blsSignature *aggSig,
const blsSignature *sigVec,
mclSize n
);
Verify a signature sig
of a message msg[0..msgSize-1]
by pubVec[0]
, ..., pubVec[n-1]
.
int blsFastAggregateVerify(
const blsSignature *sig,
const blsPublicKey *pubVec,
mclSize n,
const void *msg,
mclSize msgSize
);
pubVec
isn
array of PublicKeymsgVec
isn * msgSize
-byte array, which concatenatesn
-byte messages of lengthmsgSize
.
Verify Signature sig
of (Message msgVec[msgSize * i..msgSize * (i+1)-1]
and pubVec[i]
) for i = 0
, ..., n-1
.
int blsAggregateVerifyNoCheck(
const blsSignature *sig,
const blsPublicKey *pubVec,
const void *msgVec,
mclSize msgSize,
mclSize n
);
REMARK : blsAggregateVerifyNoCheck
does not check
sig
has the correct order- every
n
-byte messages of lengthmsgSize
are different from each other
Check them at the caller if necessary.
bls.h | eth2.0 spec name |
---|---|
blsSign | Sign |
blsVerify | Verify |
blsAggregateSignature | Aggregate |
blsFastAggregateVerify | FastAggregateVerify |
blsAggregateVerifyNoCheck | AggregateVerify |
int blsSecretKeySetLittleEndianMod(blsSecretKey *sec, const void *buf, mclSize bufSize);
Set sec
to (buf[0..bufSize-1]
as little endian) mod r and return 0 if bufSize <= 64
else -1.
mclSize blsSecretKeySerialize(void *buf, mclSize maxBufSize, const blsSecretKey *sec);
mclSize blsPublicKeySerialize(void *buf, mclSize maxBufSize, const blsPublicKey *pub);
mclSize blsSignatureSerialize(void *buf, mclSize maxBufSize, const blsSignature *sig);
Serialize the instance to buf[0..maxBufSize-1]
and return written byte size if success else 0.
mclSize blsSecretKeyDeserialize(blsSecretKey *sec, const void *buf, mclSize bufSize);
mclSize blsPublicKeyDeserialize(blsPublicKey *pub, const void *buf, mclSize bufSize);
mclSize blsSignatureDeserialize(blsSignature *sig, const void *buf, mclSize bufSize);
Deserialize buf[0..bufSize-1]
to the instance and return read byte size if success else 0.
Check whether sig
and pub
have the correct order r
.
// return 1 if it is valid else 0
int blsSignatureIsValidOrder(const blsSignature *sig);
int blsPublicKeyIsValidOrder(const blsPublicKey *pub);
- Prepare k secret keys (msk).
- Make n secret keys from msk by
blsSecretKeyShare
. - Each user makes the public key from the given secret key.
- Each user makes a signature for the same message.
- Any k subset of n signatures can recover the master signature by
blsSignatureRecover
.
See sample/minsample.c for the details.
int blsSecretKeyShare(blsSecretKey *sec, const blsSecretKey *msk, mclSize k, const blsId *id);
Make sec
corresponding to id
from {msk[i] for i = 0, ..., k-1}
.
int blsSignatureRecover(blsSignature *sig, const blsSignature *sigVec, const blsId *idVec, mclSize n);
Recover sig
from {(sigVec[i], idVec[i]) for i = 0, ..., n-1}
.
blsMultiAggregateSignature
and blsMultiAggregatePublicKey
are provided for BLS Multi-Signatures With Public-Key Aggregation.
The hash function is temporary.
See blsMultiAggregateTest.
void blsMultiAggregateSignature(
blsSignature *aggSig,
blsSignature *sigVec,
blsPublicKey *pubVec,
mclSize n
);
Set aggSig = sum_{i=0^n-1} sigVec[i] t_i, where (t_1, ..., t_n) = Hash({pubVec[0..n-1]})
.
void blsMultiAggregatePublicKey(
blsPublicKey *aggPub,
blsPublicKey *pubVec,
mclSize n
);
Set aggPub = sum_{i=0^n-1} pubVec[i] t_i, where (t_1, ..., t_n) = Hash({pubVec[0..n-1]})
.
The following description is for BLS_ETH=1
mode.
Remove it if you need PublicKey as G1.
git clone --recursive https://github.com/herumi/bls
make -C mcl lib/libmcl.a
make BLS_ETH=1 lib/libbls384_256.a
If the option MCL_USE_GMP=0
(resp.MCL_USE_OPENSSL=0
) is used then GMP (resp. OpenSSL) is not used.
Open the x64 Native Tools for Visual Studio and type the following command.
static library
mklib eth
dynamic library
mklib dll eth
Or open bls.sln
and build it.
REMARK CmakeLists.txt is not maintained for Visual Studio.
- 2020/May/13 :
blsSetETHmode()
supportsBLS_ETH_MODE_DRAFT_07
defined at BLS12381G2_XMD:SHA-256_SSWU_RO_. - 2020/Apr/02 : experimental add blsMultiAggregateSignature/blsMultiAggregatePublicKey multiSig
- The hash function is temporary, which may be modified in the future.
- 2020/Mar/26 : DST of hash-to-curve of mcl is changed, so the output has also changed for
BLS_ETH_MODE_DRAFT_06
. - 2020/Mar/15 :
blsSetETHmode()
supportsBLS_ETH_MODE_DRAFT_06
defined at draft-irtf-cfrg-hash-to-curve at March 2020. But it has not yet fully tested.
modified new BSD License http://opensource.org/licenses/BSD-3-Clause
MITSUNARI Shigeo([email protected])