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
blsMultiVerifyto process many verification all together 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_setDstto 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:
blsInitand some functions which modify global settings such asblsSetETHmodeare NOT thread-safe. The other functions are all thread-safe.blsSetETHmodeis available for onlyBLS_ETH=1mode.
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
);
pubVecisnarray of PublicKeymsgVecisn * 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
sighas the correct order- every
n-byte messages of lengthmsgSizeare 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 -f Makefile.onelib LIB_DIR=lib
CMakeLists.txt generates a shared library with libmcl.
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_07defined 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_06defined 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])