-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* bls signature for basic account * benchmark for bls and ed25519 * added bls sig verify cost to genesis * Revert "Merge branch 'fetchai:master' into bls" This reverts commit a5dd8ea, reversing changes made to 082e071. * format using go tools * nuisance golangci-lint errors * POP interfaces in accounts and authentication * add bls multsig operations * fixed golangci-lint error * changes after comments
- Loading branch information
Showing
10 changed files
with
372 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package bls12381 | ||
|
||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
|
||
blst "github.com/supranational/blst/bindings/go" | ||
) | ||
|
||
func aggregatePublicKey(pks []*PubKey) (*blst.P1Affine, error) { | ||
pubkeys := make([]*blst.P1Affine, len(pks)) | ||
for i, pk := range pks { | ||
pubkeys[i] = new(blst.P1Affine).Deserialize(pk.Key) | ||
if pubkeys[i] == nil { | ||
return nil, fmt.Errorf("failed to deserialize public key") | ||
} | ||
} | ||
|
||
aggregator := new(blst.P1Aggregate) | ||
b := aggregator.Aggregate(pubkeys, false) | ||
if !b { | ||
return nil, fmt.Errorf("failed to aggregate public keys") | ||
} | ||
apk := aggregator.ToAffine() | ||
|
||
return apk, nil | ||
} | ||
|
||
// AggregateSignature combines a set of verified signatures into a single bls signature | ||
func AggregateSignature(sigs [][]byte) ([]byte, error) { | ||
sigmas := make([]*blst.P2Affine, len(sigs)) | ||
for i, sig := range sigs { | ||
sigmas[i] = new(blst.P2Affine).Uncompress(sig) | ||
if sigmas[i] == nil { | ||
return nil, fmt.Errorf("failed to deserialize the %d-th signature", i) | ||
} | ||
} | ||
|
||
aggregator := new(blst.P2Aggregate) | ||
b := aggregator.Aggregate(sigmas, false) | ||
if !b { | ||
return nil, fmt.Errorf("failed to aggregate signatures") | ||
} | ||
aggSigBytes := aggregator.ToAffine().Compress() | ||
return aggSigBytes, nil | ||
} | ||
|
||
// VerifyMultiSignature assumes public key is already validated | ||
func VerifyMultiSignature(msg []byte, sig []byte, pks []*PubKey) error { | ||
return VerifyAggregateSignature([][]byte{msg}, sig, [][]*PubKey{pks}) | ||
} | ||
|
||
func Unique(msgs [][]byte) bool { | ||
if len(msgs) <= 1 { | ||
return true | ||
} | ||
msgMap := make(map[string]bool, len(msgs)) | ||
for _, msg := range msgs { | ||
s := base64.StdEncoding.EncodeToString(msg) | ||
if _, ok := msgMap[s]; ok { | ||
return false | ||
} | ||
msgMap[s] = true | ||
} | ||
return true | ||
} | ||
|
||
func VerifyAggregateSignature(msgs [][]byte, sig []byte, pkss [][]*PubKey) error { | ||
n := len(msgs) | ||
if n == 0 { | ||
return fmt.Errorf("messages cannot be empty") | ||
} | ||
|
||
if len(pkss) != n { | ||
return fmt.Errorf("the number of messages and public key sets must match") | ||
} | ||
|
||
if !Unique(msgs) { | ||
return fmt.Errorf("messages must be pairwise distinct") | ||
} | ||
|
||
apks := make([]*blst.P1Affine, len(pkss)) | ||
for i, pks := range pkss { | ||
apk, err := aggregatePublicKey(pks) | ||
if err != nil { | ||
return fmt.Errorf("cannot aggregate public keys: %s", err.Error()) | ||
} | ||
apks[i] = apk | ||
} | ||
|
||
sigma := new(blst.P2Affine).Uncompress(sig) | ||
if sigma == nil { | ||
return fmt.Errorf("failed to deserialize signature") | ||
} | ||
|
||
dst := []byte("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_") | ||
if !sigma.AggregateVerify(true, apks, false, msgs, dst) { | ||
return fmt.Errorf("failed to verify signature") | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package bls12381_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
|
||
bls "github.com/cosmos/cosmos-sdk/crypto/keys/bls12381" | ||
) | ||
|
||
func TestBlsMultiSig(t *testing.T) { | ||
total := 5 | ||
pks := make([]*bls.PubKey, total) | ||
sigs := make([][]byte, total) | ||
msg := []byte("hello world") | ||
for i := 0; i < total; i++ { | ||
sk := bls.GenPrivKey() | ||
pk, ok := sk.PubKey().(*bls.PubKey) | ||
require.True(t, ok) | ||
|
||
sig, err := sk.Sign(msg) | ||
require.Nil(t, err) | ||
|
||
pks[i] = pk | ||
sigs[i] = sig | ||
} | ||
|
||
aggSig, err := bls.AggregateSignature(sigs) | ||
require.Nil(t, err) | ||
|
||
assert.Nil(t, bls.VerifyMultiSignature(msg, aggSig, pks)) | ||
|
||
} | ||
|
||
func TestBlsAggSig(t *testing.T) { | ||
total := 5 | ||
pks := make([][]*bls.PubKey, total) | ||
sigs := make([][]byte, total) | ||
msgs := make([][]byte, total) | ||
for i := 0; i < total; i++ { | ||
msgs[i] = []byte(fmt.Sprintf("message %d", i)) | ||
sk := bls.GenPrivKey() | ||
pk, ok := sk.PubKey().(*bls.PubKey) | ||
require.True(t, ok) | ||
|
||
sig, err := sk.Sign(msgs[i]) | ||
require.Nil(t, err) | ||
|
||
pks[i] = []*bls.PubKey{pk} | ||
sigs[i] = sig | ||
} | ||
|
||
aggSig, err := bls.AggregateSignature(sigs) | ||
require.Nil(t, err) | ||
|
||
assert.Nil(t, bls.VerifyAggregateSignature(msgs, aggSig, pks)) | ||
|
||
} | ||
|
||
func benchmarkBlsVerifyMulti(total int, b *testing.B) { | ||
pks := make([]*bls.PubKey, total) | ||
sigs := make([][]byte, total) | ||
msg := []byte("hello world") | ||
for i := 0; i < total; i++ { | ||
sk := bls.GenPrivKey() | ||
pk, ok := sk.PubKey().(*bls.PubKey) | ||
require.True(b, ok) | ||
|
||
sig, err := sk.Sign(msg) | ||
require.Nil(b, err) | ||
|
||
pks[i] = pk | ||
sigs[i] = sig | ||
} | ||
|
||
aggSig, err := bls.AggregateSignature(sigs) | ||
require.Nil(b, err) | ||
|
||
b.ResetTimer() | ||
for i := 0; i < b.N; i++ { | ||
bls.VerifyMultiSignature(msg, aggSig, pks) | ||
} | ||
} | ||
|
||
func BenchmarkBlsVerifyMulti8(b *testing.B) { benchmarkBlsVerifyMulti(8, b) } | ||
func BenchmarkBlsVerifyMulti16(b *testing.B) { benchmarkBlsVerifyMulti(16, b) } | ||
func BenchmarkBlsVerifyMulti32(b *testing.B) { benchmarkBlsVerifyMulti(32, b) } | ||
func BenchmarkBlsVerifyMulti64(b *testing.B) { benchmarkBlsVerifyMulti(64, b) } | ||
func BenchmarkBlsVerifyMulti128(b *testing.B) { benchmarkBlsVerifyMulti(128, b) } | ||
|
||
func benchmarkBlsVerifyAgg(total int, b *testing.B) { | ||
pks := make([][]*bls.PubKey, total) | ||
sigs := make([][]byte, total) | ||
msgs := make([][]byte, total) | ||
for i := 0; i < total; i++ { | ||
msgs[i] = []byte(fmt.Sprintf("message %d", i)) | ||
sk := bls.GenPrivKey() | ||
pk, ok := sk.PubKey().(*bls.PubKey) | ||
require.True(b, ok) | ||
|
||
sig, err := sk.Sign(msgs[i]) | ||
require.Nil(b, err) | ||
|
||
pks[i] = []*bls.PubKey{pk} | ||
sigs[i] = sig | ||
} | ||
|
||
aggSig, err := bls.AggregateSignature(sigs) | ||
require.Nil(b, err) | ||
|
||
b.ResetTimer() | ||
|
||
for i := 0; i < b.N; i++ { | ||
bls.VerifyAggregateSignature(msgs, aggSig, pks) | ||
} | ||
} | ||
|
||
func BenchmarkBlsVerifyAgg8(b *testing.B) { benchmarkBlsVerifyAgg(8, b) } | ||
func BenchmarkBlsVerifyAgg16(b *testing.B) { benchmarkBlsVerifyAgg(16, b) } | ||
func BenchmarkBlsVerifyAgg32(b *testing.B) { benchmarkBlsVerifyAgg(32, b) } | ||
func BenchmarkBlsVerifyAgg64(b *testing.B) { benchmarkBlsVerifyAgg(64, b) } | ||
func BenchmarkBlsVerifyAgg128(b *testing.B) { benchmarkBlsVerifyAgg(128, b) } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.