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  }