From 0b74d5b609bf319a81e019a93d50a8cc8d87ca6e Mon Sep 17 00:00:00 2001 From: Andy Polyakov Date: Fri, 20 Nov 2020 17:46:21 +0100 Subject: [PATCH] bindings/go: add groupcheck flags, interface-breaking change. --- bindings/go/blst.go | 296 +++++++++++++++++++------------- bindings/go/blst.tgo | 52 +++--- bindings/go/blst_minpk.tgo | 120 ++++++++----- bindings/go/blst_minpk_test.go | 119 +++++++------ bindings/go/blst_minsig_test.go | 119 +++++++------ bindings/go/blst_px.tgo | 14 +- 6 files changed, 418 insertions(+), 302 deletions(-) diff --git a/bindings/go/blst.go b/bindings/go/blst.go index cfd3c4a3..d35606ff 100644 --- a/bindings/go/blst.go +++ b/bindings/go/blst.go @@ -103,8 +103,8 @@ func PairingCtx(hash_or_encode bool, DST []byte) Pairing { return ctx } -func PairingAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, - msg []byte, +func PairingAggregatePkInG1(ctx Pairing, PK *P1Affine, pkValidate bool, + sig *P2Affine, sigGroupcheck bool, msg []byte, optional ...[]byte) int { // aug var aug []byte var uaug *C.byte @@ -119,15 +119,17 @@ func PairingAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_aggregate_pk_in_g1((*C.blst_pairing)(&ctx[0]), PK, sig, + r := C.blst_pairing_chk_n_aggr_pk_in_g1((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), umsg, C.size_t(len(msg)), uaug, C.size_t(len(aug))) return int(r) } -func PairingAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, - msg []byte, +func PairingAggregatePkInG2(ctx Pairing, PK *P2Affine, pkValidate bool, + sig *P1Affine, sigGroupcheck bool, msg []byte, optional ...[]byte) int { // aug var aug []byte var uaug *C.byte @@ -142,14 +144,17 @@ func PairingAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_aggregate_pk_in_g2((*C.blst_pairing)(&ctx[0]), PK, sig, + r := C.blst_pairing_chk_n_aggr_pk_in_g2((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), umsg, C.size_t(len(msg)), uaug, C.size_t(len(aug))) return int(r) } -func PairingMulNAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, +func PairingMulNAggregatePkInG1(ctx Pairing, PK *P1Affine, pkValidate bool, + sig *P2Affine, sigGroupcheck bool, rand *Scalar, randBits int, msg []byte, optional ...[]byte) int { // aug var aug []byte @@ -165,8 +170,9 @@ func PairingMulNAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_mul_n_aggregate_pk_in_g1((*C.blst_pairing)(&ctx[0]), - PK, sig, + r := C.blst_pairing_chk_n_mul_n_aggr_pk_in_g1((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), &rand.b[0], C.size_t(randBits), umsg, C.size_t(len(msg)), uaug, C.size_t(len(aug))) @@ -174,7 +180,8 @@ func PairingMulNAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, return int(r) } -func PairingMulNAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, +func PairingMulNAggregatePkInG2(ctx Pairing, PK *P2Affine, pkValidate bool, + sig *P1Affine, sigGroupcheck bool, rand *Scalar, randBits int, msg []byte, optional ...[]byte) int { // aug var aug []byte @@ -190,8 +197,9 @@ func PairingMulNAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_mul_n_aggregate_pk_in_g2((*C.blst_pairing)(&ctx[0]), - PK, sig, + r := C.blst_pairing_chk_n_mul_n_aggr_pk_in_g2((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), &rand.b[0], C.size_t(randBits), umsg, C.size_t(len(msg)), uaug, C.size_t(len(aug))) @@ -239,6 +247,15 @@ func (pk *P1Affine) KeyValidate() bool { bool(C.blst_p1_affine_in_g1(pk)) } +// sigInfcheck, check for infinity, is a way to avoid going +// into resource-consuming verification. Passing 'false' is +// always cryptographically safe, but application might want +// to guard against obviously bogus individual[!] signatures. +func (sig *P2Affine) SigValidate(sigInfcheck bool) bool { + return (sigInfcheck && !bool(C.blst_p2_affine_is_inf(sig))) || + bool(C.blst_p2_affine_in_g2(sig)) +} + // // Sign // @@ -270,30 +287,32 @@ type sigGetterP2 func() *P2Affine type pkGetterP1 func(i uint32, temp *P1Affine) (*P1Affine, []byte) // Single verify with decompressed pk -func (sig *P2Affine) Verify(pk *P1Affine, msg Message, dst []byte, +func (sig *P2Affine) Verify(sigGroupcheck bool, pk *P1Affine, pkValidate bool, + msg Message, dst []byte, optional ...interface{}) bool { // useHash bool, aug []byte aug, _, useHash, ok := parseOpts(optional...) if !ok { return false } - return sig.AggregateVerify([]*P1Affine{pk}, []Message{msg}, dst, - useHash, [][]byte{aug}) + return sig.AggregateVerify(sigGroupcheck, []*P1Affine{pk}, pkValidate, + []Message{msg}, dst, useHash, [][]byte{aug}) } // Single verify with compressed pk // Uses a dummy signature to get the correct type -func (dummy *P2Affine) VerifyCompressed(sig []byte, pk []byte, - msg Message, dst []byte, +func (dummy *P2Affine) VerifyCompressed(sig []byte, sigGroupcheck bool, + pk []byte, pkValidate bool, msg Message, dst []byte, optional ...bool) bool { // useHash bool, usePksAsAugs bool - return dummy.AggregateVerifyCompressed(sig, [][]byte{pk}, + return dummy.AggregateVerifyCompressed(sig, sigGroupcheck, + [][]byte{pk}, pkValidate, []Message{msg}, dst, optional...) } // Aggregate verify with uncompressed signature and public keys -func (sig *P2Affine) AggregateVerify(pks []*P1Affine, msgs []Message, - dst []byte, +func (sig *P2Affine) AggregateVerify(sigGroupcheck bool, + pks []*P1Affine, pksVerify bool, msgs []Message, dst []byte, optional ...interface{}) bool { // useHash bool, augs [][]byte // sanity checks and argument parsing @@ -319,13 +338,14 @@ func (sig *P2Affine) AggregateVerify(pks []*P1Affine, msgs []Message, } } - return coreAggregateVerifyPkInG1(sigFn, pkFn, msgs, dst, useHash) + return coreAggregateVerifyPkInG1(sigFn, sigGroupcheck, pkFn, pksVerify, + msgs, dst, useHash) } // Aggregate verify with compressed signature and public keys // Uses a dummy signature to get the correct type -func (dummy *P2Affine) AggregateVerifyCompressed(sig []byte, pks [][]byte, - msgs []Message, dst []byte, +func (dummy *P2Affine) AggregateVerifyCompressed(sig []byte, sigGroupcheck bool, + pks [][]byte, pksVerify bool, msgs []Message, dst []byte, optional ...bool) bool { // useHash bool, usePksAsAugs bool // sanity checks and argument parsing @@ -375,12 +395,13 @@ func (dummy *P2Affine) AggregateVerifyCompressed(sig []byte, pks [][]byte, } return pk, nil } - return coreAggregateVerifyPkInG1(sigFn, pkFn, msgs, dst, useHash) + return coreAggregateVerifyPkInG1(sigFn, sigGroupcheck, pkFn, pksVerify, + msgs, dst, useHash) } // TODO: check message uniqueness -func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, - msgs []Message, dst []byte, +func coreAggregateVerifyPkInG1(sigFn sigGetterP2, sigGroupcheck bool, + pkFn pkGetterP1, pkValidate bool, msgs []Message, dst []byte, optional ...bool) bool { // useHash n := len(msgs) @@ -437,8 +458,8 @@ func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, } // Pairing and accumulate - ret := PairingAggregatePkInG1(pairing, curPk, nil, msgs[work], - aug) + ret := PairingAggregatePkInG1(pairing, curPk, pkValidate, + nil, false, msgs[work], aug) if ret != C.BLST_SUCCESS { atomic.StoreInt32(&valid, 0) break @@ -461,7 +482,12 @@ func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, sig := sigFn() if sig == nil { atomic.StoreInt32(&valid, 0) - } else { + } + if atomic.LoadInt32(&valid) > 0 && sigGroupcheck && + !sig.SigValidate(false) { + atomic.StoreInt32(&valid, 0) + } + if atomic.LoadInt32(&valid) > 0 { C.blst_aggregated_in_g2(>sig, sig) } mutex.Unlock() @@ -488,8 +514,10 @@ func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, return PairingFinalVerify(pairings, >sig) } -func (sig *P2Affine) FastAggregateVerify(pks []*P1Affine, msg Message, - dst []byte, +// pks are assumed to be verified for proof of possession, +// which implies that they are already group-checked +func (sig *P2Affine) FastAggregateVerify(sigGroupcheck bool, + pks []*P1Affine, msg Message, dst []byte, optional ...interface{}) bool { // pass-through to Verify n := len(pks) @@ -498,19 +526,19 @@ func (sig *P2Affine) FastAggregateVerify(pks []*P1Affine, msg Message, return false } - aggregator := new(P1Aggregate).Aggregate(pks) - if aggregator == nil { + aggregator := new(P1Aggregate) + if !aggregator.Aggregate(pks, false) { return false } pkAff := aggregator.ToAffine() // Verify - return sig.Verify(pkAff, msg, dst, optional...) + return sig.Verify(sigGroupcheck, pkAff, false, msg, dst, optional...) } func (dummy *P2Affine) MultipleAggregateVerify(sigs []*P2Affine, - pks []*P1Affine, msgs []Message, dst []byte, randFn func(*Scalar), - randBits int, + sigsGroupcheck bool, pks []*P1Affine, pksVerify bool, + msgs []Message, dst []byte, randFn func(*Scalar), randBits int, optional ...interface{}) bool { // useHash // Sanity checks and argument parsing @@ -535,14 +563,15 @@ func (dummy *P2Affine) MultipleAggregateVerify(sigs []*P2Affine, return sigs[work], pks[work], rand, aug } - return multipleAggregateVerifyPkInG1(paramsFn, msgs, dst, - randBits, useHash) + return multipleAggregateVerifyPkInG1(paramsFn, sigsGroupcheck, pksVerify, + msgs, dst, randBits, useHash) } type mulAggGetterPkInG1 func(work uint32, sig *P2Affine, pk *P1Affine, rand *Scalar) (*P2Affine, *P1Affine, *Scalar, []byte) -func multipleAggregateVerifyPkInG1(paramsFn mulAggGetterPkInG1, msgs []Message, +func multipleAggregateVerifyPkInG1(paramsFn mulAggGetterPkInG1, + sigsGroupcheck bool, pksVerify bool, msgs []Message, dst []byte, randBits int, optional ...bool) bool { // useHash n := len(msgs) @@ -587,7 +616,8 @@ func multipleAggregateVerifyPkInG1(paramsFn mulAggGetterPkInG1, msgs []Message, curSig, curPk, curRand, aug := paramsFn(work, &tempSig, &tempPk, &tempRand) - if PairingMulNAggregatePkInG1(pairing, curPk, curSig, curRand, + if PairingMulNAggregatePkInG1(pairing, curPk, pksVerify, + curSig, sigsGroupcheck, curRand, randBits, msgs[work], aug) != C.BLST_SUCCESS { atomic.StoreInt32(&valid, 0) @@ -638,21 +668,23 @@ type P2Aggregate struct { } // Aggregate uncompressed elements -func (agg *P2Aggregate) Aggregate(elmts []*P2Affine) *P2Aggregate { +func (agg *P2Aggregate) Aggregate(elmts []*P2Affine, + groupcheck bool) bool { if len(elmts) == 0 { - return agg + return true } getter := func(i uint32, _ *P2Affine) *P2Affine { return elmts[i] } - if !agg.aggregate(getter, len(elmts)) { - return nil + if !agg.aggregate(getter, groupcheck, len(elmts)) { + return false } - return agg + return true } // Aggregate compressed elements -func (agg *P2Aggregate) AggregateCompressed(elmts [][]byte) *P2Aggregate { +func (agg *P2Aggregate) AggregateCompressed(elmts [][]byte, + groupcheck bool) bool { if len(elmts) == 0 { - return agg + return true } getter := func(i uint32, p *P2Affine) *P2Affine { bytes := elmts[i] @@ -671,13 +703,13 @@ func (agg *P2Aggregate) AggregateCompressed(elmts [][]byte) *P2Aggregate { } return p } - if !agg.aggregate(getter, len(elmts)) { - return nil + if !agg.aggregate(getter, groupcheck, len(elmts)) { + return false } - return agg + return true } -func (agg *P2Aggregate) AddAggregate(other *P2Aggregate) *P2Aggregate { +func (agg *P2Aggregate) AddAggregate(other *P2Aggregate) { if other.v == nil { // do nothing } else if agg.v == nil { @@ -685,17 +717,19 @@ func (agg *P2Aggregate) AddAggregate(other *P2Aggregate) *P2Aggregate { } else { C.blst_p2_add(agg.v, agg.v, other.v) } - return agg } -func (agg *P2Aggregate) Add(elmt *P2Affine) *P2Aggregate { +func (agg *P2Aggregate) Add(elmt *P2Affine, groupcheck bool) bool { + if groupcheck && !bool(C.blst_p2_affine_in_g2(elmt)) { + return false + } if agg.v == nil { agg.v = new(P2) C.blst_p2_from_affine(agg.v, elmt) } else { C.blst_p2_add_or_double_affine(agg.v, agg.v, elmt) } - return agg + return true } func (agg *P2Aggregate) ToAffine() *P2Affine { @@ -705,7 +739,9 @@ func (agg *P2Aggregate) ToAffine() *P2Affine { return agg.v.ToAffine() } -func (agg *P2Aggregate) aggregate(getter aggGetterP2, n int) bool { +func (agg *P2Aggregate) aggregate(getter aggGetterP2, groupcheck bool, + n int) bool { + if n == 0 { return true } @@ -741,6 +777,10 @@ func (agg *P2Aggregate) aggregate(getter aggGetterP2, n int) bool { atomic.StoreInt32(&valid, 0) break } + if groupcheck && !bool(C.blst_p2_affine_in_g2(curElmt)) { + atomic.StoreInt32(&valid, 0) + break + } if first { C.blst_p2_from_affine(&agg, curElmt) first = false @@ -805,6 +845,15 @@ func (pk *P2Affine) KeyValidate() bool { bool(C.blst_p2_affine_in_g2(pk)) } +// sigInfcheck, check for infinity, is a way to avoid going +// into resource-consuming verification. Passing 'false' is +// always cryptographically safe, but application might want +// to guard against obviously bogus individual[!] signatures. +func (sig *P1Affine) SigValidate(sigInfcheck bool) bool { + return (sigInfcheck && !bool(C.blst_p1_affine_is_inf(sig))) || + bool(C.blst_p1_affine_in_g1(sig)) +} + // // Sign // @@ -836,30 +885,32 @@ type sigGetterP1 func() *P1Affine type pkGetterP2 func(i uint32, temp *P2Affine) (*P2Affine, []byte) // Single verify with decompressed pk -func (sig *P1Affine) Verify(pk *P2Affine, msg Message, dst []byte, +func (sig *P1Affine) Verify(sigGroupcheck bool, pk *P2Affine, pkValidate bool, + msg Message, dst []byte, optional ...interface{}) bool { // useHash bool, aug []byte aug, _, useHash, ok := parseOpts(optional...) if !ok { return false } - return sig.AggregateVerify([]*P2Affine{pk}, []Message{msg}, dst, - useHash, [][]byte{aug}) + return sig.AggregateVerify(sigGroupcheck, []*P2Affine{pk}, pkValidate, + []Message{msg}, dst, useHash, [][]byte{aug}) } // Single verify with compressed pk // Uses a dummy signature to get the correct type -func (dummy *P1Affine) VerifyCompressed(sig []byte, pk []byte, - msg Message, dst []byte, +func (dummy *P1Affine) VerifyCompressed(sig []byte, sigGroupcheck bool, + pk []byte, pkValidate bool, msg Message, dst []byte, optional ...bool) bool { // useHash bool, usePksAsAugs bool - return dummy.AggregateVerifyCompressed(sig, [][]byte{pk}, + return dummy.AggregateVerifyCompressed(sig, sigGroupcheck, + [][]byte{pk}, pkValidate, []Message{msg}, dst, optional...) } // Aggregate verify with uncompressed signature and public keys -func (sig *P1Affine) AggregateVerify(pks []*P2Affine, msgs []Message, - dst []byte, +func (sig *P1Affine) AggregateVerify(sigGroupcheck bool, + pks []*P2Affine, pksVerify bool, msgs []Message, dst []byte, optional ...interface{}) bool { // useHash bool, augs [][]byte // sanity checks and argument parsing @@ -885,13 +936,14 @@ func (sig *P1Affine) AggregateVerify(pks []*P2Affine, msgs []Message, } } - return coreAggregateVerifyPkInG2(sigFn, pkFn, msgs, dst, useHash) + return coreAggregateVerifyPkInG2(sigFn, sigGroupcheck, pkFn, pksVerify, + msgs, dst, useHash) } // Aggregate verify with compressed signature and public keys // Uses a dummy signature to get the correct type -func (dummy *P1Affine) AggregateVerifyCompressed(sig []byte, pks [][]byte, - msgs []Message, dst []byte, +func (dummy *P1Affine) AggregateVerifyCompressed(sig []byte, sigGroupcheck bool, + pks [][]byte, pksVerify bool, msgs []Message, dst []byte, optional ...bool) bool { // useHash bool, usePksAsAugs bool // sanity checks and argument parsing @@ -941,12 +993,13 @@ func (dummy *P1Affine) AggregateVerifyCompressed(sig []byte, pks [][]byte, } return pk, nil } - return coreAggregateVerifyPkInG2(sigFn, pkFn, msgs, dst, useHash) + return coreAggregateVerifyPkInG2(sigFn, sigGroupcheck, pkFn, pksVerify, + msgs, dst, useHash) } // TODO: check message uniqueness -func coreAggregateVerifyPkInG2(sigFn sigGetterP1, pkFn pkGetterP2, - msgs []Message, dst []byte, +func coreAggregateVerifyPkInG2(sigFn sigGetterP1, sigGroupcheck bool, + pkFn pkGetterP2, pkValidate bool, msgs []Message, dst []byte, optional ...bool) bool { // useHash n := len(msgs) @@ -1003,8 +1056,8 @@ func coreAggregateVerifyPkInG2(sigFn sigGetterP1, pkFn pkGetterP2, } // Pairing and accumulate - ret := PairingAggregatePkInG2(pairing, curPk, nil, msgs[work], - aug) + ret := PairingAggregatePkInG2(pairing, curPk, pkValidate, + nil, false, msgs[work], aug) if ret != C.BLST_SUCCESS { atomic.StoreInt32(&valid, 0) break @@ -1027,7 +1080,12 @@ func coreAggregateVerifyPkInG2(sigFn sigGetterP1, pkFn pkGetterP2, sig := sigFn() if sig == nil { atomic.StoreInt32(&valid, 0) - } else { + } + if atomic.LoadInt32(&valid) > 0 && sigGroupcheck && + !sig.SigValidate(false) { + atomic.StoreInt32(&valid, 0) + } + if atomic.LoadInt32(&valid) > 0 { C.blst_aggregated_in_g1(>sig, sig) } mutex.Unlock() @@ -1054,8 +1112,10 @@ func coreAggregateVerifyPkInG2(sigFn sigGetterP1, pkFn pkGetterP2, return PairingFinalVerify(pairings, >sig) } -func (sig *P1Affine) FastAggregateVerify(pks []*P2Affine, msg Message, - dst []byte, +// pks are assumed to be verified for proof of possession, +// which implies that they are already group-checked +func (sig *P1Affine) FastAggregateVerify(sigGroupcheck bool, + pks []*P2Affine, msg Message, dst []byte, optional ...interface{}) bool { // pass-through to Verify n := len(pks) @@ -1064,19 +1124,19 @@ func (sig *P1Affine) FastAggregateVerify(pks []*P2Affine, msg Message, return false } - aggregator := new(P2Aggregate).Aggregate(pks) - if aggregator == nil { + aggregator := new(P2Aggregate) + if !aggregator.Aggregate(pks, false) { return false } pkAff := aggregator.ToAffine() // Verify - return sig.Verify(pkAff, msg, dst, optional...) + return sig.Verify(sigGroupcheck, pkAff, false, msg, dst, optional...) } func (dummy *P1Affine) MultipleAggregateVerify(sigs []*P1Affine, - pks []*P2Affine, msgs []Message, dst []byte, randFn func(*Scalar), - randBits int, + sigsGroupcheck bool, pks []*P2Affine, pksVerify bool, + msgs []Message, dst []byte, randFn func(*Scalar), randBits int, optional ...interface{}) bool { // useHash // Sanity checks and argument parsing @@ -1101,14 +1161,15 @@ func (dummy *P1Affine) MultipleAggregateVerify(sigs []*P1Affine, return sigs[work], pks[work], rand, aug } - return multipleAggregateVerifyPkInG2(paramsFn, msgs, dst, - randBits, useHash) + return multipleAggregateVerifyPkInG2(paramsFn, sigsGroupcheck, pksVerify, + msgs, dst, randBits, useHash) } type mulAggGetterPkInG2 func(work uint32, sig *P1Affine, pk *P2Affine, rand *Scalar) (*P1Affine, *P2Affine, *Scalar, []byte) -func multipleAggregateVerifyPkInG2(paramsFn mulAggGetterPkInG2, msgs []Message, +func multipleAggregateVerifyPkInG2(paramsFn mulAggGetterPkInG2, + sigsGroupcheck bool, pksVerify bool, msgs []Message, dst []byte, randBits int, optional ...bool) bool { // useHash n := len(msgs) @@ -1153,7 +1214,8 @@ func multipleAggregateVerifyPkInG2(paramsFn mulAggGetterPkInG2, msgs []Message, curSig, curPk, curRand, aug := paramsFn(work, &tempSig, &tempPk, &tempRand) - if PairingMulNAggregatePkInG2(pairing, curPk, curSig, curRand, + if PairingMulNAggregatePkInG2(pairing, curPk, pksVerify, + curSig, sigsGroupcheck, curRand, randBits, msgs[work], aug) != C.BLST_SUCCESS { atomic.StoreInt32(&valid, 0) @@ -1204,21 +1266,23 @@ type P1Aggregate struct { } // Aggregate uncompressed elements -func (agg *P1Aggregate) Aggregate(elmts []*P1Affine) *P1Aggregate { +func (agg *P1Aggregate) Aggregate(elmts []*P1Affine, + groupcheck bool) bool { if len(elmts) == 0 { - return agg + return true } getter := func(i uint32, _ *P1Affine) *P1Affine { return elmts[i] } - if !agg.aggregate(getter, len(elmts)) { - return nil + if !agg.aggregate(getter, groupcheck, len(elmts)) { + return false } - return agg + return true } // Aggregate compressed elements -func (agg *P1Aggregate) AggregateCompressed(elmts [][]byte) *P1Aggregate { +func (agg *P1Aggregate) AggregateCompressed(elmts [][]byte, + groupcheck bool) bool { if len(elmts) == 0 { - return agg + return true } getter := func(i uint32, p *P1Affine) *P1Affine { bytes := elmts[i] @@ -1237,13 +1301,13 @@ func (agg *P1Aggregate) AggregateCompressed(elmts [][]byte) *P1Aggregate { } return p } - if !agg.aggregate(getter, len(elmts)) { - return nil + if !agg.aggregate(getter, groupcheck, len(elmts)) { + return false } - return agg + return true } -func (agg *P1Aggregate) AddAggregate(other *P1Aggregate) *P1Aggregate { +func (agg *P1Aggregate) AddAggregate(other *P1Aggregate) { if other.v == nil { // do nothing } else if agg.v == nil { @@ -1251,17 +1315,19 @@ func (agg *P1Aggregate) AddAggregate(other *P1Aggregate) *P1Aggregate { } else { C.blst_p1_add(agg.v, agg.v, other.v) } - return agg } -func (agg *P1Aggregate) Add(elmt *P1Affine) *P1Aggregate { +func (agg *P1Aggregate) Add(elmt *P1Affine, groupcheck bool) bool { + if groupcheck && !bool(C.blst_p1_affine_in_g1(elmt)) { + return false + } if agg.v == nil { agg.v = new(P1) C.blst_p1_from_affine(agg.v, elmt) } else { C.blst_p1_add_or_double_affine(agg.v, agg.v, elmt) } - return agg + return true } func (agg *P1Aggregate) ToAffine() *P1Affine { @@ -1271,7 +1337,9 @@ func (agg *P1Aggregate) ToAffine() *P1Affine { return agg.v.ToAffine() } -func (agg *P1Aggregate) aggregate(getter aggGetterP1, n int) bool { +func (agg *P1Aggregate) aggregate(getter aggGetterP1, groupcheck bool, + n int) bool { + if n == 0 { return true } @@ -1307,6 +1375,10 @@ func (agg *P1Aggregate) aggregate(getter aggGetterP1, n int) bool { atomic.StoreInt32(&valid, 0) break } + if groupcheck && !bool(C.blst_p1_affine_in_g1(curElmt)) { + atomic.StoreInt32(&valid, 0) + break + } if first { C.blst_p1_from_affine(&agg, curElmt) first = false @@ -1368,12 +1440,7 @@ func (p1 *P1Affine) Deserialize(in []byte) *P1Affine { if len(in) != BLST_P1_SERIALIZE_BYTES { return nil } - if C.blst_p1_deserialize(p1, - (*C.byte)(&in[0])) != C.BLST_SUCCESS { - return nil - } - - if !bool(C.blst_p1_affine_in_g1(p1)) { + if C.blst_p1_deserialize(p1, (*C.byte)(&in[0])) != C.BLST_SUCCESS { return nil } return p1 @@ -1388,12 +1455,7 @@ func (p1 *P1Affine) Uncompress(in []byte) *P1Affine { if len(in) != BLST_P1_COMPRESS_BYTES { return nil } - if C.blst_p1_uncompress(p1, - (*C.byte)(&in[0])) != C.BLST_SUCCESS { - return nil - } - - if !bool(C.blst_p1_affine_in_g1(p1)) { + if C.blst_p1_uncompress(p1, (*C.byte)(&in[0])) != C.BLST_SUCCESS { return nil } return p1 @@ -1560,12 +1622,7 @@ func (p2 *P2Affine) Deserialize(in []byte) *P2Affine { if len(in) != BLST_P2_SERIALIZE_BYTES { return nil } - if C.blst_p2_deserialize(p2, - (*C.byte)(&in[0])) != C.BLST_SUCCESS { - return nil - } - - if !bool(C.blst_p2_affine_in_g2(p2)) { + if C.blst_p2_deserialize(p2, (*C.byte)(&in[0])) != C.BLST_SUCCESS { return nil } return p2 @@ -1580,12 +1637,7 @@ func (p2 *P2Affine) Uncompress(in []byte) *P2Affine { if len(in) != BLST_P2_COMPRESS_BYTES { return nil } - if C.blst_p2_uncompress(p2, - (*C.byte)(&in[0])) != C.BLST_SUCCESS { - return nil - } - - if !bool(C.blst_p2_affine_in_g2(p2)) { + if C.blst_p2_uncompress(p2, (*C.byte)(&in[0])) != C.BLST_SUCCESS { return nil } return p2 diff --git a/bindings/go/blst.tgo b/bindings/go/blst.tgo index ec3671c6..6002f125 100644 --- a/bindings/go/blst.tgo +++ b/bindings/go/blst.tgo @@ -94,8 +94,8 @@ func PairingCtx(hash_or_encode bool, DST []byte) Pairing { return ctx } -func PairingAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, - msg []byte, +func PairingAggregatePkInG1(ctx Pairing, PK *P1Affine, pkValidate bool, + sig *P2Affine, sigGroupcheck bool, msg []byte, optional ...[]byte) int { // aug var aug []byte var uaug *C.byte @@ -110,15 +110,17 @@ func PairingAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_aggregate_pk_in_g1((*C.blst_pairing)(&ctx[0]), PK, sig, - umsg, C.size_t(len(msg)), - uaug, C.size_t(len(aug))) + r := C.blst_pairing_chk_n_aggr_pk_in_g1((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), + umsg, C.size_t(len(msg)), + uaug, C.size_t(len(aug))) return int(r) } -func PairingAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, - msg []byte, +func PairingAggregatePkInG2(ctx Pairing, PK *P2Affine, pkValidate bool, + sig *P1Affine, sigGroupcheck bool, msg []byte, optional ...[]byte) int { // aug var aug []byte var uaug *C.byte @@ -133,14 +135,17 @@ func PairingAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_aggregate_pk_in_g2((*C.blst_pairing)(&ctx[0]), PK, sig, - umsg, C.size_t(len(msg)), - uaug, C.size_t(len(aug))) + r := C.blst_pairing_chk_n_aggr_pk_in_g2((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), + umsg, C.size_t(len(msg)), + uaug, C.size_t(len(aug))) return int(r) } -func PairingMulNAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, +func PairingMulNAggregatePkInG1(ctx Pairing, PK *P1Affine, pkValidate bool, + sig *P2Affine, sigGroupcheck bool, rand *Scalar, randBits int, msg []byte, optional ...[]byte) int { // aug var aug []byte @@ -156,16 +161,18 @@ func PairingMulNAggregatePkInG1(ctx Pairing, PK *P1Affine, sig *P2Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_mul_n_aggregate_pk_in_g1((*C.blst_pairing)(&ctx[0]), - PK, sig, - &rand.b[0], C.size_t(randBits), - umsg, C.size_t(len(msg)), - uaug, C.size_t(len(aug))) + r := C.blst_pairing_chk_n_mul_n_aggr_pk_in_g1((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), + &rand.b[0], C.size_t(randBits), + umsg, C.size_t(len(msg)), + uaug, C.size_t(len(aug))) return int(r) } -func PairingMulNAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, +func PairingMulNAggregatePkInG2(ctx Pairing, PK *P2Affine, pkValidate bool, + sig *P1Affine, sigGroupcheck bool, rand *Scalar, randBits int, msg []byte, optional ...[]byte) int { // aug var aug []byte @@ -181,11 +188,12 @@ func PairingMulNAggregatePkInG2(ctx Pairing, PK *P2Affine, sig *P1Affine, umsg = (*C.byte)(&msg[0]) } - r := C.blst_pairing_mul_n_aggregate_pk_in_g2((*C.blst_pairing)(&ctx[0]), - PK, sig, - &rand.b[0], C.size_t(randBits), - umsg, C.size_t(len(msg)), - uaug, C.size_t(len(aug))) + r := C.blst_pairing_chk_n_mul_n_aggr_pk_in_g2((*C.blst_pairing)(&ctx[0]), + PK, C.bool(pkValidate), + sig, C.bool(sigGroupcheck), + &rand.b[0], C.size_t(randBits), + umsg, C.size_t(len(msg)), + uaug, C.size_t(len(aug))) return int(r) } diff --git a/bindings/go/blst_minpk.tgo b/bindings/go/blst_minpk.tgo index 18845e50..44808238 100644 --- a/bindings/go/blst_minpk.tgo +++ b/bindings/go/blst_minpk.tgo @@ -10,7 +10,7 @@ import ( // func (pk *P1Affine) From(s *Scalar) *P1Affine { - C.blst_sk_to_pk2_in_g1(nil, pk, s) + C.blst_sk_to_pk2_in_g1(nil, pk, s) return pk } @@ -19,6 +19,15 @@ func (pk *P1Affine) KeyValidate() bool { bool(C.blst_p1_affine_in_g1(pk)) } +// sigInfcheck, check for infinity, is a way to avoid going +// into resource-consuming verification. Passing 'false' is +// always cryptographically safe, but application might want +// to guard against obviously bogus individual[!] signatures. +func (sig *P2Affine) SigValidate(sigInfcheck bool) bool { + return (sigInfcheck && !bool(C.blst_p2_affine_is_inf(sig))) || + bool(C.blst_p2_affine_in_g2(sig)) +} + // // Sign // @@ -50,30 +59,32 @@ type sigGetterP2 func() *P2Affine type pkGetterP1 func(i uint32, temp *P1Affine) (*P1Affine, []byte) // Single verify with decompressed pk -func (sig *P2Affine) Verify(pk *P1Affine, msg Message, dst []byte, +func (sig *P2Affine) Verify(sigGroupcheck bool, pk *P1Affine, pkValidate bool, + msg Message, dst []byte, optional ...interface{}) bool { // useHash bool, aug []byte aug, _, useHash, ok := parseOpts(optional...) if !ok { return false } - return sig.AggregateVerify([]*P1Affine{pk}, []Message{msg}, dst, - useHash, [][]byte{aug}) + return sig.AggregateVerify(sigGroupcheck, []*P1Affine{pk}, pkValidate, + []Message{msg}, dst, useHash, [][]byte{aug}) } // Single verify with compressed pk // Uses a dummy signature to get the correct type -func (dummy *P2Affine) VerifyCompressed(sig []byte, pk []byte, - msg Message, dst []byte, +func (dummy *P2Affine) VerifyCompressed(sig []byte, sigGroupcheck bool, + pk []byte, pkValidate bool, msg Message, dst []byte, optional ...bool) bool { // useHash bool, usePksAsAugs bool - return dummy.AggregateVerifyCompressed(sig, [][]byte{pk}, + return dummy.AggregateVerifyCompressed(sig, sigGroupcheck, + [][]byte{pk}, pkValidate, []Message{msg}, dst, optional...) } // Aggregate verify with uncompressed signature and public keys -func (sig *P2Affine) AggregateVerify(pks []*P1Affine, msgs []Message, - dst []byte, +func (sig *P2Affine) AggregateVerify(sigGroupcheck bool, + pks []*P1Affine, pksVerify bool, msgs []Message, dst []byte, optional ...interface{}) bool { // useHash bool, augs [][]byte // sanity checks and argument parsing @@ -99,13 +110,14 @@ func (sig *P2Affine) AggregateVerify(pks []*P1Affine, msgs []Message, } } - return coreAggregateVerifyPkInG1(sigFn, pkFn, msgs, dst, useHash) + return coreAggregateVerifyPkInG1(sigFn, sigGroupcheck, pkFn, pksVerify, + msgs, dst, useHash) } // Aggregate verify with compressed signature and public keys // Uses a dummy signature to get the correct type -func (dummy *P2Affine) AggregateVerifyCompressed(sig []byte, pks [][]byte, - msgs []Message, dst []byte, +func (dummy *P2Affine) AggregateVerifyCompressed(sig []byte, sigGroupcheck bool, + pks [][]byte, pksVerify bool, msgs []Message, dst []byte, optional ...bool) bool { // useHash bool, usePksAsAugs bool // sanity checks and argument parsing @@ -155,12 +167,13 @@ func (dummy *P2Affine) AggregateVerifyCompressed(sig []byte, pks [][]byte, } return pk, nil } - return coreAggregateVerifyPkInG1(sigFn, pkFn, msgs, dst, useHash) + return coreAggregateVerifyPkInG1(sigFn, sigGroupcheck, pkFn, pksVerify, + msgs, dst, useHash) } // TODO: check message uniqueness -func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, - msgs []Message, dst []byte, +func coreAggregateVerifyPkInG1(sigFn sigGetterP2, sigGroupcheck bool, + pkFn pkGetterP1, pkValidate bool, msgs []Message, dst []byte, optional ...bool) bool { // useHash n := len(msgs) @@ -217,8 +230,8 @@ func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, } // Pairing and accumulate - ret := PairingAggregatePkInG1(pairing, curPk, nil, msgs[work], - aug) + ret := PairingAggregatePkInG1(pairing, curPk, pkValidate, + nil, false, msgs[work], aug) if ret != C.BLST_SUCCESS { atomic.StoreInt32(&valid, 0) break @@ -241,7 +254,12 @@ func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, sig := sigFn() if sig == nil { atomic.StoreInt32(&valid, 0) - } else { + } + if atomic.LoadInt32(&valid) > 0 && sigGroupcheck && + !sig.SigValidate(false) { + atomic.StoreInt32(&valid, 0) + } + if atomic.LoadInt32(&valid) > 0 { C.blst_aggregated_in_g2(>sig, sig) } mutex.Unlock() @@ -268,8 +286,10 @@ func coreAggregateVerifyPkInG1(sigFn sigGetterP2, pkFn pkGetterP1, return PairingFinalVerify(pairings, >sig) } -func (sig *P2Affine) FastAggregateVerify(pks []*P1Affine, msg Message, - dst []byte, +// pks are assumed to be verified for proof of possession, +// which implies that they are already group-checked +func (sig *P2Affine) FastAggregateVerify(sigGroupcheck bool, + pks []*P1Affine, msg Message, dst []byte, optional ...interface{}) bool { // pass-through to Verify n := len(pks) @@ -278,19 +298,19 @@ func (sig *P2Affine) FastAggregateVerify(pks []*P1Affine, msg Message, return false } - aggregator := new(P1Aggregate).Aggregate(pks) - if aggregator == nil { + aggregator := new(P1Aggregate) + if !aggregator.Aggregate(pks, false) { return false } pkAff := aggregator.ToAffine() // Verify - return sig.Verify(pkAff, msg, dst, optional...) + return sig.Verify(sigGroupcheck, pkAff, false, msg, dst, optional...) } func (dummy *P2Affine) MultipleAggregateVerify(sigs []*P2Affine, - pks []*P1Affine, msgs []Message, dst []byte, randFn func(*Scalar), - randBits int, + sigsGroupcheck bool, pks []*P1Affine, pksVerify bool, + msgs []Message, dst []byte, randFn func(*Scalar), randBits int, optional ...interface{}) bool { // useHash // Sanity checks and argument parsing @@ -315,14 +335,15 @@ func (dummy *P2Affine) MultipleAggregateVerify(sigs []*P2Affine, return sigs[work], pks[work], rand, aug } - return multipleAggregateVerifyPkInG1(paramsFn, msgs, dst, - randBits, useHash) + return multipleAggregateVerifyPkInG1(paramsFn, sigsGroupcheck, pksVerify, + msgs, dst, randBits, useHash) } type mulAggGetterPkInG1 func(work uint32, sig *P2Affine, pk *P1Affine, rand *Scalar) (*P2Affine, *P1Affine, *Scalar, []byte) -func multipleAggregateVerifyPkInG1(paramsFn mulAggGetterPkInG1, msgs []Message, +func multipleAggregateVerifyPkInG1(paramsFn mulAggGetterPkInG1, + sigsGroupcheck bool, pksVerify bool, msgs []Message, dst []byte, randBits int, optional ...bool) bool { // useHash n := len(msgs) @@ -367,7 +388,8 @@ func multipleAggregateVerifyPkInG1(paramsFn mulAggGetterPkInG1, msgs []Message, curSig, curPk, curRand, aug := paramsFn(work, &tempSig, &tempPk, &tempRand) - if PairingMulNAggregatePkInG1(pairing, curPk, curSig, curRand, + if PairingMulNAggregatePkInG1(pairing, curPk, pksVerify, + curSig, sigsGroupcheck, curRand, randBits, msgs[work], aug) != C.BLST_SUCCESS { atomic.StoreInt32(&valid, 0) @@ -418,21 +440,23 @@ type P2Aggregate struct { } // Aggregate uncompressed elements -func (agg *P2Aggregate) Aggregate(elmts []*P2Affine) *P2Aggregate { +func (agg *P2Aggregate) Aggregate(elmts []*P2Affine, + groupcheck bool) bool { if len(elmts) == 0 { - return agg + return true } getter := func(i uint32, _ *P2Affine) *P2Affine { return elmts[i] } - if !agg.aggregate(getter, len(elmts)) { - return nil + if !agg.aggregate(getter, groupcheck, len(elmts)) { + return false } - return agg + return true } // Aggregate compressed elements -func (agg *P2Aggregate) AggregateCompressed(elmts [][]byte) *P2Aggregate { +func (agg *P2Aggregate) AggregateCompressed(elmts [][]byte, + groupcheck bool) bool { if len(elmts) == 0 { - return agg + return true } getter := func(i uint32, p *P2Affine) *P2Affine { bytes := elmts[i] @@ -451,13 +475,13 @@ func (agg *P2Aggregate) AggregateCompressed(elmts [][]byte) *P2Aggregate { } return p } - if !agg.aggregate(getter, len(elmts)) { - return nil + if !agg.aggregate(getter, groupcheck, len(elmts)) { + return false } - return agg + return true } -func (agg *P2Aggregate) AddAggregate(other *P2Aggregate) *P2Aggregate { +func (agg *P2Aggregate) AddAggregate(other *P2Aggregate) { if other.v == nil { // do nothing } else if agg.v == nil { @@ -465,17 +489,19 @@ func (agg *P2Aggregate) AddAggregate(other *P2Aggregate) *P2Aggregate { } else { C.blst_p2_add(agg.v, agg.v, other.v) } - return agg } -func (agg *P2Aggregate) Add(elmt *P2Affine) *P2Aggregate { +func (agg *P2Aggregate) Add(elmt *P2Affine, groupcheck bool) bool { + if groupcheck && !bool(C.blst_p2_affine_in_g2(elmt)) { + return false + } if agg.v == nil { agg.v = new(P2) C.blst_p2_from_affine(agg.v, elmt) } else { C.blst_p2_add_or_double_affine(agg.v, agg.v, elmt) } - return agg + return true } func (agg *P2Aggregate) ToAffine() *P2Affine { @@ -485,7 +511,9 @@ func (agg *P2Aggregate) ToAffine() *P2Affine { return agg.v.ToAffine() } -func (agg *P2Aggregate) aggregate(getter aggGetterP2, n int) bool { +func (agg *P2Aggregate) aggregate(getter aggGetterP2, groupcheck bool, + n int) bool { + if n == 0 { return true } @@ -521,6 +549,10 @@ func (agg *P2Aggregate) aggregate(getter aggGetterP2, n int) bool { atomic.StoreInt32(&valid, 0) break } + if groupcheck && !bool(C.blst_p2_affine_in_g2(curElmt)) { + atomic.StoreInt32(&valid, 0) + break + } if first { C.blst_p2_from_affine(&agg, curElmt) first = false diff --git a/bindings/go/blst_minpk_test.go b/bindings/go/blst_minpk_test.go index b20aa3e0..71c0ac8f 100644 --- a/bindings/go/blst_minpk_test.go +++ b/bindings/go/blst_minpk_test.go @@ -102,49 +102,54 @@ func TestSignVerifyMinPk(t *testing.T) { sig1 := new(SignatureMinPk).Sign(sk1, msg1, dstMinPk) // Verify - if !sig0.Verify(pk0, msg0, dstMinPk) { + if !sig0.Verify(true, pk0, false, msg0, dstMinPk) { t.Errorf("verify sig0") } - if !sig1.Verify(pk1, msg1, dstMinPk) { + if !sig1.Verify(true, pk1, false, msg1, dstMinPk) { t.Errorf("verify sig1") } - if !new(SignatureMinPk).VerifyCompressed(sig1.Compress(), pk1.Compress(), - msg1, dstMinPk) { + if !new(SignatureMinPk).VerifyCompressed(sig1.Compress(), true, + pk1.Compress(), false, + msg1, dstMinPk) { t.Errorf("verify sig1") } // Batch verify - if !sig0.AggregateVerify([]*PublicKeyMinPk{pk0}, []Message{msg0}, - dstMinPk) { + if !sig0.AggregateVerify(true, []*PublicKeyMinPk{pk0}, false, + []Message{msg0}, dstMinPk) { t.Errorf("aggregate verify sig0") } // Verify compressed inputs - if !new(SignatureMinPk).AggregateVerifyCompressed(sig0.Compress(), - [][]byte{pk0.Compress()}, []Message{msg0}, dstMinPk) { + if !new(SignatureMinPk).AggregateVerifyCompressed(sig0.Compress(), true, + [][]byte{pk0.Compress()}, + false, + []Message{msg0}, dstMinPk) { t.Errorf("aggregate verify sig0 compressed") } // Verify serialized inputs - if !new(SignatureMinPk).AggregateVerifyCompressed(sig0.Serialize(), - [][]byte{pk0.Serialize()}, []Message{msg0}, dstMinPk) { + if !new(SignatureMinPk).AggregateVerifyCompressed(sig0.Serialize(), true, + [][]byte{pk0.Serialize()}, + false, + []Message{msg0}, dstMinPk) { t.Errorf("aggregate verify sig0 serialized") } // Compressed with empty pk var emptyPk []byte - if new(SignatureMinPk).VerifyCompressed(sig0.Compress(), emptyPk, msg0, - dstMinPk) { + if new(SignatureMinPk).VerifyCompressed(sig0.Compress(), true, + emptyPk, false, msg0, dstMinPk) { t.Errorf("verify sig compressed inputs") } // Wrong message - if sig0.Verify(pk0, msg1, dstMinPk) { + if sig0.Verify(true, pk0, false, msg1, dstMinPk) { t.Errorf("Expected Verify to return false") } // Wrong key - if sig0.Verify(pk1, msg0, dstMinPk) { + if sig0.Verify(true, pk1, false, msg0, dstMinPk) { t.Errorf("Expected Verify to return false") } // Wrong sig - if sig1.Verify(pk0, msg0, dstMinPk) { + if sig1.Verify(true, pk0, false, msg0, dstMinPk) { t.Errorf("Expected Verify to return false") } } @@ -155,14 +160,14 @@ func TestSignVerifyAugMinPk(t *testing.T) { msg := []byte("hello foo") aug := []byte("augmentation") sig := new(SignatureMinPk).Sign(sk, msg, dstMinPk, aug) - if !sig.Verify(pk, msg, dstMinPk, aug) { + if !sig.Verify(true, pk, false, msg, dstMinPk, aug) { t.Errorf("verify sig") } aug2 := []byte("augmentation2") - if sig.Verify(pk, msg, dstMinPk, aug2) { + if sig.Verify(true, pk, false, msg, dstMinPk, aug2) { t.Errorf("verify sig, wrong augmentation") } - if sig.Verify(pk, msg, dstMinPk) { + if sig.Verify(true, pk, false, msg, dstMinPk) { t.Errorf("verify sig, no augmentation") } // TODO: augmentation with aggregate verify @@ -173,13 +178,13 @@ func TestSignVerifyEncodeMinPk(t *testing.T) { pk := new(PublicKeyMinPk).From(sk) msg := []byte("hello foo") sig := new(SignatureMinPk).Sign(sk, msg, dstMinPk, false) - if !sig.Verify(pk, msg, dstMinPk, false) { + if !sig.Verify(true, pk, false, msg, dstMinPk, false) { t.Errorf("verify sig") } - if sig.Verify(pk, msg, dstMinPk) { + if sig.Verify(true, pk, false, msg, dstMinPk) { t.Errorf("verify sig expected fail, wrong hashing engine") } - if sig.Verify(pk, msg, dstMinPk, 0) { + if sig.Verify(true, pk, false, msg, dstMinPk, 0) { t.Errorf("verify sig expected fail, illegal argument") } } @@ -199,8 +204,8 @@ func TestSignVerifyAggregateMinPk(t *testing.T) { sigs = append(sigs, new(SignatureMinPk).Sign(sks[i], msgs[0], dstMinPk)) } - agProj := new(AggregateSignatureMinPk).Aggregate(sigs) - if agProj == nil { + agProj := new(AggregateSignatureMinPk) + if !agProj.Aggregate(sigs, false) { t.Errorf("Aggregate unexpectedly returned nil") return } @@ -224,8 +229,8 @@ func TestSignVerifyAggregateMinPk(t *testing.T) { compSigs[i] = sigs[i].Serialize() } } - agProj = new(AggregateSignatureMinPk).AggregateCompressed(compSigs) - if agProj == nil { + agProj = new(AggregateSignatureMinPk) + if !agProj.AggregateCompressed(compSigs, false) { t.Errorf("AggregateCompressed unexpectedly returned nil") return } @@ -268,18 +273,25 @@ func TestSignMultipleVerifyAggregateMinPk(t *testing.T) { sigsToAgg := make([]*SignatureMinPk, 0) pksToAgg := make([]*PublicKeyMinPk, 0) for j := 0; j < size; j++ { - sigsToAgg = append(sigsToAgg, new(SignatureMinPk).Sign(sks[j], - msgs[i], dstMinPk)) + sigsToAgg = append(sigsToAgg, + new(SignatureMinPk).Sign(sks[j], msgs[i], + dstMinPk)) pksToAgg = append(pksToAgg, pks[j]) } - agSig := new(AggregateSignatureMinPk).Aggregate(sigsToAgg).ToAffine() - agPk := new(AggregatePublicKeyMinPk).Aggregate(pksToAgg).ToAffine() - aggSigs = append(aggSigs, agSig) - aggPks = append(aggPks, agPk) + agSig := new(AggregateSignatureMinPk) + if !agSig.Aggregate(sigsToAgg, true) { + t.Errorf("failed to aggregate") + } + afSig := agSig.ToAffine() + agPk := new(AggregatePublicKeyMinPk) + agPk.Aggregate(pksToAgg, false) + afPk := agPk.ToAffine() + aggSigs = append(aggSigs, afSig) + aggPks = append(aggPks, afPk) // Verify aggregated signature and pk - if !agSig.Verify(agPk, msgs[i], dstMinPk) { + if !afSig.Verify(false, afPk, false, msgs[i], dstMinPk) { t.Errorf("failed to verify single aggregate size %d", size) } @@ -293,14 +305,18 @@ func TestSignMultipleVerifyAggregateMinPk(t *testing.T) { // Verify randBits := 64 - if !new(SignatureMinPk).MultipleAggregateVerify(aggSigs, aggPks, msgs, - dstMinPk, randFn, randBits) { + if !new(SignatureMinPk).MultipleAggregateVerify(aggSigs, true, + aggPks, false, + msgs, dstMinPk, + randFn, randBits) { t.Errorf("failed to verify multiple aggregate size %d", size) } // Negative test - if new(SignatureMinPk).MultipleAggregateVerify(aggSigs, aggPks, msgs, - dstMinPk[1:], randFn, randBits) { + if new(SignatureMinPk).MultipleAggregateVerify(aggSigs, true, + aggPks, false, + msgs, dstMinPk[1:], + randFn, randBits) { t.Errorf("failed to not verify multiple aggregate size %d", size) } } @@ -358,7 +374,7 @@ func BenchmarkCoreVerifyMinPk(b *testing.B) { // Verify for i := 0; i < b.N; i++ { - if !sig.Verify(pk, msg, dstMinPk) { + if !sig.Verify(true, pk, false, msg, dstMinPk) { b.Fatal("verify sig") } } @@ -373,8 +389,9 @@ func BenchmarkCoreVerifyAggregateMinPk(b *testing.B) { } b.ResetTimer() for i := 0; i < b.N; i++ { - if !new(SignatureMinPk).AggregateVerifyCompressed(agsig, pubks, - msgs, dstMinPk) { + if !new(SignatureMinPk).AggregateVerifyCompressed(agsig, true, + pubks, false, + msgs, dstMinPk) { b.Fatal("failed to verify") } } @@ -400,7 +417,7 @@ func BenchmarkVerifyAggregateUncompressedMinPk(b *testing.B) { } b.ResetTimer() for i := 0; i < b.N; i++ { - if !agsig.AggregateVerify(pubks, msgs, dstMinPk) { + if !agsig.AggregateVerify(true, pubks, false, msgs, dstMinPk) { b.Fatal("failed to verify") } } @@ -426,7 +443,7 @@ func BenchmarkCoreAggregateMinPk(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { var agg AggregateSignatureMinPk - agg.AggregateCompressed(sigs) + agg.AggregateCompressed(sigs, true) } } } @@ -462,8 +479,8 @@ func generateBatchTestDataMinPk(size int) (msgs []Message, Compress()) pubks = append(pubks, new(PublicKeyMinPk).From(priv).Compress()) } - agProj := new(AggregateSignatureMinPk).AggregateCompressed(sigs) - if agProj == nil { + agProj := new(AggregateSignatureMinPk) + if !agProj.AggregateCompressed(sigs, true) { fmt.Println("AggregateCompressed unexpectedly returned nil") err = true return @@ -490,8 +507,8 @@ func generateBatchTestDataUncompressedMinPk(size int) (sks []*SecretKey, sigs = append(sigs, new(SignatureMinPk).Sign(priv, msg, dstMinPk)) pubks = append(pubks, new(PublicKeyMinPk).From(priv)) } - agProj := new(AggregateSignatureMinPk).Aggregate(sigs) - if agProj == nil { + agProj := new(AggregateSignatureMinPk) + if !agProj.Aggregate(sigs, true) { fmt.Println("Aggregate unexpectedly returned nil") err = true return @@ -552,14 +569,14 @@ func TestSignVerifyAggregateValidatesInfinitePubkeyMinPk(t *testing.T) { // Single message: Infinite pubkeys and signature zeroKey := new(PublicKeyMinPk) zeroSig := new(SignatureMinPk) - agProj := new(AggregateSignatureMinPk).Aggregate([]*SignatureMinPk{zeroSig}) - if agProj == nil { + agProj := new(AggregateSignatureMinPk) + if !agProj.Aggregate([]*SignatureMinPk{zeroSig}, false) { t.Errorf("Aggregate unexpectedly returned nil") return } agSig := agProj.ToAffine() - if agSig.AggregateVerify([]*PublicKeyMinPk{zeroKey}, + if agSig.AggregateVerify(false, []*PublicKeyMinPk{zeroKey}, false, [][]byte{msgs[0]}, dstMinPk) { t.Errorf("failed to NOT verify signature") } @@ -567,14 +584,14 @@ func TestSignVerifyAggregateValidatesInfinitePubkeyMinPk(t *testing.T) { // Replace firstkey with infinite pubkey. pubks[0] = zeroKey sigs[0] = zeroSig - agProj = new(AggregateSignatureMinPk).Aggregate(sigs) - if agProj == nil { + agProj = new(AggregateSignatureMinPk) + if !agProj.Aggregate(sigs, false) { t.Errorf("Aggregate unexpectedly returned nil") return } agSig = agProj.ToAffine() - if agSig.AggregateVerify(pubks, msgs, dstMinPk) { + if agSig.AggregateVerify(false, pubks, false, msgs, dstMinPk) { t.Errorf("failed to NOT verify signature") } } diff --git a/bindings/go/blst_minsig_test.go b/bindings/go/blst_minsig_test.go index a6ac002a..b50bdbba 100644 --- a/bindings/go/blst_minsig_test.go +++ b/bindings/go/blst_minsig_test.go @@ -106,49 +106,54 @@ func TestSignVerifyMinSig(t *testing.T) { sig2 := new(SignatureMinSig).Sign(sk1, msg2, dstMinSig) // Verify - if !sig0.Verify(pk0, msg0, dstMinSig) { + if !sig0.Verify(true, pk0, false, msg0, dstMinSig) { t.Errorf("verify sig0") } - if !sig2.Verify(pk1, msg2, dstMinSig) { + if !sig2.Verify(true, pk1, false, msg2, dstMinSig) { t.Errorf("verify sig2") } - if !new(SignatureMinSig).VerifyCompressed(sig2.Compress(), pk1.Compress(), - msg2, dstMinSig) { + if !new(SignatureMinSig).VerifyCompressed(sig2.Compress(), true, + pk1.Compress(), false, + msg2, dstMinSig) { t.Errorf("verify sig2") } // Batch verify - if !sig0.AggregateVerify([]*PublicKeyMinSig{pk0}, []Message{msg0}, - dstMinSig) { + if !sig0.AggregateVerify(true, []*PublicKeyMinSig{pk0}, false, + []Message{msg0}, dstMinSig) { t.Errorf("aggregate verify sig0") } // Verify compressed inputs - if !new(SignatureMinSig).AggregateVerifyCompressed(sig0.Compress(), - [][]byte{pk0.Compress()}, []Message{msg0}, dstMinSig) { + if !new(SignatureMinSig).AggregateVerifyCompressed(sig0.Compress(), true, + [][]byte{pk0.Compress()}, + false, + []Message{msg0}, dstMinSig) { t.Errorf("aggregate verify sig0 compressed") } // Verify serialized inputs - if !new(SignatureMinSig).AggregateVerifyCompressed(sig0.Serialize(), - [][]byte{pk0.Serialize()}, []Message{msg0}, dstMinSig) { + if !new(SignatureMinSig).AggregateVerifyCompressed(sig0.Serialize(), true, + [][]byte{pk0.Serialize()}, + false, + []Message{msg0}, dstMinSig) { t.Errorf("aggregate verify sig0 serialized") } // Compressed with empty pk var emptyPk []byte - if new(SignatureMinSig).VerifyCompressed(sig0.Compress(), emptyPk, msg0, - dstMinSig) { + if new(SignatureMinSig).VerifyCompressed(sig0.Compress(), true, + emptyPk, false, msg0, dstMinSig) { t.Errorf("verify sig compressed inputs") } // Wrong message - if sig0.Verify(pk0, msg2, dstMinSig) { + if sig0.Verify(true, pk0, false, msg2, dstMinSig) { t.Errorf("Expected Verify to return false") } // Wrong key - if sig0.Verify(pk1, msg0, dstMinSig) { + if sig0.Verify(true, pk1, false, msg0, dstMinSig) { t.Errorf("Expected Verify to return false") } // Wrong sig - if sig2.Verify(pk0, msg0, dstMinSig) { + if sig2.Verify(true, pk0, false, msg0, dstMinSig) { t.Errorf("Expected Verify to return false") } } @@ -159,14 +164,14 @@ func TestSignVerifyAugMinSig(t *testing.T) { msg := []byte("hello foo") aug := []byte("augmentation") sig := new(SignatureMinSig).Sign(sk, msg, dstMinSig, aug) - if !sig.Verify(pk, msg, dstMinSig, aug) { + if !sig.Verify(true, pk, false, msg, dstMinSig, aug) { t.Errorf("verify sig") } aug1 := []byte("augmentation2") - if sig.Verify(pk, msg, dstMinSig, aug1) { + if sig.Verify(true, pk, false, msg, dstMinSig, aug1) { t.Errorf("verify sig, wrong augmentation") } - if sig.Verify(pk, msg, dstMinSig) { + if sig.Verify(true, pk, false, msg, dstMinSig) { t.Errorf("verify sig, no augmentation") } // TODO: augmentation with aggregate verify @@ -177,13 +182,13 @@ func TestSignVerifyEncodeMinSig(t *testing.T) { pk := new(PublicKeyMinSig).From(sk) msg := []byte("hello foo") sig := new(SignatureMinSig).Sign(sk, msg, dstMinSig, false) - if !sig.Verify(pk, msg, dstMinSig, false) { + if !sig.Verify(true, pk, false, msg, dstMinSig, false) { t.Errorf("verify sig") } - if sig.Verify(pk, msg, dstMinSig) { + if sig.Verify(true, pk, false, msg, dstMinSig) { t.Errorf("verify sig expected fail, wrong hashing engine") } - if sig.Verify(pk, msg, dstMinSig, 0) { + if sig.Verify(true, pk, false, msg, dstMinSig, 0) { t.Errorf("verify sig expected fail, illegal argument") } } @@ -203,8 +208,8 @@ func TestSignVerifyAggregateMinSig(t *testing.T) { sigs = append(sigs, new(SignatureMinSig).Sign(sks[i], msgs[0], dstMinSig)) } - agProj := new(AggregateSignatureMinSig).Aggregate(sigs) - if agProj == nil { + agProj := new(AggregateSignatureMinSig) + if !agProj.Aggregate(sigs, false) { t.Errorf("Aggregate unexpectedly returned nil") return } @@ -228,8 +233,8 @@ func TestSignVerifyAggregateMinSig(t *testing.T) { compSigs[i] = sigs[i].Serialize() } } - agProj = new(AggregateSignatureMinSig).AggregateCompressed(compSigs) - if agProj == nil { + agProj = new(AggregateSignatureMinSig) + if !agProj.AggregateCompressed(compSigs, false) { t.Errorf("AggregateCompressed unexpectedly returned nil") return } @@ -272,18 +277,25 @@ func TestSignMultipleVerifyAggregateMinSig(t *testing.T) { sigsToAgg := make([]*SignatureMinSig, 0) pksToAgg := make([]*PublicKeyMinSig, 0) for j := 0; j < size; j++ { - sigsToAgg = append(sigsToAgg, new(SignatureMinSig).Sign(sks[j], - msgs[i], dstMinSig)) + sigsToAgg = append(sigsToAgg, + new(SignatureMinSig).Sign(sks[j], msgs[i], + dstMinSig)) pksToAgg = append(pksToAgg, pks[j]) } - agSig := new(AggregateSignatureMinSig).Aggregate(sigsToAgg).ToAffine() - agPk := new(AggregatePublicKeyMinSig).Aggregate(pksToAgg).ToAffine() - aggSigs = append(aggSigs, agSig) - aggPks = append(aggPks, agPk) + agSig := new(AggregateSignatureMinSig) + if !agSig.Aggregate(sigsToAgg, true) { + t.Errorf("failed to aggregate") + } + afSig := agSig.ToAffine() + agPk := new(AggregatePublicKeyMinSig) + agPk.Aggregate(pksToAgg, false) + afPk := agPk.ToAffine() + aggSigs = append(aggSigs, afSig) + aggPks = append(aggPks, afPk) // Verify aggregated signature and pk - if !agSig.Verify(agPk, msgs[i], dstMinSig) { + if !afSig.Verify(false, afPk, false, msgs[i], dstMinSig) { t.Errorf("failed to verify single aggregate size %d", size) } @@ -297,14 +309,18 @@ func TestSignMultipleVerifyAggregateMinSig(t *testing.T) { // Verify randBits := 64 - if !new(SignatureMinSig).MultipleAggregateVerify(aggSigs, aggPks, msgs, - dstMinSig, randFn, randBits) { + if !new(SignatureMinSig).MultipleAggregateVerify(aggSigs, true, + aggPks, false, + msgs, dstMinSig, + randFn, randBits) { t.Errorf("failed to verify multiple aggregate size %d", size) } // Negative test - if new(SignatureMinSig).MultipleAggregateVerify(aggSigs, aggPks, msgs, - dstMinSig[1:], randFn, randBits) { + if new(SignatureMinSig).MultipleAggregateVerify(aggSigs, true, + aggPks, false, + msgs, dstMinSig[1:], + randFn, randBits) { t.Errorf("failed to not verify multiple aggregate size %d", size) } } @@ -362,7 +378,7 @@ func BenchmarkCoreVerifyMinSig(b *testing.B) { // Verify for i := 0; i < b.N; i++ { - if !sig.Verify(pk, msg, dstMinSig) { + if !sig.Verify(true, pk, false, msg, dstMinSig) { b.Fatal("verify sig") } } @@ -377,8 +393,9 @@ func BenchmarkCoreVerifyAggregateMinSig(b *testing.B) { } b.ResetTimer() for i := 0; i < b.N; i++ { - if !new(SignatureMinSig).AggregateVerifyCompressed(agsig, pubks, - msgs, dstMinSig) { + if !new(SignatureMinSig).AggregateVerifyCompressed(agsig, true, + pubks, false, + msgs, dstMinSig) { b.Fatal("failed to verify") } } @@ -404,7 +421,7 @@ func BenchmarkVerifyAggregateUncompressedMinSig(b *testing.B) { } b.ResetTimer() for i := 0; i < b.N; i++ { - if !agsig.AggregateVerify(pubks, msgs, dstMinSig) { + if !agsig.AggregateVerify(true, pubks, false, msgs, dstMinSig) { b.Fatal("failed to verify") } } @@ -430,7 +447,7 @@ func BenchmarkCoreAggregateMinSig(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { var agg AggregateSignatureMinSig - agg.AggregateCompressed(sigs) + agg.AggregateCompressed(sigs, true) } } } @@ -466,8 +483,8 @@ func generateBatchTestDataMinSig(size int) (msgs []Message, Compress()) pubks = append(pubks, new(PublicKeyMinSig).From(priv).Compress()) } - agProj := new(AggregateSignatureMinSig).AggregateCompressed(sigs) - if agProj == nil { + agProj := new(AggregateSignatureMinSig) + if !agProj.AggregateCompressed(sigs, true) { fmt.Println("AggregateCompressed unexpectedly returned nil") err = true return @@ -494,8 +511,8 @@ func generateBatchTestDataUncompressedMinSig(size int) (sks []*SecretKey, sigs = append(sigs, new(SignatureMinSig).Sign(priv, msg, dstMinSig)) pubks = append(pubks, new(PublicKeyMinSig).From(priv)) } - agProj := new(AggregateSignatureMinSig).Aggregate(sigs) - if agProj == nil { + agProj := new(AggregateSignatureMinSig) + if !agProj.Aggregate(sigs, true) { fmt.Println("Aggregate unexpectedly returned nil") err = true return @@ -556,14 +573,14 @@ func TestSignVerifyAggregateValidatesInfinitePubkeyMinSig(t *testing.T) { // Single message: Infinite pubkeys and signature zeroKey := new(PublicKeyMinSig) zeroSig := new(SignatureMinSig) - agProj := new(AggregateSignatureMinSig).Aggregate([]*SignatureMinSig{zeroSig}) - if agProj == nil { + agProj := new(AggregateSignatureMinSig) + if !agProj.Aggregate([]*SignatureMinSig{zeroSig}, false) { t.Errorf("Aggregate unexpectedly returned nil") return } agSig := agProj.ToAffine() - if agSig.AggregateVerify([]*PublicKeyMinSig{zeroKey}, + if agSig.AggregateVerify(false, []*PublicKeyMinSig{zeroKey}, false, [][]byte{msgs[0]}, dstMinSig) { t.Errorf("failed to NOT verify signature") } @@ -571,14 +588,14 @@ func TestSignVerifyAggregateValidatesInfinitePubkeyMinSig(t *testing.T) { // Replace firstkey with infinite pubkey. pubks[0] = zeroKey sigs[0] = zeroSig - agProj = new(AggregateSignatureMinSig).Aggregate(sigs) - if agProj == nil { + agProj = new(AggregateSignatureMinSig) + if !agProj.Aggregate(sigs, false) { t.Errorf("Aggregate unexpectedly returned nil") return } agSig = agProj.ToAffine() - if agSig.AggregateVerify(pubks, msgs, dstMinSig) { + if agSig.AggregateVerify(false, pubks, false, msgs, dstMinSig) { t.Errorf("failed to NOT verify signature") } } diff --git a/bindings/go/blst_px.tgo b/bindings/go/blst_px.tgo index 58a8b8a0..56ad5e72 100644 --- a/bindings/go/blst_px.tgo +++ b/bindings/go/blst_px.tgo @@ -14,12 +14,7 @@ func (p1 *P1Affine) Deserialize(in []byte) *P1Affine { if len(in) != BLST_P1_SERIALIZE_BYTES { return nil } - if C.blst_p1_deserialize(p1, - (*C.byte)(&in[0])) != C.BLST_SUCCESS { - return nil - } - - if !bool(C.blst_p1_affine_in_g1(p1)) { + if C.blst_p1_deserialize(p1, (*C.byte)(&in[0])) != C.BLST_SUCCESS { return nil } return p1 @@ -34,12 +29,7 @@ func (p1 *P1Affine) Uncompress(in []byte) *P1Affine { if len(in) != BLST_P1_COMPRESS_BYTES { return nil } - if C.blst_p1_uncompress(p1, - (*C.byte)(&in[0])) != C.BLST_SUCCESS { - return nil - } - - if !bool(C.blst_p1_affine_in_g1(p1)) { + if C.blst_p1_uncompress(p1, (*C.byte)(&in[0])) != C.BLST_SUCCESS { return nil } return p1