github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/bbs/bbs_verifier_factory.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package bbs 8 9 import ( 10 "errors" 11 "fmt" 12 13 "github.com/google/tink/go/core/cryptofmt" 14 "github.com/google/tink/go/core/primitiveset" 15 "github.com/google/tink/go/core/registry" 16 "github.com/google/tink/go/keyset" 17 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 18 19 bbsapi "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/bbs/api" 20 ) 21 22 // NewVerifier returns a Verifier primitive from the given keyset handle. 23 func NewVerifier(h *keyset.Handle) (bbsapi.Verifier, error) { 24 return NewVerifierWithKeyManager(h, nil) 25 } 26 27 // NewVerifierWithKeyManager returns a Verifier primitive from the given keyset handle and custom key manager. 28 func NewVerifierWithKeyManager(h *keyset.Handle, km registry.KeyManager) (bbsapi.Verifier, error) { 29 ps, err := h.PrimitivesWithKeyManager(km) 30 if err != nil { 31 return nil, fmt.Errorf("bbs_verifier_factory: cannot obtain primitive set: %w", err) 32 } 33 34 return newWrappedVerifier(ps) 35 } 36 37 var ( 38 errInvalidSignature = errors.New("bbs_verifier_factory: invalid signature") 39 errInvalidSignatureProof = errors.New("bbs_verifier_factory: invalid signature proof") 40 errInvalidPrimitive = errors.New("bbs_verifier_factory: not a Verifier primitive") 41 ) 42 43 // wrappedVerifier is a BBS Verifier implementation that uses the underlying primitive set for BBS signature 44 // verification and proof creation/verification. 45 type wrappedVerifier struct { 46 ps *primitiveset.PrimitiveSet 47 } 48 49 func newWrappedVerifier(ps *primitiveset.PrimitiveSet) (bbsapi.Verifier, error) { 50 if _, ok := (ps.Primary.Primitive).(bbsapi.Verifier); !ok { 51 return nil, errInvalidPrimitive 52 } 53 54 for _, primitives := range ps.Entries { 55 for _, p := range primitives { 56 if _, ok := (p.Primitive).(bbsapi.Verifier); !ok { 57 return nil, errInvalidPrimitive 58 } 59 } 60 } 61 62 ret := new(wrappedVerifier) 63 ret.ps = ps 64 65 return ret, nil 66 } 67 68 func (wv *wrappedVerifier) fetchNonRawKeyEntries(signature []byte) ([]byte, []byte, error) { 69 prefixSize := cryptofmt.NonRawPrefixSize 70 if len(signature) < prefixSize { 71 return nil, nil, errInvalidSignature 72 } 73 74 prefix := signature[:prefixSize] 75 signatureNoPrefix := signature[prefixSize:] 76 77 return signatureNoPrefix, prefix, nil 78 } 79 80 func buildPrefixedMsgToSign(messages [][]byte, entry *primitiveset.Entry) [][]byte { 81 if entry.PrefixType == tinkpb.OutputPrefixType_LEGACY { 82 return append(messages, []byte{cryptofmt.LegacyStartByte}) 83 } 84 85 return messages 86 } 87 88 func toBBSVerifier(v interface{}) (bbsapi.Verifier, error) { 89 verifier, ok := v.(bbsapi.Verifier) 90 if !ok { 91 return nil, errInvalidPrimitive 92 } 93 94 return verifier, nil 95 } 96 97 // Verify checks whether the given signature is a valid signature of the given messages. 98 func (wv *wrappedVerifier) Verify(messages [][]byte, signature []byte) error { 99 signatureNoPrefix, prefix, err := wv.fetchNonRawKeyEntries(signature) 100 if err != nil { 101 return err 102 } 103 104 // try non-raw keys 105 entries, err := wv.ps.EntriesForPrefix(string(prefix)) 106 if err == nil { 107 for i := 0; i < len(entries); i++ { 108 var verifier bbsapi.Verifier 109 110 verifier, err = toBBSVerifier(entries[i].Primitive) 111 if err != nil { 112 return err 113 } 114 115 dataToSign := buildPrefixedMsgToSign(messages, entries[i]) 116 if err = verifier.Verify(dataToSign, signatureNoPrefix); err == nil { 117 return nil 118 } 119 } 120 } 121 122 // try raw keys 123 entries, err = wv.ps.RawEntries() 124 if err == nil { 125 for i := 0; i < len(entries); i++ { 126 var verifier bbsapi.Verifier 127 128 verifier, err = toBBSVerifier(entries[i].Primitive) 129 if err != nil { 130 return err 131 } 132 133 if err = verifier.Verify(messages, signature); err == nil { 134 return nil 135 } 136 } 137 } 138 139 return errInvalidSignature 140 } 141 142 // VerifyProof will verify a BBS+ signature proof (generated by a Verifier's DeriveProof() call) of the given messages. 143 func (wv *wrappedVerifier) VerifyProof(messages [][]byte, proof, nonce []byte) error { 144 proofNoPrefix, prefix, err := wv.fetchNonRawKeyEntries(proof) 145 if err != nil { 146 return err 147 } 148 149 // try non-raw keys 150 entries, err := wv.ps.EntriesForPrefix(string(prefix)) 151 if err == nil { 152 for i := 0; i < len(entries); i++ { 153 var verifier bbsapi.Verifier 154 155 verifier, err = toBBSVerifier(entries[i].Primitive) 156 if err != nil { 157 return err 158 } 159 160 msgsToSign := buildPrefixedMsgToSign(messages, entries[i]) 161 if err = verifier.VerifyProof(msgsToSign, proofNoPrefix, nonce); err == nil { 162 return nil 163 } 164 } 165 } 166 167 // try raw keys 168 entries, err = wv.ps.RawEntries() 169 if err == nil { 170 for i := 0; i < len(entries); i++ { 171 var verifier bbsapi.Verifier 172 173 verifier, err = toBBSVerifier(entries[i].Primitive) 174 if err != nil { 175 return err 176 } 177 178 if err = verifier.VerifyProof(messages, proof, nonce); err == nil { 179 return nil 180 } 181 } 182 } 183 184 return errInvalidSignatureProof 185 } 186 187 // DeriveProof will create a BBS+ signature proof for a list of revealed messages using BBS signature (generated by a 188 // Signer's Sign() call). 189 func (wv *wrappedVerifier) DeriveProof(messages [][]byte, signature, nonce []byte, 190 revealedIndexes []int) ([]byte, error) { 191 signatureNoPrefix, prefix, err := wv.fetchNonRawKeyEntries(signature) 192 if err != nil { 193 return nil, err 194 } 195 196 // try non-raw keys 197 entries, err := wv.ps.EntriesForPrefix(string(prefix)) 198 if err == nil { 199 for i := 0; i < len(entries); i++ { 200 var ( 201 verifier bbsapi.Verifier 202 proof []byte 203 ) 204 205 verifier, err = toBBSVerifier(entries[i].Primitive) 206 if err != nil { 207 return nil, err 208 } 209 210 msgsToSign := buildPrefixedMsgToSign(messages, entries[i]) 211 if proof, err = verifier.DeriveProof(msgsToSign, signatureNoPrefix, nonce, revealedIndexes); err == nil { 212 ret := make([]byte, 0, len(entries[i].Prefix)+len(proof)) 213 ret = append(ret, entries[i].Prefix...) 214 ret = append(ret, proof...) 215 216 return ret, nil 217 } 218 } 219 } 220 221 // try raw keys 222 entries, err = wv.ps.RawEntries() 223 if err == nil { 224 for i := 0; i < len(entries); i++ { 225 var ( 226 verifier bbsapi.Verifier 227 proof []byte 228 ) 229 230 verifier, err = toBBSVerifier(entries[i].Primitive) 231 if err != nil { 232 return nil, err 233 } 234 235 if proof, err = verifier.DeriveProof(messages, signature, nonce, revealedIndexes); err == nil { 236 ret := make([]byte, 0, len(entries[i].Prefix)+len(proof)) 237 ret = append(ret, entries[i].Prefix...) 238 ret = append(ret, proof...) 239 240 return ret, nil 241 } 242 } 243 } 244 245 return nil, errInvalidSignatureProof 246 }