An implementation of BLS threshold signature
- Windows Visual Studio / MSYS2(MinGW-w64)
- Linux
- macOS
- Android
- iOS
- WebAssembly
This library supports the new BLS Signatures specified at Ethereum 2.0 Phase 0.
bls.h | eth2.0 spec name |
---|---|
blsSign | Sign |
blsVerify | Verify |
blsAggregateSignature | Aggregate |
blsFastAggregateVerify | FastAggregateVerify |
blsAggregateVerifyNoCheck | AggregateVerify |
language | repository |
---|---|
Go | bls-eth-go-binary |
WebAssembly(Node.js) | bls-eth-wasm |
Rust | bls-eth-rust |
#include <mcl/bn384_256.h>
#include <bls/bls.h>
bn384_256.h
is for 384-bit p
and 256-bit r
, where the elliptic curve is defined over Fp
and the order of G1
and G2
is r
.
The compiled static libraries for {linux, windows, darwin}/amd64 and android/{arm64-v8a, armeabi-v7a} are provided at bls-eth-go-binary/bls/lib
On Linux, macOS
make CXX=clang++-8 lib/libbls384_256.a BLS_ETH=1
On Windows
mklib eth
// init library at once before calling the other apis
blsInit(MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR);
// use the latest eth2.0 spec
blsSetETHmode(BLS_ETH_MODE_LATEST);
Init SecretKey sec
and create PublicKey pub
.
blsSecretKey sec;
blsPublicKey pub;
// init SecretKey sec by random number
blsSecretKeySetByCSPRNG(&sec);
// get PublicKey pub from SecretKey sec
blsGetPublicKey(&pub, &sec);
Make Signature sig
of Message msg[0..msgSize-1]
by SecretKey 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 Signature sig
of Message msg[0..msgSize-1]
by PublicKey pub
.
// return 1 if it is valid else 0
int blsVerify(&sig, &pub, msg, msgSize);
Aggregate Signatures sigVec[0]
, ..., sigVec[n-1]
to aggSig
.
// return 1 if it is valid else 0
void blsAggregateSignature(
blsSignature *aggSig,
const blsSignature *sigVec,
mclSize n
);
Verify Signature sig
of 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 each other
Check them at the caller if necessary.
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);
- Go; in ffi/go or bls-go-binary
- C#; in ffi/cs
Create a working directory (e.g., work) and clone the following repositories.
mkdir work
cd work
git clone git://github.com/herumi/mcl.git
git clone git://github.com/herumi/bls.git
git clone git://github.com/herumi/cybozulib_ext ; for only Windows
-
disabled to check the order in setStr/deserialize. call once
blsSignatureVerifyOrder(1)
orblsPublicKeyVerifyOrder(1)
to check it. -
add uncompressed function to PublicKey and Sign
-
add blsSignHashWithDomain, blsVerifyHashWithDomain(see (Ethereum 2.0 spec mode)[https://github.com/herumi/bls/#ethereum-20-spec-mode])
-
rename blsGetGeneratorOfG{1 or 2} to blsGetGeneratorOfPublicKey
-
add blsSetETHserialization(1) to use ETH serialization for BLS12-381
-
Support swap of G1 and G2 for Go (-tags bn384_256_swapg)
-
blsInit() is not thread safe (pthread is not used)
-
-tags option for Go bindings is always necessary
- use -tags bn384_256 for BLS12-381
-
support Android
-
(Break backward compatibility) The suffix
_dy
of library name is removed and bls*.a requires libmcl.so set LD_LIBRARY_PATH to the directory. -
-tags option for Go bindings
- -tags bn256
- -tags bn384_256
- -tags bn384
-
Support swap of G1 and G2
make BLS_SWAP_G=1
then G1 is assigned to PublicKey and G2 is assigned to Signature.
-
Build option without GMP
make MCL_USE_GMP=0
-
Build option without OpenSSL
make MCL_USE_OPENSSL=0
-
Build option to specify
mcl
directorymake MCL_DIR=<mcl directory>
-
(old) libbls.a for C++ interface(bls/bls.hpp) is removed Link
lib/libbls256.a
orlib/libbls384.a
to usebls/bls.hpp
according to MCLBN_FP_UNIT_SIZE = 4 or 6.
To make and test, run
cd bls
make test
To make sample programs, run
make sample_test
- make static library and use it
mklib
mk -s test\bls_c384_test.cpp
bin\bls_c384_test.exe
- make dynamic library and use it
mklib dll
mk -d test\bls_c384_test.cpp
bin\bls_c384_test.exe
see readme.md
cd bls
make gomobile
If you want to swap G1 and G2 for PublicKey and Signature, then type as the followings:
make clean
make BLS_SWAP_G=1
make test_go_swapg ; test for cgo
Remark:
- The library built with BLS_SWAP_G is not compatible with the library built without BLS_SWAP_G.
- Define
-DBLS_SWAP_G' before including
bls/bn.h`.
For eth2,
make clean
make BLS_ETH=1 bin/libbls384_256.a
uint8_t hashWithDomain[40]
in the following apis means a structure of 32 bytes msg and 8 bytes domain.
struct Message {
uint8_t hash[32];
uint8_t domain[8];
};
int blsSignHashWithDomain(blsSignature *sig, const blsSecretKey *sec, const unsigned char hashWithDomain[40]);
return 0 if sccess else -1
int blsVerifyHashWithDomain(const blsSignature *sig, const blsPublicKey *pub, const unsigned char hashWithDomain[40]);
return 1 if valid else 0
aggSig
is aggregated signature of {sig[i]}
corresponding to {pubVec[i]}
.
int blsVerifyAggregatedHashWithDomain(const blsSignature *aggSig, const blsPublicKey *pubVec, const unsigned char hashWithDomain[][40], mclSize n);
return 1 if valid else 0
- libbls256.a/libbls256.so ; for BN254 compiled with MCLBN_FP_UNIT_SIZE=4
- libbls384.a/libbls384.so ; for BN254/BN381_1/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6
- libbls384_256.a/libbls384_256.so ; for BN254/BLS12_381 compiled with MCLBN_FP_UNIT_SIZE=6 and MCLBN_FR_UNIT_SIZE=4
- precompiled static library is provided at bls-go-binary
See mcl/include/curve_type.h
for curve parameter
If there are both a shared library both and static library having the same name in the same directory, then the shared library is linked. So if you want to link a static library, then remove the shared library in the directory.
BLS signature
e : G2 x G1 -> Fp12 ; optimal ate pairing over BN curve
Q in G2 ; fixed global parameter
H : {str} -> G1
s in Fr: secret key
sQ in G2; public key
s H(m) in G1; signature of m
verify ; e(sQ, H(m)) = e(Q, s H(m))
blsInit(MCL_BLS12_381, MCLBN_COMPILED_TIME_VAR); // use BLS12-381
blsSignatureVerifyOrder(0); // disable to check the order of a point in deserializing
blsPublicKeyVerifyOrder(0);
blsSetETHserialization(1); // obey ETH serialization
void bls::init();
Initialize this library. Call this once to use the other api.
void SecretKey::init();
Initialize the instance of SecretKey. s
is a random number.
void SecretKey::getPublicKey(PublicKey& pub) const;
Get public key sQ
for the secret key s
.
void SecretKey::sign(Sign& sign, const std::string& m) const;
Make sign s H(m)
from message m.
bool Sign::verify(const PublicKey& pub, const std::string& m) const;
Verify sign with pub and m and return true if it is valid.
e(sQ, H(m)) == e(Q, s H(m))
void SecretKey::getMasterSecretKey(SecretKeyVec& msk, size_t k) const;
Prepare k-out-of-n secret sharing for the secret key.
msk[0]
is the original secret key s
and msk[i]
for i > 0 are random secret key.
void SecretKey::set(const SecretKeyVec& msk, const Id& id);
Make secret key f(id) from msk and id where f(x) = msk[0] + msk[1] x + ... + msk[k-1] x^{k-1}.
You can make a public key f(id)Q
from each secret key f(id) for id != 0 and sign a message.
void Sign::recover(const SignVec& signVec, const IdVec& idVec);
Collect k pair of sign f(id) H(m)
and id
for a message m and recover the original signature s H(m)
for the secret key s
.
void SecretKey::getPop(Sign& pop) const;
Sign pub and make a pop s H(sQ)
bool Sign::verify(const PublicKey& pub) const;
Verify a public key by pop.
deserializer functions check whether a point has correct order and the cost is heavy for especially G2. If you do not want to check it, then call
void blsSignatureVerifyOrder(false);
void blsPublicKeyVerifyOrder(false);
cf. subgroup attack
make test_go
mkdir ../bls-wasm
make bls-wasm
modified new BSD License http://opensource.org/licenses/BSD-3-Clause
MITSUNARI Shigeo([email protected])