Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

feat: BBS+ signer #2278

Merged
merged 1 commit into from
Oct 28, 2020
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
2 changes: 1 addition & 1 deletion cmd/aries-agent-mobile/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ require (
replace (
github.com/hyperledger/aries-framework-go => ../../
github.com/kilic/bls12-381 => github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e
)
2 changes: 2 additions & 0 deletions cmd/aries-agent-mobile/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,8 @@ github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4 h1:Sq/6
github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4/go.mod h1:9PdLyPiZIiW3UopXyRnPYyjUXSpiQNHRLu8fOsR3o8M=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc h1:312UsgPy3LxPl3dM+OrjQ6M2ymLcVTXIp+6wdDWkSY8=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e h1:IuSryDFXv17anJ2sux9qSEmIyaqKSWXnfVMv5CFCmDc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef h1:nZF/RNtWszq+WD8+p7blxWsWJjiTgdGQ1rv2IEffLj8=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
Expand Down
2 changes: 1 addition & 1 deletion cmd/aries-agent-rest/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ replace (
github.com/hyperledger/aries-framework-go => ../..
github.com/hyperledger/aries-framework-go/component/storage/leveldb => ../../component/storage/leveldb
github.com/kilic/bls12-381 => github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e
)

require (
Expand Down
2 changes: 2 additions & 0 deletions cmd/aries-agent-rest/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4/go.mod
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc h1:312UsgPy3LxPl3dM+OrjQ6M2ymLcVTXIp+6wdDWkSY8=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e h1:IuSryDFXv17anJ2sux9qSEmIyaqKSWXnfVMv5CFCmDc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef h1:nZF/RNtWszq+WD8+p7blxWsWJjiTgdGQ1rv2IEffLj8=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
Expand Down
2 changes: 1 addition & 1 deletion cmd/aries-js-worker/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ replace (
github.com/hyperledger/aries-framework-go => ../../
github.com/hyperledger/aries-framework-go/component/storage/jsindexeddb => ../../component/storage/jsindexeddb
github.com/kilic/bls12-381 => github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e
github.com/piprate/json-gold => github.com/trustbloc/json-gold v0.3.1-0.20200414173446-30d742ee949e
)
4 changes: 2 additions & 2 deletions cmd/aries-js-worker/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4 h1:Sq/68UWgBzKT+pLTUTkSf0jS2IUwwXLFlZmeh+nAzQM=
github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4/go.mod h1:9PdLyPiZIiW3UopXyRnPYyjUXSpiQNHRLu8fOsR3o8M=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc h1:312UsgPy3LxPl3dM+OrjQ6M2ymLcVTXIp+6wdDWkSY8=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e h1:IuSryDFXv17anJ2sux9qSEmIyaqKSWXnfVMv5CFCmDc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef h1:nZF/RNtWszq+WD8+p7blxWsWJjiTgdGQ1rv2IEffLj8=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/trustbloc/json-gold v0.3.1-0.20200414173446-30d742ee949e h1:i+hGa8C1MKGO71j3jIV7e2aKX72/DTrzLjq9R8kc6xk=
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ require (

replace (
github.com/kilic/bls12-381 => github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc
github.com/phoreproject/bls => github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e
github.com/piprate/json-gold => github.com/trustbloc/json-gold v0.3.1-0.20200414173446-30d742ee949e
golang.org/x/sys => golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4 h1:Sq/68UWgBzKT+pLTUTkSf0jS2IUwwXLFlZmeh+nAzQM=
github.com/teserakt-io/golang-ed25519 v0.0.0-20200315192543-8255be791ce4/go.mod h1:9PdLyPiZIiW3UopXyRnPYyjUXSpiQNHRLu8fOsR3o8M=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc h1:312UsgPy3LxPl3dM+OrjQ6M2ymLcVTXIp+6wdDWkSY8=
github.com/trustbloc/bls v0.0.0-20201008085849-81064514c3cc/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e h1:IuSryDFXv17anJ2sux9qSEmIyaqKSWXnfVMv5CFCmDc=
github.com/trustbloc/bls v0.0.0-20201023141329-a1e218beb89e/go.mod h1:xHJKf2TLXUA39Dhv8k5QmQOxLsbrb1KeTS/3ERfLeqc=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef h1:nZF/RNtWszq+WD8+p7blxWsWJjiTgdGQ1rv2IEffLj8=
github.com/trustbloc/bls12-381 v0.0.0-20201008080608-ba2e87ef05ef/go.mod h1:XXfR6YFCRSrkEXbNlIyDsgXVNJWVUV30m/ebkVy9n6s=
github.com/trustbloc/json-gold v0.3.1-0.20200414173446-30d742ee949e h1:i+hGa8C1MKGO71j3jIV7e2aKX72/DTrzLjq9R8kc6xk=
Expand Down
9 changes: 8 additions & 1 deletion pkg/doc/bbs/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,15 @@ package bbs
// BBS defines BBS+ signature scheme (https://eprint.iacr.org/2016/663.pdf, section 4.3).
type BBS interface {

// Verify will verify each signature against a public key
// Verify will verify an aggregated signature of one or more messages against a public key
// returns:
// error in case of errors or nil if signature verification was successful
Verify(messages [][]byte, signature, pubKey []byte) error

// Sign will sign create signature of each message and aggregate it into a single signature using
// provided private key in binary form.
// returns:
// signature in []byte
// error in case of errors
Sign(messages [][]byte, privKey []byte) ([]byte, error)
}
95 changes: 76 additions & 19 deletions pkg/doc/bbs/bbs12381g2pub/bbs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ SPDX-License-Identifier: Apache-2.0
package bbs12381g2pub

import (
"crypto/rand"
"encoding/binary"
"errors"
"fmt"
"hash"

bls12381 "github.com/kilic/bls12-381"
"github.com/phoreproject/bls"
"github.com/phoreproject/bls/g2pubs"
"golang.org/x/crypto/blake2b"
)

Expand Down Expand Up @@ -44,16 +46,19 @@ const (

// Number of bytes in scalar compressed form.
frCompressedSize = 32

// Number of bytes in scalar uncompressed form.
frUncompressedSize = 48
)

// Verify makes BLS BBS12-381 signature verification.
func (b BBSG2Pub) Verify(messages [][]byte, sigBytes, pubKeyBytes []byte) error {
func (bbs *BBSG2Pub) Verify(messages [][]byte, sigBytes, pubKeyBytes []byte) error {
signature, err := ParseSignature(sigBytes)
if err != nil {
return fmt.Errorf("parse signature: %w", err)
}

publicKey, err := ParsePublicKey(pubKeyBytes)
publicKey, err := UnmarshalPublicKey(pubKeyBytes)
if err != nil {
return fmt.Errorf("parse public key: %w", err)
}
Expand All @@ -62,7 +67,7 @@ func (b BBSG2Pub) Verify(messages [][]byte, sigBytes, pubKeyBytes []byte) error
for i := range messages {
messagesFr[i], err = ParseSignatureMessage(messages[i])
if err != nil {
return fmt.Errorf("parse signature message: %w", err)
return fmt.Errorf("parse signature message %d: %w", i+1, err)
}
}

Expand All @@ -83,7 +88,63 @@ func (b BBSG2Pub) Verify(messages [][]byte, sigBytes, pubKeyBytes []byte) error
return errors.New("BLS12-381: invalid signature")
}

func getB(s *bls.FR, messages []*SignatureMessage, key *PublicKey) (*bls.G1Affine, error) {
// Sign signs the one or more messages using private key in compressed form.
func (bbs *BBSG2Pub) Sign(messages [][]byte, privKeyBytes []byte) ([]byte, error) {
privKey, err := UnmarshalPrivateKey(privKeyBytes)
if err != nil {
return nil, fmt.Errorf("unmarshal private key: %w", err)
}

if len(messages) == 0 {
return nil, errors.New("messages are not defined")
}

return bbs.SignWithKey(messages, privKey)
}

// SignWithKey signs the one or more messages using BBS+ key pair.
func (bbs *BBSG2Pub) SignWithKey(messages [][]byte, privKey *PrivateKey) ([]byte, error) {
var err error

pubKey := privKey.PublicKey()

messagesFr := make([]*SignatureMessage, len(messages))
for i := range messages {
messagesFr[i], err = ParseSignatureMessage(messages[i])
if err != nil {
return nil, fmt.Errorf("parse signature message %d: %w", i+1, err)
}
}

e, err := bls.RandFR(rand.Reader)
if err != nil {
return nil, fmt.Errorf("create signature.E: %w", err)
}

s, err := bls.RandFR(rand.Reader)
if err != nil {
return nil, fmt.Errorf("create signature.S: %w", err)
}

b, err := computeB(s, messagesFr, pubKey)
if err != nil {
return nil, fmt.Errorf("compute B point: %w", err)
}

exp := privKey.GetFRElement().Copy()
exp.AddAssign(e)
sig := b.MulFR(exp.Inverse().ToRepr())

signature := &Signature{
Signature: g2pubs.NewSignatureFromG1(sig.ToAffine()),
E: e,
S: s,
}

return signature.ToBytes()
}

func computeB(s *bls.FR, messages []*SignatureMessage, key *PublicKey) (*bls.G1Projective, error) {
const basesOffset = 2

messagesCount := len(messages)
Expand Down Expand Up @@ -139,9 +200,18 @@ func getB(s *bls.FR, messages []*SignatureMessage, key *PublicKey) (*bls.G1Affin
res = res.Add(g)
}

res.NegAssign()
return res, nil
}

func getB(s *bls.FR, messages []*SignatureMessage, key *PublicKey) (*bls.G1Affine, error) {
b, err := computeB(s, messages, key)
if err != nil {
return nil, err
}

b.NegAssign()

return res.ToAffine(), nil
return b.ToAffine(), nil
}

func calcData(key *PublicKey, messagesCount int) []byte {
Expand Down Expand Up @@ -215,16 +285,3 @@ func compareTwoPairings(p1 *bls.G1Projective, q1 *bls.G2Projective, p2 *bls.G1Pr

return engine.Check()
}

func parseFr(data []byte) (*bls.FR, error) {
var arr [32]byte

copy(arr[:], data)

fr := bls.FRReprToFR(bls.FRReprFromBytes(arr))
if fr == nil {
return nil, errors.New("invalid FR")
}

return fr, nil
}
53 changes: 53 additions & 0 deletions pkg/doc/bbs/bbs12381g2pub/bbs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,56 @@ func TestBlsG2Pub_Verify(t *testing.T) {
require.Contains(t, err.Error(), "parse signature: deserialize G1 compressed signature")
})
}

func TestBBSG2Pub_SignWithKeyPair(t *testing.T) {
pubKey, privKey, err := generateKeyPairRandom()
require.NoError(t, err)

bls := bbs12381g2pub.New()

messagesBytes := [][]byte{[]byte("message1"), []byte("message2")}

signatureBytes, err := bls.SignWithKey(messagesBytes, privKey)
require.NoError(t, err)
require.NotEmpty(t, signatureBytes)
require.Len(t, signatureBytes, 112)

pubKeyBytes, err := pubKey.Marshal()
require.NoError(t, err)

require.NoError(t, bls.Verify(messagesBytes, signatureBytes, pubKeyBytes))
}

func TestBBSG2Pub_Sign(t *testing.T) {
pubKey, privKey, err := generateKeyPairRandom()
require.NoError(t, err)

bls := bbs12381g2pub.New()

messagesBytes := [][]byte{[]byte("message1"), []byte("message2")}

privKeyBytes, err := privKey.Marshal()
require.NoError(t, err)

signatureBytes, err := bls.Sign(messagesBytes, privKeyBytes)
require.NoError(t, err)
require.NotEmpty(t, signatureBytes)
require.Len(t, signatureBytes, 112)

pubKeyBytes, err := pubKey.Marshal()
require.NoError(t, err)

require.NoError(t, bls.Verify(messagesBytes, signatureBytes, pubKeyBytes))

// invalid private key bytes
signatureBytes, err = bls.Sign(messagesBytes, []byte("invalid"))
require.Error(t, err)
require.EqualError(t, err, "unmarshal private key: invalid size of private key")
require.Nil(t, signatureBytes)

// at least one message must be passed
signatureBytes, err = bls.Sign([][]byte{}, privKeyBytes)
require.Error(t, err)
require.EqualError(t, err, "messages are not defined")
require.Nil(t, signatureBytes)
}
72 changes: 72 additions & 0 deletions pkg/doc/bbs/bbs12381g2pub/fr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package bbs12381g2pub

import (
"errors"

"github.com/phoreproject/bls"
"golang.org/x/crypto/blake2b"
)

func frFromOKM(message []byte) (*bls.FR, error) {
const (
eightBytes = 8
okmMiddle = 24
)

// We pass a null key so error is impossible here.
h, _ := blake2b.New384(nil) //nolint:errcheck

// blake2b.digest() does not return an error.
_, _ = h.Write(message) //nolint:errcheck
okm := h.Sum(nil)
emptyEightBytes := make([]byte, eightBytes)

elm, err := parseFr(append(emptyEightBytes, okm[:okmMiddle]...))
if err != nil {
return nil, err
}

elm.MulAssign(f2192())

fr, err := parseFr(append(emptyEightBytes, okm[okmMiddle:]...))
if err != nil {
return nil, err
}

elm.AddAssign(fr)

return elm, nil
}

func parseFr(data []byte) (*bls.FR, error) {
var arr [frCompressedSize]byte

copy(arr[:], data)

fr := bls.FRReprToFR(bls.FRReprFromBytes(arr))
if fr == nil {
return nil, errors.New("invalid FR")
}

return fr, nil
}

func frToBytes(fr *bls.FR) []byte {
bytes := fr.ToRepr().Bytes()
return bytes[:]
}

func f2192() *bls.FR {
return bls.NewFr(&bls.FRRepr{
0x59476ebc41b4528f,
0xc5a30cb243fcc152,
0x2b34e63940ccbd72,
0x1e179025ca247088,
})
}
Loading