github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/bbs/bbs_signer_key_manager.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  	"crypto/rand"
    11  	"errors"
    12  	"fmt"
    13  
    14  	"github.com/google/tink/go/keyset"
    15  	commonpb "github.com/google/tink/go/proto/common_go_proto"
    16  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    17  	"github.com/google/tink/go/subtle"
    18  	"github.com/trustbloc/bbs-signature-go/bbs12381g2pub"
    19  	"google.golang.org/protobuf/proto"
    20  
    21  	bbssubtle "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/bbs/subtle"
    22  	bbspb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/bbs_go_proto"
    23  )
    24  
    25  const (
    26  	bbsSignerKeyVersion = 0
    27  	bbsSignerKeyTypeURL = "type.hyperledger.org/hyperledger.aries.crypto.tink.BBSPrivateKey"
    28  )
    29  
    30  // common errors.
    31  var (
    32  	errInvalidBBSSignerKey       = errors.New("bbs_signer_key_manager: invalid key")
    33  	errInvalidBBSSignerKeyFormat = errors.New("bbs_signer_key_manager: invalid key format")
    34  )
    35  
    36  // bbsSignerKeyManager is an implementation of KeyManager interface for BBS signatures/proofs.
    37  // It generates new BBSPrivateKeys and produces new instances of BBSSign subtle.
    38  type bbsSignerKeyManager struct{}
    39  
    40  // newBBSSignerKeyManager creates a new bbsSignerKeyManager.
    41  func newBBSSignerKeyManager() *bbsSignerKeyManager {
    42  	return new(bbsSignerKeyManager)
    43  }
    44  
    45  // Primitive creates an BBS Signer subtle for the given serialized BBSPrivateKey proto.
    46  func (km *bbsSignerKeyManager) Primitive(serializedKey []byte) (interface{}, error) {
    47  	if len(serializedKey) == 0 {
    48  		return nil, errInvalidBBSSignerKey
    49  	}
    50  
    51  	key := new(bbspb.BBSPrivateKey)
    52  
    53  	err := proto.Unmarshal(serializedKey, key)
    54  	if err != nil {
    55  		return nil, fmt.Errorf(errInvalidBBSSignerKey.Error()+": invalid proto: %w", err)
    56  	}
    57  
    58  	err = km.validateKey(key)
    59  	if err != nil {
    60  		return nil, fmt.Errorf(errInvalidBBSSignerKey.Error()+": %w", err)
    61  	}
    62  
    63  	return bbssubtle.NewBLS12381G2Signer(key.KeyValue), nil
    64  }
    65  
    66  // NewKey creates a new key according to the specification of BBSPrivateKey format.
    67  func (km *bbsSignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
    68  	if len(serializedKeyFormat) == 0 {
    69  		return nil, errInvalidBBSSignerKeyFormat
    70  	}
    71  
    72  	keyFormat := new(bbspb.BBSKeyFormat)
    73  
    74  	err := proto.Unmarshal(serializedKeyFormat, keyFormat)
    75  	if err != nil {
    76  		return nil, fmt.Errorf(errInvalidBBSSignerKeyFormat.Error()+": invalid proto: %w", err)
    77  	}
    78  
    79  	err = validateKeyFormat(keyFormat)
    80  	if err != nil {
    81  		return nil, fmt.Errorf(errInvalidBBSSignerKeyFormat.Error()+": %w", err)
    82  	}
    83  
    84  	var (
    85  		pubKey  *bbs12381g2pub.PublicKey
    86  		privKey *bbs12381g2pub.PrivateKey
    87  	)
    88  
    89  	// Since bbs+ in aries-framework-go only supports BLS12-381 curve on G2, we create keys of this curve and
    90  	// group only. BBS+ keys with other curves/group field can be added later if needed.
    91  	if keyFormat.Params.Group == bbspb.GroupField_G2 && keyFormat.Params.Curve == bbspb.BBSCurveType_BLS12_381 {
    92  		seed := make([]byte, 32)
    93  
    94  		_, err = rand.Read(seed)
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  
    99  		hFunc := subtle.GetHashFunc(keyFormat.Params.HashType.String())
   100  
   101  		pubKey, privKey, err = bbs12381g2pub.GenerateKeyPair(hFunc, seed)
   102  		if err != nil {
   103  			return nil, err
   104  		}
   105  	} else {
   106  		return nil, errInvalidBBSSignerKeyFormat
   107  	}
   108  
   109  	pubKeyBytes, err := pubKey.Marshal()
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	privKeyBytes, err := privKey.Marshal()
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  
   119  	return &bbspb.BBSPrivateKey{
   120  		Version:  bbsSignerKeyVersion,
   121  		KeyValue: privKeyBytes,
   122  		PublicKey: &bbspb.BBSPublicKey{
   123  			Version:  bbsSignerKeyVersion,
   124  			Params:   keyFormat.Params,
   125  			KeyValue: pubKeyBytes,
   126  		},
   127  	}, nil
   128  }
   129  
   130  // NewKeyData creates a new KeyData according to the specification of ECDHESPrivateKey Format.
   131  // It should be used solely by the key management API.
   132  func (km *bbsSignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
   133  	key, err := km.NewKey(serializedKeyFormat)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  
   138  	serializedKey, err := proto.Marshal(key)
   139  	if err != nil {
   140  		return nil, fmt.Errorf("bbs_signer_key_manager: Proto.Marshal failed: %w", err)
   141  	}
   142  
   143  	return &tinkpb.KeyData{
   144  		TypeUrl:         bbsSignerKeyTypeURL,
   145  		Value:           serializedKey,
   146  		KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
   147  	}, nil
   148  }
   149  
   150  // PublicKeyData returns the enclosed public key data of serializedPrivKey.
   151  func (km *bbsSignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) {
   152  	privKey := new(bbspb.BBSPrivateKey)
   153  
   154  	err := proto.Unmarshal(serializedPrivKey, privKey)
   155  	if err != nil {
   156  		return nil, errInvalidBBSSignerKey
   157  	}
   158  
   159  	serializedPubKey, err := proto.Marshal(privKey.PublicKey)
   160  	if err != nil {
   161  		return nil, errInvalidBBSSignerKey
   162  	}
   163  
   164  	return &tinkpb.KeyData{
   165  		TypeUrl:         bbsVerifierKeyTypeURL,
   166  		Value:           serializedPubKey,
   167  		KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
   168  	}, nil
   169  }
   170  
   171  // DoesSupport indicates if this key manager supports the given key type.
   172  func (km *bbsSignerKeyManager) DoesSupport(typeURL string) bool {
   173  	return typeURL == bbsSignerKeyTypeURL
   174  }
   175  
   176  // TypeURL returns the key type of keys managed by this key manager.
   177  func (km *bbsSignerKeyManager) TypeURL() string {
   178  	return bbsSignerKeyTypeURL
   179  }
   180  
   181  // validateKey validates the given ECDHPrivateKey and returns the KW curve.
   182  func (km *bbsSignerKeyManager) validateKey(key *bbspb.BBSPrivateKey) error {
   183  	err := keyset.ValidateKeyVersion(key.Version, bbsSignerKeyVersion)
   184  	if err != nil {
   185  		return fmt.Errorf("bbs_signer_key_manager: invalid key: %w", err)
   186  	}
   187  
   188  	return validateKeyParams(key.PublicKey.Params)
   189  }
   190  
   191  // validateKeyFormat validates the given BBS curve and Group field.
   192  func validateKeyFormat(format *bbspb.BBSKeyFormat) error {
   193  	return validateKeyParams(format.Params)
   194  }
   195  
   196  func validateKeyParams(params *bbspb.BBSParams) error {
   197  	switch params.Curve {
   198  	case bbspb.BBSCurveType_BLS12_381:
   199  	default:
   200  		return fmt.Errorf("bad curve '%s'", params.Curve)
   201  	}
   202  
   203  	switch params.Group {
   204  	case bbspb.GroupField_G1, bbspb.GroupField_G2:
   205  	default:
   206  		return fmt.Errorf("bad group field '%s'", params.Group)
   207  	}
   208  
   209  	switch params.HashType {
   210  	case commonpb.HashType_SHA256, commonpb.HashType_SHA384, commonpb.HashType_SHA512:
   211  	default:
   212  		return fmt.Errorf("unsupported hash type '%s'", params.HashType)
   213  	}
   214  
   215  	return nil
   216  }