Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New blstypes #34

Merged
merged 2 commits into from
Mar 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 42 additions & 64 deletions bgls/bgls.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,30 +40,6 @@ func LoadPublicKey(curve CurveSystem, sk *big.Int) Point2 {
return pubKey
}

// Authenticate generates an Authentication for a valid *big.Int/Point2 combo
// It signs a verification key with x.
func Authenticate(curve CurveSystem, sk *big.Int) Point1 {
return AuthenticateCustHash(curve, sk, curve.HashToG1)
}

// AuthenticateCustHash generates an Authentication for a valid *big.Int/Point2 combo
// It signs a verification key with x. This runs with the specified hash function.
func AuthenticateCustHash(curve CurveSystem, sk *big.Int, hash func([]byte) Point1) Point1 {
m := LoadPublicKey(curve, sk).Marshal()
return SignCustHash(sk, m, hash)
}

//CheckAuthentication verifies that this Point2 is valid
func CheckAuthentication(curve CurveSystem, v Point2, authentication Point1) bool {
return CheckAuthenticationCustHash(curve, v, authentication, curve.HashToG1)
}

//CheckAuthenticationCustHash verifies that this Point2 is valid, with the specified hash function
func CheckAuthenticationCustHash(curve CurveSystem, v Point2, authentication Point1, hash func([]byte) Point1) bool {
m := v.Marshal()
return VerifyCustHash(curve, v, m, authentication, hash)
}

//Sign creates a signature on a message with a private key
func Sign(curve CurveSystem, sk *big.Int, m []byte) Point1 {
return SignCustHash(sk, m, curve.HashToG1)
Expand Down Expand Up @@ -95,29 +71,34 @@ func VerifyCustHash(curve CurveSystem, pubKey Point2, m []byte, sig Point1, hash

// AggregateG1 takes the sum of points on G1. This is used to convert a set of signatures into a single signature
func AggregateG1(sigs []Point1) Point1 {
c := make(chan Point1)
if len(sigs) == 2 {
if len(sigs) == 2 { // No parallelization needed
aggG1, _ := sigs[0].Add(sigs[1])
return aggG1
}
// Aggregate all the g1 signatures together using concurrency
c := make(chan Point1)
aggSigs := make([]Point1, (len(sigs)/2)+(len(sigs)%2))
counter := 0
for i := 0; i < len(sigs); i += 2 { // No parallelization needed
go concurrentAggregateG1(i, i+2, sigs, c)

// Initialize aggsigs to an array with signatures being the sum of two
// adjacent signatures.
for i := 0; i < len(sigs); i += 2 {
go concurrentAggregateG1(i, sigs, c)
counter++
}
for i := 0; i < counter; i++ {
aggSigs[i] = <-c
}

// Keep on aggregating every pair of signatures until only one signature remains
for {
nxtAggSigs := make([]Point1, (len(aggSigs)/2)+(len(aggSigs)%2))
counter = 0
if len(aggSigs) == 1 {
break
}
for i := 0; i < len(aggSigs); i += 2 {
go concurrentAggregateG1(i, i+2, aggSigs, c)
go concurrentAggregateG1(i, aggSigs, c)
counter++
}
for i := 0; i < counter; i++ {
Expand All @@ -128,40 +109,47 @@ func AggregateG1(sigs []Point1) Point1 {
return aggSigs[0]
}

func concurrentAggregateG1(start int, end int, sigs []Point1, c chan Point1) {
if end > len(sigs) {
// concurrentAggregateG1 handles the channel for concurrent Aggregation of g1 points.
// It only adds the element at keys[start] and keys[start + 1], and sends it through the channel
func concurrentAggregateG1(start int, sigs []Point1, c chan Point1) {
if start+1 >= len(sigs) {
c <- sigs[start]
return
}
summed, _ := sigs[start].Add(sigs[end-1])
summed, _ := sigs[start].Add(sigs[start+1])
c <- summed
}

// AggregateG2 takes the sum of points on G2. This is used to sum a set of public keys for the multisignature
func AggregateG2(keys []Point2) Point2 {
c := make(chan Point2)
if len(keys) == 2 { // No parallelization needed
aggG2, _ := keys[0].Add(keys[1])
return aggG2
}
// Aggregate all the g2 points together using concurrency
c := make(chan Point2)
aggKeys := make([]Point2, (len(keys)/2)+(len(keys)%2))
counter := 0

// Initialize aggKeys to an array with elements being the sum of two
// adjacent Point 2's.
for i := 0; i < len(keys); i += 2 {
go concurrentAggregateG2(i, i+2, keys, c)
go concurrentAggregateG2(i, keys, c)
counter++
}
for i := 0; i < counter; i++ {
aggKeys[i] = <-c
}

// Keep on aggregating every pair of keys until only one aggregate key remains
for {
nxtAggKeys := make([]Point2, (len(aggKeys)/2)+(len(aggKeys)%2))
counter = 0
if len(aggKeys) == 1 {
break
}
for i := 0; i < len(aggKeys); i += 2 {
go concurrentAggregateG2(i, i+2, aggKeys, c)
go concurrentAggregateG2(i, aggKeys, c)
counter++
}
for i := 0; i < counter; i++ {
Expand All @@ -172,24 +160,31 @@ func AggregateG2(keys []Point2) Point2 {
return aggKeys[0]
}

func concurrentAggregateG2(start int, end int, keys []Point2, c chan Point2) {
if end > len(keys) {
// concurrentAggregateG2 handles the channel for concurrent Aggregation of g2 points.
// It only adds the element at keys[start] and keys[start + 1], and sends it through the channel
func concurrentAggregateG2(start int, keys []Point2, c chan Point2) {
if start+1 >= len(keys) {
c <- keys[start]
return
}
summed, _ := keys[start].Add(keys[end-1])
summed, _ := keys[start].Add(keys[start+1])
c <- summed
}

// Verify checks that all messages were signed by associated keys
// Will fail under duplicate messages
func (a AggSig) Verify(curve CurveSystem) bool {
return VerifyAggregateSignature(curve, a.sig, a.keys, a.msgs, false)
func (a *AggSig) Verify(curve CurveSystem) bool {
return VerifyAggregateSignature(curve, a.sig, a.keys, a.msgs)
}

// VerifyAggregateSignature verifies that the aggregated signature proves that all messages were signed by associated keys
// Will fail under duplicate messages, unless allow duplicates is True.
func VerifyAggregateSignature(curve CurveSystem, aggsig Point1, keys []Point2, msgs [][]byte, allowDuplicates bool) bool {
// Will fail if there are duplicate messages, due to the possibility of the rogue public-key attack.
// If duplicate messages should be allowed, one of the protections against the rogue public-key attack should be used
// such as Knowledge of Secret Key (Kosk), enforcing distinct messages, or the method discussed
// here <https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html>
func VerifyAggregateSignature(curve CurveSystem, aggsig Point1, keys []Point2, msgs [][]byte) bool {
return verifyAggSig(curve, aggsig, keys, msgs, false)
}

func verifyAggSig(curve CurveSystem, aggsig Point1, keys []Point2, msgs [][]byte, allowDuplicates bool) bool {
if len(keys) != len(msgs) {
return false
}
Expand All @@ -213,33 +208,16 @@ func VerifyAggregateSignature(curve CurveSystem, aggsig Point1, keys []Point2, m
return e1.Equals(e2)
}

// concurrentPair pairs pt with key, and sends the result down the channel.
func concurrentPair(curve CurveSystem, pt Point1, key Point2, c chan PointT) {
targetPoint, _ := pt.Pair(key)
c <- targetPoint
}

// concurrentMsgPair hashes the message, pairs it with key, and sends the result down the channel.
func concurrentMsgPair(curve CurveSystem, msg []byte, key Point2, c chan PointT) {
h := curve.HashToG1(msg)
targetPoint, _ := h.Pair(key)
c <- targetPoint
}

//Verify checks that a single message has been signed by a set of keys
//vulnerable against chosen key attack, if keys have not been authenticated
func (m MultiSig) Verify(curve CurveSystem) bool {
return VerifyMultiSignature(curve, m.sig, m.keys, m.msg)
}

// VerifyMultiSignature checks that the aggregate signature correctly proves that a single message has been signed by a set of keys,
// vulnerable against chosen key attack, if keys have not been authenticated
func VerifyMultiSignature(curve CurveSystem, aggsig Point1, keys []Point2, msg []byte) bool {
vs := AggregateG2(keys)
c := make(chan PointT)
go concurrentPair(curve, aggsig, curve.GetG2(), c)
go concurrentMsgPair(curve, msg, vs, c)
e1 := <-c
e2 := <-c
return e1.Equals(e2)
concurrentPair(curve, h, key, c)
}

func containsDuplicateMessage(msgs [][]byte) bool {
Expand Down
64 changes: 8 additions & 56 deletions bgls/bgls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,25 +50,25 @@ func TestAggregation(t *testing.T) {
sigs[i] = sig
}
aggSig := AggregateG1(sigs[:N])
assert.True(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N], msgs[:N], false),
assert.True(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N], msgs[:N]),
"Aggregate Point1 verification failed")
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N-1], msgs[:N], false),
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N-1], msgs[:N]),
"Aggregate Point1 verification succeeding without enough pubkeys")
skf, vkf, _ := KeyGen(curve)
pubkeys[N] = vkf
sigs[N] = Sign(curve, skf, msgs[0])
msgs[N] = msgs[0]
aggSig = AggregateG1(sigs)
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys, msgs, false),
"Aggregate Point1 succeeding with duplicate messages with allow duplicates being false")
assert.True(t, VerifyAggregateSignature(curve, aggSig, pubkeys, msgs, true),
"Aggregate Point1 failing with duplicate messages with allow duplicates")
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N], msgs[:N], false),
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys, msgs),
"Aggregate Signature succeeding with duplicate messages")
assert.True(t, VerifyAggregateKoskSignature(curve, aggSig, pubkeys, msgs),
"Aggregate Kosk signature failing with duplicate messages")
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N], msgs[:N]),
"Aggregate Point1 succeeding with invalid signature")
msgs[0] = msgs[1]
msgs[1] = msgs[N]
aggSig = AggregateG1(sigs[:N])
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N], msgs[:N], false),
assert.False(t, VerifyAggregateSignature(curve, aggSig, pubkeys[:N], msgs[:N]),
"Aggregate Point1 succeeded with messages 0 and 1 switched")

// TODO Add tests to make sure there is no mutation
Expand Down Expand Up @@ -159,54 +159,6 @@ func TestMarshal(t *testing.T) {
}
}

// This is commented out because I just changed the hash implementation, so consistency
// is supposed to be broken with past implementations.
// func TestKnownCases(t *testing.T) {
// curve := Altbn128
// N := 3
// msgs := make([][]byte, N)
// msg1 := []byte{65, 20, 86, 143, 250}
// msg2 := []byte{157, 76, 30, 64, 128}
// msg3 := []byte{202, 255, 227, 59, 238}
// sk1, _ := new(big.Int).SetString("7830752896741750908830464020410322281763657818307273013205711220156049734883", 10)
// sk2, _ := new(big.Int).SetString("10065703961787583059826108098259128135713944641698809475150397710106034167549", 10)
// sk3, _ := new(big.Int).SetString("17145080297596291172729378766677038070724014074212589728874454474449054012678", 10)
//
// pubkeys := make([]Point2, N)
// vk1, vk2, vk3 := LoadPublicKey(curve, sk1), LoadPublicKey(curve, sk2), LoadPublicKey(curve, sk3)
// msgs[0], msgs[1], msgs[2] = msg1, msg2, msg3
// pubkeys[0], pubkeys[1], pubkeys[2] = vk1, vk2, vk3
//
// sigGen1 := Sign(curve, sk1, msgs[0])
// sigGen2 := Sign(curve, sk2, msgs[1])
// sigGen3 := Sign(curve, sk3, msgs[2])
// sigVal1_1, _ := new(big.Int).SetString("21637350149051642305293442272499488026428127697128429631193536777535027009518", 10)
// sigVal1_2, _ := new(big.Int).SetString("149479762519169687769683150632580363857094522511606512652585818657412262489", 10)
// sigVal2_1, _ := new(big.Int).SetString("14834848655731874780751719195269704123719987185153910215596714529658047741046", 10)
// sigVal2_2, _ := new(big.Int).SetString("5847895190688397897156144807293187828750812390735163763226617490736304595451", 10)
// sigVal3_1, _ := new(big.Int).SetString("21239057713889019692075876723610689006006025737755828182426488764514117409847", 10)
// sigVal3_2, _ := new(big.Int).SetString("11967902298809667109716532536825395835657143208987520118971083760489593281874", 10)
// sigChk1, _ := curve.MakeG1Point(sigVal1_1, sigVal1_2)
// sigChk2, _ := curve.MakeG1Point(sigVal2_1, sigVal2_2)
// sigChk3, _ := curve.MakeG1Point(sigVal3_1, sigVal3_2)
//
// assert.False(t, (!sigChk1.Equals(sigGen1) || !sigChk2.Equals(sigGen2) || !sigChk3.Equals(sigGen3)),
// "Recreating message signatures from known test cases failed")
//
// sigs := make([]Point1, N)
// sigs[0], sigs[1], sigs[2] = sigGen1, sigGen2, sigGen3
//
// aggSig1, _ := new(big.Int).SetString("12682380538491839124790562586247816360937861029087546329767912056050859037239", 10)
// aggSig2, _ := new(big.Int).SetString("5755139208159515629159661524903000057840676877654799839167369795924360592246", 10)
// aggSigChk, _ := curve.MakeG1Point(aggSig1, aggSig2)
//
// aggSig := AggregateG1(sigs)
// assert.True(t, aggSigChk.Equals(aggSig),
// "Aggregate Point1 does not match the known test case.")
// assert.True(t, VerifyAggregateSignature(curve, aggSig, pubkeys, msgs, false),
// "Aggregate Point1 verification failed")
// }

func BenchmarkKeygen(b *testing.B) {
b.ResetTimer()
curve := Altbn128
Expand Down
48 changes: 48 additions & 0 deletions bgls/blsDistinctMessage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (C) 2018 Authors
// distributed under Apache 2.0 license

package bgls

import (
"math/big"

. "github.com/Project-Arda/bgls/curves"
)

// This implements the method of using Distinct Messages for aggregate signatures.
// This ensures that no two messages are used from separate pubkeys by prepending
// the public key before the message.

//Sign creates a signature on a message with a private key
func SignDistinctMsg(curve CurveSystem, sk *big.Int, m []byte) Point1 {
return SignDistinctMsgCustHash(curve, sk, m, curve.HashToG1)
}

// SignCustHash creates a signature on a message with a private key, using
// a supplied function to hash to g1.
func SignDistinctMsgCustHash(curve CurveSystem, sk *big.Int, m []byte, hash func([]byte) Point1) Point1 {
msg := append(LoadPublicKey(curve, sk).MarshalUncompressed(), m...)
h := hash(msg)
i := h.Mul(sk)
return i
}

// VerifyDistinctMsg checks that a single 'Distinct Message' signature is valid
func VerifyDistinctMsg(curve CurveSystem, pubKey Point2, m []byte, sig Point1) bool {
msg := append(pubKey.MarshalUncompressed(), m...)
return Verify(curve, pubKey, msg, sig)
}

func VerifyAggregateDistinctMsg(curve CurveSystem, aggsig Point1, keys []Point2, msgs [][]byte) bool {
if len(keys) != len(msgs) {
return false
}
prependedMsgs := make([][]byte, len(msgs))
for i := 0; i < len(msgs); i++ {
prependedMsgs[i] = append(keys[i].MarshalUncompressed(), msgs[i]...)
}
// Use true for allow duplicates even though duplicates aren't allowed
// This is because the prepending ensures that there are no duplicates,
// So setting this to true skips that check.
return verifyAggSig(curve, aggsig, keys, prependedMsgs, true)
}
Loading