mirror of
https://github.com/sonr-io/crypto.git
synced 2026-08-02 15:31:38 +00:00
963 lines
24 KiB
Go
963 lines
24 KiB
Go
//
|
|||
|
|
// Copyright Coinbase, Inc. All Rights Reserved.
|
||
|
|
//
|
||
|
|
// SPDX-License-Identifier: Apache-2.0
|
||
|
|
//
|
||
|
|
|
||
|
|
package bls_sig
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"math/big"
|
||
|
|
"math/rand"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/sonr-io/sonr/crypto/core/curves/native/bls12381"
|
||
|
|
)
|
||
|
|
|
||
|
|
const numAggregateG1 = 10
|
||
|
|
|
||
|
|
func TestGetPublicKeyG2(t *testing.T) {
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
actual := marshalStruct(pk, t)
|
||
|
|
expected := []byte{
|
||
|
|
175,
|
||
|
|
76,
|
||
|
|
33,
|
||
|
|
103,
|
||
|
|
184,
|
||
|
|
172,
|
||
|
|
12,
|
||
|
|
111,
|
||
|
|
24,
|
||
|
|
87,
|
||
|
|
84,
|
||
|
|
61,
|
||
|
|
243,
|
||
|
|
82,
|
||
|
|
99,
|
||
|
|
76,
|
||
|
|
131,
|
||
|
|
95,
|
||
|
|
171,
|
||
|
|
237,
|
||
|
|
145,
|
||
|
|
143,
|
||
|
|
7,
|
||
|
|
93,
|
||
|
|
205,
|
||
|
|
148,
|
||
|
|
104,
|
||
|
|
29,
|
||
|
|
153,
|
||
|
|
103,
|
||
|
|
187,
|
||
|
|
206,
|
||
|
|
112,
|
||
|
|
223,
|
||
|
|
252,
|
||
|
|
198,
|
||
|
|
102,
|
||
|
|
41,
|
||
|
|
38,
|
||
|
|
244,
|
||
|
|
228,
|
||
|
|
223,
|
||
|
|
102,
|
||
|
|
16,
|
||
|
|
216,
|
||
|
|
152,
|
||
|
|
231,
|
||
|
|
250,
|
||
|
|
7,
|
||
|
|
111,
|
||
|
|
90,
|
||
|
|
98,
|
||
|
|
194,
|
||
|
|
244,
|
||
|
|
101,
|
||
|
|
251,
|
||
|
|
69,
|
||
|
|
130,
|
||
|
|
11,
|
||
|
|
209,
|
||
|
|
41,
|
||
|
|
210,
|
||
|
|
133,
|
||
|
|
105,
|
||
|
|
217,
|
||
|
|
179,
|
||
|
|
190,
|
||
|
|
1,
|
||
|
|
6,
|
||
|
|
155,
|
||
|
|
135,
|
||
|
|
2,
|
||
|
|
168,
|
||
|
|
249,
|
||
|
|
253,
|
||
|
|
41,
|
||
|
|
59,
|
||
|
|
87,
|
||
|
|
8,
|
||
|
|
49,
|
||
|
|
231,
|
||
|
|
198,
|
||
|
|
142,
|
||
|
|
30,
|
||
|
|
186,
|
||
|
|
44,
|
||
|
|
175,
|
||
|
|
17,
|
||
|
|
198,
|
||
|
|
63,
|
||
|
|
210,
|
||
|
|
176,
|
||
|
|
237,
|
||
|
|
171,
|
||
|
|
11,
|
||
|
|
127,
|
||
|
|
}
|
||
|
|
if !bytes.Equal(actual, expected) {
|
||
|
|
t.Errorf("Expected GetPublicKeyVt to pass but failed.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func testSignG1(message []byte, t *testing.T) {
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
sig := genSignatureVt(sk, message, t)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
|
||
|
|
if res, _ := bls.Verify(pk, message, sig); !res {
|
||
|
|
t.Errorf("createSignatureVt failed when it should've passed.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignG1EmptyNilMessage(t *testing.T) {
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
sig, _ := bls.Sign(sk, nil)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
|
||
|
|
if res, _ := bls.Verify(pk, nil, sig); res {
|
||
|
|
t.Errorf("createSignature succeeded when it should've failed")
|
||
|
|
}
|
||
|
|
|
||
|
|
message := []byte{}
|
||
|
|
sig = genSignatureVt(sk, message, t)
|
||
|
|
|
||
|
|
if res, err := bls.Verify(pk, message, sig); !res {
|
||
|
|
t.Errorf("create and verify failed on empty message: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignG1OneByteMessage(t *testing.T) {
|
||
|
|
message := []byte{1}
|
||
|
|
testSignG1(message, t)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignG1LargeMessage(t *testing.T) {
|
||
|
|
message := make([]byte, 1048576)
|
||
|
|
testSignG1(message, t)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignG1RandomMessage(t *testing.T) {
|
||
|
|
message := make([]byte, 65537)
|
||
|
|
readRand(message, t)
|
||
|
|
testSignG1(message, t)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignG1BadMessage(t *testing.T) {
|
||
|
|
message := make([]byte, 1024)
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
sig := genSignatureVt(sk, message, t)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
message = []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
|
||
|
|
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
|
||
|
|
if res, _ := bls.Verify(pk, message, sig); res {
|
||
|
|
t.Errorf("Expected signature to not verify")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBadConversionsG1(t *testing.T) {
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
message := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
|
||
|
|
sig := genSignatureVt(sk, message, t)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
|
||
|
|
if res, _ := bls.Verify(pk, message, sig); !res {
|
||
|
|
t.Errorf("Signature should be valid")
|
||
|
|
}
|
||
|
|
if res, _ := sig.verify(pk, message, blsSignaturePopVtDst); !res {
|
||
|
|
t.Errorf("Signature should be valid")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert public key to signature in G2
|
||
|
|
sig2 := new(Signature)
|
||
|
|
err := sig2.UnmarshalBinary(marshalStruct(pk, t))
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Should be able to convert to signature in G2")
|
||
|
|
}
|
||
|
|
pk2 := new(PublicKey)
|
||
|
|
err = pk2.UnmarshalBinary(marshalStruct(sig, t))
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Should be able to convert to public key in G1")
|
||
|
|
}
|
||
|
|
|
||
|
|
res, _ := pk2.verifySignature(message, sig2, blsSignaturePopVtDst)
|
||
|
|
if res {
|
||
|
|
t.Errorf("The signature shouldn't verify")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregatePublicKeysG2(t *testing.T) {
|
||
|
|
pks := []*PublicKeyVt{}
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
for i := 0; i < 20; i++ {
|
||
|
|
readRand(ikm, t)
|
||
|
|
sk := genRandSecretKey(ikm, t)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
pks = append(pks, pk)
|
||
|
|
}
|
||
|
|
apk1, err := aggregatePublicKeysVt(pks...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
rng := rand.New(rand.NewSource(1234567890))
|
||
|
|
rng.Shuffle(len(pks), func(i, j int) { pks[i], pks[j] = pks[j], pks[i] })
|
||
|
|
apk2, err := aggregatePublicKeysVt(pks...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
if !bytes.Equal(marshalStruct(apk1, t), marshalStruct(apk2, t)) {
|
||
|
|
t.Errorf("Aggregated public keys should be equal")
|
||
|
|
}
|
||
|
|
rand.Shuffle(len(pks), func(i, j int) { pks[i], pks[j] = pks[j], pks[i] })
|
||
|
|
apk1, err = aggregatePublicKeysVt(pks...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
if !bytes.Equal(marshalStruct(apk1, t), marshalStruct(apk2, t)) {
|
||
|
|
t.Errorf("Aggregated public keys should be equal")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregateSignaturesG1(t *testing.T) {
|
||
|
|
sigs := []*SignatureVt{}
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
for i := 0; i < 20; i++ {
|
||
|
|
readRand(ikm, t)
|
||
|
|
sk := genRandSecretKey(ikm, t)
|
||
|
|
sig := genSignatureVt(sk, ikm, t)
|
||
|
|
sigs = append(sigs, sig)
|
||
|
|
}
|
||
|
|
asig1, err := aggregateSignaturesVt(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
rng2 := rand.New(rand.NewSource(1234567890))
|
||
|
|
rng2.Shuffle(len(sigs), func(i, j int) { sigs[i], sigs[j] = sigs[j], sigs[i] })
|
||
|
|
asig2, err := aggregateSignaturesVt(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
if !bytes.Equal(marshalStruct(asig1, t), marshalStruct(asig2, t)) {
|
||
|
|
t.Errorf("Aggregated signatures should be equal")
|
||
|
|
}
|
||
|
|
rand.Shuffle(len(sigs), func(i, j int) { sigs[i], sigs[j] = sigs[j], sigs[i] })
|
||
|
|
asig1, err = aggregateSignaturesVt(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
if !bytes.Equal(marshalStruct(asig1, t), marshalStruct(asig2, t)) {
|
||
|
|
t.Errorf("Aggregated signatures should be equal")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func initAggregatedTestValuesG1(messages [][]byte, t *testing.T) ([]*PublicKeyVt, []*SignatureVt) {
|
||
|
|
pks := []*PublicKeyVt{}
|
||
|
|
sigs := []*SignatureVt{}
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
for i := 0; i < numAggregateG1; i++ {
|
||
|
|
readRand(ikm, t)
|
||
|
|
sk := genRandSecretKey(ikm, t)
|
||
|
|
sig := genSignatureVt(sk, messages[i%len(messages)], t)
|
||
|
|
sigs = append(sigs, sig)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
pks = append(pks, pk)
|
||
|
|
}
|
||
|
|
return pks, sigs
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregatedFunctionalityG1(t *testing.T) {
|
||
|
|
message := make([]byte, 20)
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
messages[0] = message
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
asig, err := bls.AggregateSignatures(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
apk, err := bls.AggregatePublicKeys(pks...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
if res, _ := bls.VerifyMultiSignature(apk, message, asig); !res {
|
||
|
|
t.Errorf("Should verify aggregated signatures with same message")
|
||
|
|
}
|
||
|
|
if res, _ := asig.verify(apk, message, blsSignaturePopVtDst); !res {
|
||
|
|
t.Errorf("MultiSignature.verify failed.")
|
||
|
|
}
|
||
|
|
if res, _ := apk.verify(message, asig, blsSignaturePopVtDst); !res {
|
||
|
|
t.Errorf("MultiPublicKey.verify failed.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBadAggregatedFunctionalityG1(t *testing.T) {
|
||
|
|
message := make([]byte, 20)
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
messages[0] = message
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
|
||
|
|
apk, err := bls.AggregatePublicKeys(pks[2:]...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
asig, err := bls.AggregateSignatures(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if res, _ := bls.VerifyMultiSignature(apk, message, asig); res {
|
||
|
|
t.Errorf(
|
||
|
|
"Should not verify aggregated signatures with same message when some public keys are missing",
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
apk, err = bls.AggregatePublicKeys(pks...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
asig, err = bls.AggregateSignatures(sigs[2:]...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
if res, _ := bls.VerifyMultiSignature(apk, message, asig); res {
|
||
|
|
t.Errorf(
|
||
|
|
"Should not verify aggregated signatures with same message when some signatures are missing",
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
asig, err = bls.AggregateSignatures(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
badmsg := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}
|
||
|
|
if res, _ := bls.VerifyMultiSignature(apk, badmsg, asig); res {
|
||
|
|
t.Errorf("Should not verify aggregated signature with bad message")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregateVerifyG1Pass(t *testing.T) {
|
||
|
|
messages := make([][]byte, numAggregateG1)
|
||
|
|
for i := 0; i < numAggregateG1; i++ {
|
||
|
|
message := make([]byte, 20)
|
||
|
|
readRand(message, t)
|
||
|
|
messages[i] = message
|
||
|
|
}
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
if res, _ := bls.AggregateVerify(pks, messages, sigs); !res {
|
||
|
|
t.Errorf("Expected aggregateVerify to pass but failed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregateVerifyG1MsgSigCntMismatch(t *testing.T) {
|
||
|
|
messages := make([][]byte, 8)
|
||
|
|
for i := 0; i < 8; i++ {
|
||
|
|
message := make([]byte, 20)
|
||
|
|
readRand(message, t)
|
||
|
|
messages[i] = message
|
||
|
|
}
|
||
|
|
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
if res, _ := bls.AggregateVerify(pks, messages, sigs); res {
|
||
|
|
t.Errorf("Expected AggregateVerifyG1 to fail with duplicate message but passed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregateVerifyG1FailDupMsg(t *testing.T) {
|
||
|
|
messages := make([][]byte, 10)
|
||
|
|
for i := 0; i < 9; i++ {
|
||
|
|
message := make([]byte, 20)
|
||
|
|
readRand(message, t)
|
||
|
|
messages[i] = message
|
||
|
|
}
|
||
|
|
// Duplicate message
|
||
|
|
messages[9] = messages[0]
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
if res, _ := bls.AggregateVerify(pks, messages, sigs); res {
|
||
|
|
t.Errorf("Expected aggregateVerify to fail with duplicate message but passed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregateVerifyG1FailIncorrectMsg(t *testing.T) {
|
||
|
|
messages := make([][]byte, 10)
|
||
|
|
for i := 0; i < 9; i++ {
|
||
|
|
message := make([]byte, 20)
|
||
|
|
readRand(message, t)
|
||
|
|
messages[i] = message
|
||
|
|
}
|
||
|
|
// Duplicate message
|
||
|
|
messages[9] = messages[0]
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
if res, _ := bls.AggregateVerify(pks[2:], messages[2:], sigs); res {
|
||
|
|
t.Errorf("Expected aggregateVerify to fail with duplicate message but passed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestAggregateVerifyG1OneMsg(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
messages[0] = make([]byte, 20)
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
sig := genSignatureVt(sk, messages[0], t)
|
||
|
|
pk := genPublicKeyVt(sk, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
// Should be the same as verifySignatureVt
|
||
|
|
if res, _ := bls.AggregateVerify([]*PublicKeyVt{pk}, messages, []*SignatureVt{sig}); !res {
|
||
|
|
t.Errorf("Expected AggregateVerifyG1OneMsg to pass but failed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestVerifyG1Mutability(t *testing.T) {
|
||
|
|
// verify should not change any inputs
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
ikm_copy := make([]byte, 32)
|
||
|
|
readRand(ikm, t)
|
||
|
|
copy(ikm_copy, ikm)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
pk, sk, err := bls.KeygenWithSeed(ikm)
|
||
|
|
|
||
|
|
if !bytes.Equal(ikm, ikm_copy) {
|
||
|
|
t.Errorf("SigPopVt.KeygenWithSeed modifies ikm")
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Expected KeygenWithSeed to succeed but failed.")
|
||
|
|
}
|
||
|
|
sig, err := bls.Sign(sk, ikm)
|
||
|
|
if !bytes.Equal(ikm, ikm_copy) {
|
||
|
|
t.Errorf("SigPopVt.Sign modifies message")
|
||
|
|
}
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("SigPopVt.KeygenWithSeed to succeed but failed.")
|
||
|
|
}
|
||
|
|
sigCopy := marshalStruct(sig, t)
|
||
|
|
if res, _ := bls.Verify(pk, ikm, sig); !res {
|
||
|
|
t.Errorf("Expected verify to succeed but failed.")
|
||
|
|
}
|
||
|
|
if !bytes.Equal(ikm, ikm_copy) {
|
||
|
|
t.Errorf("SigPopVt.verify modifies message")
|
||
|
|
}
|
||
|
|
if !bytes.Equal(sigCopy, marshalStruct(sig, t)) {
|
||
|
|
t.Errorf("SigPopVt.verify modifies signature")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPublicKeyG2FromBadBytes(t *testing.T) {
|
||
|
|
pk := make([]byte, 32)
|
||
|
|
err := new(PublicKeyVt).UnmarshalBinary(pk)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected PublicKeyG2FromBytes to fail but passed")
|
||
|
|
}
|
||
|
|
// All zeros
|
||
|
|
pk = make([]byte, PublicKeyVtSize)
|
||
|
|
// See https://github.com/zcash/librustzcash/blob/master/pairing/src/bls12_381/README.md#serialization
|
||
|
|
// 1 << 7 == compressed
|
||
|
|
// 1 << 6 == infinity or zero
|
||
|
|
pk[0] = 0xc0
|
||
|
|
err = new(PublicKeyVt).UnmarshalBinary(pk)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected PublicKeyG2FromBytes to fail but passed")
|
||
|
|
}
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
pk1, err := sk.GetPublicKeyVt()
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Expected GetPublicKeyVt to pass but failed.")
|
||
|
|
}
|
||
|
|
out := marshalStruct(pk1, t)
|
||
|
|
out[3] += 1
|
||
|
|
err = new(PublicKeyVt).UnmarshalBinary(pk)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected PublicKeyG2FromBytes to fail but passed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSignatureG1FromBadBytes(t *testing.T) {
|
||
|
|
sig := make([]byte, 32)
|
||
|
|
err := new(SignatureVt).UnmarshalBinary(sig)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected SignatureG1FromBytes to fail but passed")
|
||
|
|
}
|
||
|
|
// All zeros
|
||
|
|
sig = make([]byte, SignatureVtSize)
|
||
|
|
// See https://github.com/zcash/librustzcash/blob/master/pairing/src/bls12_381/README.md#serialization
|
||
|
|
// 1 << 7 == compressed
|
||
|
|
// 1 << 6 == infinity or zero
|
||
|
|
sig[0] = 0xc0
|
||
|
|
err = new(SignatureVt).UnmarshalBinary(sig)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected SignatureG1FromBytes to fail but passed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBadSecretKeyG1(t *testing.T) {
|
||
|
|
sk := &SecretKey{value: bls12381.Bls12381FqNew()}
|
||
|
|
pk, err := sk.GetPublicKeyVt()
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected GetPublicKeyVt to fail with 0 byte secret key but passed: %v", pk)
|
||
|
|
}
|
||
|
|
_ = sk.UnmarshalBinary(sk.value.Params.BiModulus.Bytes())
|
||
|
|
pk, err = sk.GetPublicKeyVt()
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected GetPublicKeyVt to fail with secret key with Q but passed: %v", pk)
|
||
|
|
}
|
||
|
|
|
||
|
|
err = sk.UnmarshalBinary([]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected SecretKeyFromBytes to fail with not enough bytes but passed: %v", pk)
|
||
|
|
}
|
||
|
|
|
||
|
|
err = sk.UnmarshalBinary(make([]byte, 32))
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected SecretKeyFromBytes to fail but passed: %v", pk)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestProofOfPossessionG1Works(t *testing.T) {
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
readRand(ikm, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
pk, sk, err := bls.KeygenWithSeed(ikm)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Key gen failed but should've succeeded")
|
||
|
|
}
|
||
|
|
pop, err := bls.PopProve(sk)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("PopProve failed but should've succeeded")
|
||
|
|
}
|
||
|
|
if res, _ := bls.PopVerify(pk, pop); !res {
|
||
|
|
t.Errorf("PopVerify failed but should've succeeded")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestProofOfPossessionG1FromBadKey(t *testing.T) {
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
value := new(big.Int)
|
||
|
|
value.SetBytes(ikm)
|
||
|
|
sk := SecretKey{value: bls12381.Bls12381FqNew().SetBigInt(value)}
|
||
|
|
_, err := sk.createProofOfPossessionVt(blsSignaturePopVtDst)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("createProofOfPossessionVt should've failed but succeeded.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestProofOfPossessionG1BytesWorks(t *testing.T) {
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
pop, err := sk.createProofOfPossessionVt(blsSignaturePopVtDst)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("CreateProofOfPossesionG1 failed but shouldn've succeeded.")
|
||
|
|
}
|
||
|
|
out := marshalStruct(pop, t)
|
||
|
|
if len(out) != ProofOfPossessionVtSize {
|
||
|
|
t.Errorf(
|
||
|
|
"ProofOfPossessionBytes incorrect size: expected %v, got %v",
|
||
|
|
ProofOfPossessionVtSize,
|
||
|
|
len(out),
|
||
|
|
)
|
||
|
|
}
|
||
|
|
pop2 := new(ProofOfPossessionVt)
|
||
|
|
err = pop2.UnmarshalBinary(out)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("ProofOfPossessionVt.UnmarshalBinary failed: %v", err)
|
||
|
|
}
|
||
|
|
out2 := marshalStruct(pop2, t)
|
||
|
|
if !bytes.Equal(out, out2) {
|
||
|
|
t.Errorf("ProofOfPossessionVt.UnmarshalBinary failed, not equal when deserialized")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestProofOfPossessionG1BadBytes(t *testing.T) {
|
||
|
|
zeros := make([]byte, ProofOfPossessionVtSize)
|
||
|
|
temp := new(ProofOfPossessionVt)
|
||
|
|
err := temp.UnmarshalBinary(zeros)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("ProofOfPossessionVt.UnmarshalBinary shouldn've failed but succeeded.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestProofOfPossessionG1Fails(t *testing.T) {
|
||
|
|
sk := genSecretKey(t)
|
||
|
|
pop, err := sk.createProofOfPossessionVt(blsSignaturePopVtDst)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Expected createProofOfPossessionVt to succeed but failed.")
|
||
|
|
}
|
||
|
|
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
readRand(ikm, t)
|
||
|
|
sk = genRandSecretKey(ikm, t)
|
||
|
|
bad, err := sk.GetPublicKeyVt()
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Expected PublicKeyG2FromBytes to succeed but failed: %v", err)
|
||
|
|
}
|
||
|
|
if res, _ := pop.verify(bad, blsSignaturePopVtDst); res {
|
||
|
|
t.Errorf("Expected ProofOfPossession verify to fail but succeeded.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMultiSigG1Bytes(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
message := make([]byte, 20)
|
||
|
|
messages[0] = message
|
||
|
|
_, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
msig, err := bls.AggregateSignatures(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
msigBytes := marshalStruct(msig, t)
|
||
|
|
if len(msigBytes) != SignatureVtSize {
|
||
|
|
t.Errorf(
|
||
|
|
"Invalid multi-sig length. Expected %d bytes, found %d",
|
||
|
|
SignatureVtSize,
|
||
|
|
len(msigBytes),
|
||
|
|
)
|
||
|
|
}
|
||
|
|
msig2 := new(MultiSignatureVt)
|
||
|
|
err = msig2.UnmarshalBinary(msigBytes)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("MultiSignatureG1FromBytes failed with %v", err)
|
||
|
|
}
|
||
|
|
msigBytes2 := marshalStruct(msig2, t)
|
||
|
|
|
||
|
|
if !bytes.Equal(msigBytes, msigBytes2) {
|
||
|
|
t.Errorf("Bytes methods not equal.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMultiSigG1BadBytes(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
message := make([]byte, 20)
|
||
|
|
messages[0] = message
|
||
|
|
_, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
msig, err := bls.AggregateSignatures(sigs...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
msigBytes := marshalStruct(msig, t)
|
||
|
|
if len(msigBytes) != SignatureVtSize {
|
||
|
|
t.Errorf(
|
||
|
|
"Invalid multi-sig length. Expected %d bytes, found %d",
|
||
|
|
SignatureSize,
|
||
|
|
len(msigBytes),
|
||
|
|
)
|
||
|
|
}
|
||
|
|
msigBytes[0] = 0
|
||
|
|
temp := new(MultiSignatureVt)
|
||
|
|
err = temp.UnmarshalBinary(msigBytes)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("MultiSignatureG1FromBytes should've failed but succeeded")
|
||
|
|
}
|
||
|
|
msigBytes = make([]byte, SignatureVtSize)
|
||
|
|
err = temp.UnmarshalBinary(msigBytes)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("MultiSignatureG1FromBytes should've failed but succeeded")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMultiPubkeyG2Bytes(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
message := make([]byte, 20)
|
||
|
|
messages[0] = message
|
||
|
|
pks, _ := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
apk, err := bls.AggregatePublicKeys(pks...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
apkBytes := marshalStruct(apk, t)
|
||
|
|
if len(apkBytes) != PublicKeyVtSize {
|
||
|
|
t.Errorf("MultiPublicKeyVt has an incorrect size")
|
||
|
|
}
|
||
|
|
apk2 := new(MultiPublicKeyVt)
|
||
|
|
err = apk2.UnmarshalBinary(apkBytes)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("MultiPublicKeyVt.UnmarshalBinary failed with %v", err)
|
||
|
|
}
|
||
|
|
apk2Bytes := marshalStruct(apk2, t)
|
||
|
|
if !bytes.Equal(apkBytes, apk2Bytes) {
|
||
|
|
t.Errorf("Bytes methods not equal.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMultiPubkeyG2BadBytes(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
message := make([]byte, 20)
|
||
|
|
messages[0] = message
|
||
|
|
pks, _ := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
apk, err := bls.AggregatePublicKeys(pks...)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("%v", err)
|
||
|
|
}
|
||
|
|
apkBytes := marshalStruct(apk, t)
|
||
|
|
if len(apkBytes) != PublicKeyVtSize {
|
||
|
|
t.Errorf("MultiPublicKeyVt has an incorrect size")
|
||
|
|
}
|
||
|
|
apkBytes[0] = 0
|
||
|
|
temp := new(MultiPublicKeyVt)
|
||
|
|
err = temp.UnmarshalBinary(apkBytes)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("MultiPublicKeyVt.UnmarshalBinary should've failed but succeeded")
|
||
|
|
}
|
||
|
|
apkBytes = make([]byte, PublicKeyVtSize)
|
||
|
|
err = temp.UnmarshalBinary(apkBytes)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("MultiPublicKeyVt.UnmarshalBinary should've failed but succeeded")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestFastAggregateVerifyConstituentG1Works(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
message := make([]byte, 1)
|
||
|
|
messages[0] = message
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
|
||
|
|
if res, _ := bls.FastAggregateVerifyConstituent(pks, message, sigs); !res {
|
||
|
|
t.Errorf("FastAggregateVerify failed.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestFastAggregateVerifyG1Works(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
message := make([]byte, 1)
|
||
|
|
messages[0] = message
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
asig, _ := aggregateSignaturesVt(sigs...)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
|
||
|
|
if res, _ := bls.FastAggregateVerify(pks, message, asig); !res {
|
||
|
|
t.Errorf("FastAggregateVerify failed.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestFastAggregateVerifyG1Fails(t *testing.T) {
|
||
|
|
messages := make([][]byte, 1)
|
||
|
|
message := make([]byte, 1)
|
||
|
|
messages[0] = message
|
||
|
|
pks, sigs := initAggregatedTestValuesG1(messages, t)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
message[0] = 1
|
||
|
|
if res, _ := bls.FastAggregateVerifyConstituent(pks, message, sigs); res {
|
||
|
|
t.Errorf("FastAggregateVerify verified when it should've failed.")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestCustomPopDstG1Works(t *testing.T) {
|
||
|
|
bls, _ := NewSigPopVtWithDst("BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_TEST",
|
||
|
|
"BLS_POP_BLS12381G1_XMD:SHA-256_SSWU_RO_POP_TEST")
|
||
|
|
msg := make([]byte, 20)
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
pk, sk, err := bls.KeygenWithSeed(ikm)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Couldn't create custom dst keys: %v", err)
|
||
|
|
}
|
||
|
|
sig, err := bls.Sign(sk, msg)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Couldn't sign with custom dst: %v", err)
|
||
|
|
}
|
||
|
|
if res, _ := bls.Verify(pk, msg, sig); !res {
|
||
|
|
t.Errorf("verify fails with custom dst")
|
||
|
|
}
|
||
|
|
|
||
|
|
pks := make([]*PublicKeyVt, 10)
|
||
|
|
sigs := make([]*SignatureVt, 10)
|
||
|
|
pks[0] = pk
|
||
|
|
sigs[0] = sig
|
||
|
|
for i := 1; i < 10; i++ {
|
||
|
|
readRand(ikm, t)
|
||
|
|
pkt, skt, err := bls.KeygenWithSeed(ikm)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Couldn't create custom dst keys: %v", err)
|
||
|
|
}
|
||
|
|
sigt, err := bls.Sign(skt, msg)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Couldn't sign with custom dst: %v", err)
|
||
|
|
}
|
||
|
|
pks[i] = pkt
|
||
|
|
sigs[i] = sigt
|
||
|
|
}
|
||
|
|
|
||
|
|
if res, _ := bls.FastAggregateVerifyConstituent(pks, msg, sigs); !res {
|
||
|
|
t.Errorf("FastAggregateVerify failed with custom dst")
|
||
|
|
}
|
||
|
|
|
||
|
|
pop, err := bls.PopProve(sk)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("PopProve failed with custom dst")
|
||
|
|
}
|
||
|
|
|
||
|
|
if res, _ := bls.PopVerify(pk, pop); !res {
|
||
|
|
t.Errorf("PopVerify failed with custom dst")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBlsPopG1KeyGenWithSeed(t *testing.T) {
|
||
|
|
ikm := []byte("Not enough bytes")
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
_, _, err := bls.KeygenWithSeed(ikm)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("Expected KeygenWithSeed to fail but succeeded")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestBlsPopG1KeyGen(t *testing.T) {
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
_, _, err := bls.Keygen()
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("Keygen failed: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPopVtThresholdKeygenBadInputs(t *testing.T) {
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
_, _, err := bls.ThresholdKeygen(0, 0)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("ThresholdKeygen should've failed but succeeded")
|
||
|
|
}
|
||
|
|
_, _, err = bls.ThresholdKeygen(1, 0)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("ThresholdKeygen should've failed but succeeded")
|
||
|
|
}
|
||
|
|
_, _, err = bls.ThresholdKeygen(3, 2)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("ThresholdKeygen should've failed but succeeded")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPopVtThresholdKeygen(t *testing.T) {
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
_, sks, err := bls.ThresholdKeygen(3, 5)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("ThresholdKeygen failed")
|
||
|
|
}
|
||
|
|
if len(sks) != 5 {
|
||
|
|
t.Errorf("ThresholdKeygen did not produce enough shares")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestPopPartialSignVt(t *testing.T) {
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
pk, sks, err := bls.ThresholdKeygenWithSeed(ikm, 2, 4)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("ThresholdKeygen failed")
|
||
|
|
}
|
||
|
|
msg := make([]byte, 10)
|
||
|
|
sig1, err := bls.PartialSign(sks[0], msg)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("partialSign failed: %v", err)
|
||
|
|
}
|
||
|
|
sig2, err := bls.PartialSign(sks[1], msg)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("partialSign failed: %v", err)
|
||
|
|
}
|
||
|
|
sig, err := bls.CombineSignatures(sig1, sig2)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("CombineSignatures failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if res, _ := bls.Verify(pk, msg, sig); !res {
|
||
|
|
t.Errorf("Combined signature does not verify")
|
||
|
|
}
|
||
|
|
|
||
|
|
sig, err = bls.CombineSignatures(sig1)
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("CombineSignatures succeeded when it should've failed")
|
||
|
|
}
|
||
|
|
if res, _ := bls.Verify(pk, msg, sig); res {
|
||
|
|
t.Errorf("Combined signature verify succeeded when it should've failed")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Ensure that mixed partial signatures from distinct origins create invalid composite signatures
|
||
|
|
func TestPopVtPartialMixupShares(t *testing.T) {
|
||
|
|
total := uint(5)
|
||
|
|
ikm := make([]byte, 32)
|
||
|
|
bls := NewSigPopVt()
|
||
|
|
pk1, sks1, err := bls.ThresholdKeygenWithSeed(ikm, 3, total)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("ThresholdKeygen failed: %v", err)
|
||
|
|
}
|
||
|
|
for i := range ikm {
|
||
|
|
ikm[i] = 1
|
||
|
|
}
|
||
|
|
pk2, sks2, err := bls.ThresholdKeygenWithSeed(ikm, 3, total)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("ThresholdKeygen failed: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Generate partial signatures for both sets of keys
|
||
|
|
msg := make([]byte, 10)
|
||
|
|
sigs1 := make([]*PartialSignatureVt, total)
|
||
|
|
sigs2 := make([]*PartialSignatureVt, total)
|
||
|
|
for i := range sks1 {
|
||
|
|
sigs1[i], err = bls.PartialSign(sks1[i], msg)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("PartialSign failed: %v", err)
|
||
|
|
}
|
||
|
|
sigs2[i], err = bls.PartialSign(sks2[i], msg)
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("PartialSign failed: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try combining 2 from group 1 and 2 from group 2
|
||
|
|
sig, err := bls.CombineSignatures(sigs1[0], sigs1[1], sigs2[2], sigs2[3])
|
||
|
|
if err != nil {
|
||
|
|
t.Errorf("CombineSignatures failed: %v", err)
|
||
|
|
}
|
||
|
|
// Signature shouldn't validate
|
||
|
|
if res, _ := bls.Verify(pk1, msg, sig); res {
|
||
|
|
t.Errorf(
|
||
|
|
"CombineSignatures worked with different shares of two secret keys for the same message",
|
||
|
|
)
|
||
|
|
}
|
||
|
|
if res, _ := bls.Verify(pk2, msg, sig); res {
|
||
|
|
t.Errorf(
|
||
|
|
"CombineSignatures worked with different shares of two secret keys for the same message",
|
||
|
|
)
|
||
|
|
}
|
||
|
|
// Should error out due to duplicate identifiers
|
||
|
|
_, err = bls.CombineSignatures(sigs1[0], sigs1[1], sigs2[0], sigs2[1])
|
||
|
|
if err == nil {
|
||
|
|
t.Errorf("CombineSignatures expected to fail but succeeded.")
|
||
|
|
}
|
||
|
|
}
|