8bf0c812f5
22b066020c build: match detection of Win32 libraries with mimalloc (#60) 03268b3a02 Merge pull request #59 from kittywhiskers/repair_subtree 3d2e7a183e depends: commit microsoft/mimalloc@91ba1f37 to source tree as 44314dd9 7a4d1a01fa depends: remove mangled 'depends/mimalloc' subdirectory 44314dd972 Squashed 'depends/mimalloc/' content from commit 91ba1f37 8383f081bd dashbls: replace flaky minialloc with microsoft/mimalloc@91ba1f37, add as vendored dependency (#55) 85b7e61b55 fix: Should not check validity for legacy G1 and G2 in FromBytes (#58) 7457939dd5 chore/fix: bump Catch2 to v2.13.10 (#57) git-subtree-dir: src/dashbls git-subtree-split: 22b066020c14bd162022c73f90fc7c940f4acdda |
||
---|---|---|
.. | ||
.gitignore | ||
blschia.cpp | ||
blschia.h | ||
elements.cpp | ||
elements.go | ||
elements.h | ||
error.go | ||
error.h | ||
go.mod | ||
go.sum | ||
Makefile | ||
privatekey.cpp | ||
privatekey.go | ||
privatekey.h | ||
README.md | ||
schemes_test.go | ||
schemes.cpp | ||
schemes.go | ||
schemes.h | ||
threshold_test.go | ||
threshold.cpp | ||
threshold.go | ||
threshold.h | ||
util_test.go | ||
util.go | ||
utils.cpp | ||
utils.hpp |
bls-signatures
Go library that implements BLS signatures with aggregation as in Boneh, Drijvers, Neven 2018, using the relic toolkit for cryptographic primitives (pairings, EC, hashing).
This library is a Go port of the Chia Network's BLS lib.
Usage
go get github.com/dashpay/bls-signatures/go-bindings
Creating keys and signatures
// seed data must not be less 32 bytes length
seed := []byte{
0, 50, 6, 244, 24, 199, 1, 25,
52, 88, 192, 19, 18, 12, 89, 6,
220, 18, 102, 58, 209, 82, 12, 62,
89, 110, 182, 9, 44, 20, 254, 22,
}
// create a scheme, available three schemes: BasicSchemeMPL, AugSchemeMPL and PopSchemeMPL
scheme := NewAugSchemeMPL()
// generate a private key using a seed data
sk, err := scheme.KeyGen(seed)
if err != nil {
panic(err.Error())
}
// get a public key
pk, err := sk.G1Element()
if err != nil {
panic(err.Error())
}
msg := []byte{1, 2, 3, 4, 5}
// make a signature for a message
sig := scheme.Sign(sk, msg)
// verify the message signature
if !scheme.Verify(pk, msg, sig) {
panic("failed the signature verification")
}
Serializing keys and signatures to bytes
skBytes := sk.Serialize()
pkBytes := pk.Serialize()
sigBytes := sig.Serialize()
Loading keys and signatures from bytes
sk1, _ := PrivateKeyFromBytes(skBytes, false)
pk1, _ := G1ElementFromBytes(pkBytes)
sig1, _ := G2ElementFromBytes(sigBytes)
Create aggregate signatures
// Generate some more private keys
seed[0] = 1
sk1, _ := scheme.KeyGen(seed)
seed[0] = 2
sk2, _ := scheme.KeyGen(seed)
msg2 := []byte{1, 2, 3, 4, 5,6, 7}
// Generate first sig
pk1, _ := sk1.G1Element()
sig1 := scheme.Sign(sk1, msg)
// Generate second sig
pk2, _ := sk2.G1Element()
sig2 := scheme.Sign(sk2, msg2)
// Signatures can be non-interactively combined by anyone
var aggSig = scheme.AggregateSigs(sig1, sig2)
ok := scheme.AggregateVerify([]*G1Element{pk1, pk2}, [][]byte{msg, msg2}, aggSig)
if !ok {
panic("failed a verification of the aggregated signature ")
}
Arbitrary trees of aggregates
seed[0] = 3
sk3, _ := scheme.KeyGen(seed)
pk3, _ := sk3.G1Element()
msg3 := []byte{100, 2, 254, 88, 90, 45, 23}
sig3 := scheme.Sign(sk3, msg3)
aggSigFinal := scheme.AggregateSigs(aggSig, sig3)
ok = scheme.AggregateVerify([]*G1Element{pk1, pk2, pk3}, [][]byte{msg, msg2, msg3}, aggSigFinal)
if !ok {
panic("failed a verification of the aggregated signature ")
}
Very fast verification with Proof of Possession scheme
// create a proof possession scheme
popScheme := NewPopSchemeMPL()
// If the same msg is signed, you can use Proof of Possession (PopScheme) for efficiency
// A proof of possession MUST be passed around with the PK to ensure security.
popSig1 := popScheme.Sign(sk1, msg)
popSig2 := popScheme.Sign(sk2, msg)
popSig3 := popScheme.Sign(sk3, msg)
pop1 := popScheme.PopProve(sk1)
pop2 := popScheme.PopProve(sk2)
pop3 := popScheme.PopProve(sk3)
ok = popScheme.PopVerify(pk1, pop1)
if !ok {
panic("failed a verification")
}
ok = popScheme.PopVerify(pk2, pop2)
if !ok {
panic("failed a verification")
}
ok = popScheme.PopVerify(pk3, pop3)
if !ok {
panic("failed a verification")
}
popSigAgg := popScheme.AggregateSigs(popSig1, popSig2, popSig3)
ok = popScheme.FastAggregateVerify([]*G1Element{pk1, pk2, pk3}, msg, popSigAgg)
if !ok {
panic("failed a verification")
}
// Aggregate public key, indistinguishable from a single public key
var popAggPk = pk1.Add(pk2).Add(pk3)
ok = popScheme.Verify(popAggPk, msg, popSigAgg)
if !ok {
panic("failed a verification")
}
// Aggregate private keys
var aggSk = PrivateKeyAggregate(sk1, sk2, sk3)
ok = popScheme.Sign(aggSk, msg).EqualTo(popSigAgg)
if !ok {
panic("failed a verification")
}
HD keys using EIP-2333
// You can derive 'child' keys from any key, to create arbitrary trees. 4 byte indeces are used.
// Hardened (more secure, but no parent pk -> child pk)
masterSk, _ := augScheme.KeyGen(seed)
// Unhardened (less secure, but can go from parent pk -> child pk), BIP32 style
masterPk, _ := masterSk.G1Element()
childU := augScheme.DeriveChildSkUnhardened(masterSk, 22)
grandchildU := augScheme.DeriveChildSkUnhardened(childU, 0)
childUPk := augScheme.DeriveChildPkUnhardened(masterPk, 22)
grandchildUPk := augScheme.DeriveChildPkUnhardened(childUPk, 0)
pkChildU, _ := grandchildU.G1Element()
ok = grandchildUPk.EqualTo(pkChildU)
if !ok {
panic("keys are not equal")
}
Do not forget to handle the errors properly, this part of the code was omitted deliberately
Use cases can be found in the original lib's readme.
Important note: Since this library is a port of the c++ library, so every piece of memory allocated by the library
MUST be released on our own in GO. To release the memory is used runtime.SetFinalizer
function, that will invoke
automatically before GC release a memory allocated by GO.
Run tests
To run tests, build the library, then go to the go-bindings
folder in the build directory and run
make test