diff --git a/pkg/crypto/tinkcrypto/primitive/bbs/bbs.go b/pkg/crypto/tinkcrypto/primitive/bbs/bbs.go index 76e895a98f..9e4f0f3e23 100644 --- a/pkg/crypto/tinkcrypto/primitive/bbs/bbs.go +++ b/pkg/crypto/tinkcrypto/primitive/bbs/bbs.go @@ -12,7 +12,81 @@ SPDX-License-Identifier: Apache-2.0 // * Signer for signing a list of messages with a private key // // * Verifier for verifying a signature against a list of messages, deriving a proof from a signature for a given -// message and verifying such derived proof. +// set of sub messages and verifying such derived proof. +// +// +// Example: +// +// package main +// +// import ( +// "bytes" +// +// "github.com/google/tink/go/keyset" +// +// "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/bbs" +// ) +// +// func main() { +// // create signer keyset handle +// kh, err := keyset.NewHandle(bbs.BLS12381G2KeyTemplate()) +// if err != nil { +// //handle error +// } +// +// // extract signer public keyset handle and key to signature proof verification and proof derivation/verification +// verKH, err := kh.Public() +// if err != nil { +// //handle error +// } +// +// // finally get the BBS+ signing primitive from the private key handle created above +// s:= bbs.NewSigner(kh) +// +// // create a message to be signed +// messages := [][]byte{[]byte("message 1"), []byte("message 2"), []byte("message 3"), []byte("message 4")} +// +// // and now sign using s +// sig, err = s.Sign(messages) +// if err != nil { +// // handle error +// } +// +// // to verify, get the BBS+ verification primitive from the public key handle created earlier above +// v := bbs.NewVerifier(verKH) +// +// // and verify signature +// pt, err := v.Verify(messages, sig) +// if err != nil { +// // handle error +// } +// +// // to derive a proof from the bbs signature, create the indices of the messages to be revealed by the proof +// revealedIndexes := []int{0, 2} +// +// // and a nonce +// nonce := make([]byte, 10) +// +// _, err = rand.Read(nonce) +// if err != nil { +// // handle error +// } +// +// // then derive a proof for messages at index 0 and 2 as follows +// proof, err := verifier.DeriveProof(messages, sig, nonce, revealedIndexes) +// if err != nil { +// // handle error +// } +// +// // create a copy of the revealed messages to the party that should only access messages at index 0 and 2 +// revealedMsgs := [][]byte{messages[0], messages[2]} +// +// // finally to verify the proof's authenticity for revealedMsgs, do the following +// err = verifier.VerifyProof(revealedMsgs, proof, nonce) +// if err != nil { +// // handle error +// } +// } package bbs import ( diff --git a/pkg/crypto/tinkcrypto/primitive/bbs/bbs_key_template.go b/pkg/crypto/tinkcrypto/primitive/bbs/bbs_key_template.go new file mode 100644 index 0000000000..98cbbb1950 --- /dev/null +++ b/pkg/crypto/tinkcrypto/primitive/bbs/bbs_key_template.go @@ -0,0 +1,42 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package bbs + +import ( + "github.com/golang/protobuf/proto" + commonpb "github.com/google/tink/go/proto/common_go_proto" + tinkpb "github.com/google/tink/go/proto/tink_go_proto" + + bbspb "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/proto/bbs_go_proto" +) + +// BLS12381G2KeyTemplate creates a Tink key template for BBS+ on BLS12-381 curve with G2 group. +func BLS12381G2KeyTemplate() *tinkpb.KeyTemplate { + return createKeyTemplate(bbspb.BBSCurveType_BLS12_381, bbspb.GroupField_G2, commonpb.HashType_SHA256) +} + +// createKeyTemplate for BBS+ keys. +func createKeyTemplate(curve bbspb.BBSCurveType, group bbspb.GroupField, hash commonpb.HashType) *tinkpb.KeyTemplate { + format := &bbspb.BBSKeyFormat{ + Params: &bbspb.BBSParams{ + HashType: hash, + Curve: curve, + Group: group, + }, + } + + serializedFormat, err := proto.Marshal(format) + if err != nil { + panic("failed to marshal BBSKeyFormat proto") + } + + return &tinkpb.KeyTemplate{ + TypeUrl: bbsSignerKeyTypeURL, + Value: serializedFormat, + OutputPrefixType: tinkpb.OutputPrefixType_RAW, + } +} diff --git a/pkg/crypto/tinkcrypto/primitive/bbs/bbs_key_template_test.go b/pkg/crypto/tinkcrypto/primitive/bbs/bbs_key_template_test.go new file mode 100644 index 0000000000..a149e67850 --- /dev/null +++ b/pkg/crypto/tinkcrypto/primitive/bbs/bbs_key_template_test.go @@ -0,0 +1,54 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package bbs + +import ( + "crypto/rand" + "testing" + + "github.com/google/tink/go/keyset" + "github.com/stretchr/testify/require" +) + +func TestBBSKeyTemplateSuccess(t *testing.T) { + kt := BLS12381G2KeyTemplate() + + kh, err := keyset.NewHandle(kt) + require.NoError(t, err) + + pubKH, err := kh.Public() + require.NoError(t, err) + + // now test the BBS primitives with these keyset handles + signer, err := NewSigner(kh) + require.NoError(t, err) + + messages := [][]byte{[]byte("msg abc"), []byte("msg def"), []byte("msg ghi")} + + sig, err := signer.Sign(messages) + require.NoError(t, err) + + verifier, err := NewVerifier(pubKH) + require.NoError(t, err) + + err = verifier.Verify(messages, sig) + require.NoError(t, err) + + revealedIndexes := []int{1, 2} + nonce := make([]byte, 10) + + _, err = rand.Read(nonce) + require.NoError(t, err) + + proof, err := verifier.DeriveProof(messages, sig, nonce, revealedIndexes) + require.NoError(t, err) + + revealedMsgs := [][]byte{messages[1], messages[2]} + + err = verifier.VerifyProof(revealedMsgs, proof, nonce) + require.NoError(t, err) +} diff --git a/pkg/crypto/tinkcrypto/primitive/bbs/bbs_signer_key_manager.go b/pkg/crypto/tinkcrypto/primitive/bbs/bbs_signer_key_manager.go index a11ba536ee..1c77ce26ee 100644 --- a/pkg/crypto/tinkcrypto/primitive/bbs/bbs_signer_key_manager.go +++ b/pkg/crypto/tinkcrypto/primitive/bbs/bbs_signer_key_manager.go @@ -121,6 +121,7 @@ func (km *bbsSignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message KeyValue: privKeyBytes, PublicKey: &bbspb.BBSPublicKey{ Version: bbsSignerKeyVersion, + Params: keyFormat.Params, KeyValue: pubKeyBytes, }, }, nil