github.com/trustbloc/kms-go@v1.1.2/kms/localkms/pubkey_export_import_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package localkms
     8  
     9  import (
    10  	"bytes"
    11  	"testing"
    12  
    13  	"github.com/google/tink/go/aead"
    14  	"github.com/google/tink/go/hybrid"
    15  	"github.com/google/tink/go/keyset"
    16  	commonpb "github.com/google/tink/go/proto/common_go_proto"
    17  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    18  	"github.com/google/tink/go/signature"
    19  	"github.com/stretchr/testify/require"
    20  
    21  	"github.com/trustbloc/kms-go/spi/kms"
    22  
    23  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/bbs"
    24  )
    25  
    26  func TestPubKeyExportAndRead(t *testing.T) {
    27  	p256DERTemplate, err := getKeyTemplate(kms.ECDSAP256TypeDER)
    28  	require.NoError(t, err)
    29  
    30  	p384DERTemplate, err := getKeyTemplate(kms.ECDSAP384TypeDER)
    31  	require.NoError(t, err)
    32  
    33  	p521DERTemplate, err := getKeyTemplate(kms.ECDSAP521TypeDER)
    34  	require.NoError(t, err)
    35  
    36  	flagTests := []struct {
    37  		tcName      string
    38  		keyType     kms.KeyType
    39  		keyTemplate *tinkpb.KeyTemplate
    40  		doSign      bool
    41  	}{
    42  		{
    43  			tcName:      "export then read ECDSAP256DER public key",
    44  			keyType:     kms.ECDSAP256TypeDER,
    45  			keyTemplate: p256DERTemplate,
    46  			doSign:      true,
    47  		},
    48  		{
    49  			tcName:      "export then read ECDSAP384DER public key",
    50  			keyType:     kms.ECDSAP384TypeDER,
    51  			keyTemplate: p384DERTemplate,
    52  			doSign:      true,
    53  		},
    54  		{
    55  			tcName:      "export then read ECDSAP521DER public key",
    56  			keyType:     kms.ECDSAP521TypeDER,
    57  			keyTemplate: p521DERTemplate,
    58  			doSign:      true,
    59  		},
    60  		{
    61  			tcName:      "export then read ECDSAP256IEEEP1363 public key",
    62  			keyType:     kms.ECDSAP256TypeIEEEP1363,
    63  			keyTemplate: createECDSAIEEE1363KeyTemplate(commonpb.HashType_SHA256, commonpb.EllipticCurveType_NIST_P256),
    64  			doSign:      true,
    65  		},
    66  		{
    67  			tcName:      "export then read ECDSAP384IEEEP1363 public key",
    68  			keyType:     kms.ECDSAP384TypeIEEEP1363,
    69  			keyTemplate: createECDSAIEEE1363KeyTemplate(commonpb.HashType_SHA384, commonpb.EllipticCurveType_NIST_P384),
    70  			doSign:      true,
    71  		},
    72  		{
    73  			tcName:      "export then read ECDSAP521IEEEP1363 public key",
    74  			keyType:     kms.ECDSAP521TypeIEEEP1363,
    75  			keyTemplate: createECDSAIEEE1363KeyTemplate(commonpb.HashType_SHA512, commonpb.EllipticCurveType_NIST_P521),
    76  			doSign:      true,
    77  		},
    78  		{
    79  			tcName:      "export then read ED25519 public key",
    80  			keyType:     kms.ED25519Type,
    81  			keyTemplate: signature.ED25519KeyWithoutPrefixTemplate(),
    82  			doSign:      true,
    83  		},
    84  		{
    85  			tcName:      "export then read BBS+ BLS12381G2 public key",
    86  			keyType:     kms.BLS12381G2Type,
    87  			keyTemplate: bbs.BLS12381G2KeyTemplate(),
    88  			doSign:      true,
    89  		},
    90  	}
    91  
    92  	for _, tc := range flagTests {
    93  		tt := tc
    94  		t.Run(tt.tcName, func(t *testing.T) {
    95  			exportedKeyBytes, origKH := exportRawPublicKeyBytes(t, tt.keyTemplate, false)
    96  
    97  			kh, err := PublicKeyBytesToHandle(exportedKeyBytes, tt.keyType)
    98  			require.NoError(t, err)
    99  			require.NotEmpty(t, kh)
   100  
   101  			if tt.doSign {
   102  				if tt.keyType == kms.BLS12381G2Type {
   103  					msg1 := []byte("Lorem ipsum dolor sit amet,")
   104  					msg2 := []byte("consectetur adipiscing elit.")
   105  					msg := [][]byte{msg1, msg2}
   106  					signer, err := bbs.NewSigner(origKH)
   107  					require.NoError(t, err)
   108  					require.NotEmpty(t, signer)
   109  
   110  					s, err := signer.Sign(msg)
   111  					require.NoError(t, err)
   112  					require.NotEmpty(t, s)
   113  
   114  					verifier, err := bbs.NewVerifier(kh)
   115  					require.NoError(t, err)
   116  					require.NotEmpty(t, verifier)
   117  
   118  					err = verifier.Verify(msg, s)
   119  					require.NoError(t, err)
   120  
   121  					nonce := []byte("somenonce")
   122  					proof, err := verifier.DeriveProof(msg, s, nonce, []int{1})
   123  					require.NoError(t, err)
   124  					require.NotEmpty(t, proof)
   125  
   126  					err = verifier.VerifyProof([][]byte{msg2}, proof, nonce)
   127  					require.NoError(t, err)
   128  
   129  					return
   130  				}
   131  				// test signing with origKH then verifying with kh read from exported public key
   132  				msg := []byte("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
   133  				signer, err := signature.NewSigner(origKH)
   134  				require.NoError(t, err)
   135  				require.NotEmpty(t, signer)
   136  
   137  				s, err := signer.Sign(msg)
   138  				require.NoError(t, err)
   139  				require.NotEmpty(t, s)
   140  
   141  				verifier, err := signature.NewVerifier(kh)
   142  				require.NoError(t, err)
   143  				require.NotEmpty(t, verifier)
   144  
   145  				err = verifier.Verify(s, msg)
   146  				require.NoError(t, err)
   147  			}
   148  		})
   149  	}
   150  }
   151  
   152  func exportRawPublicKeyBytes(t *testing.T, keyTemplate *tinkpb.KeyTemplate, expectError bool) ([]byte, *keyset.Handle) {
   153  	t.Helper()
   154  
   155  	kh, err := keyset.NewHandle(keyTemplate)
   156  	require.NoError(t, err)
   157  	require.NotEmpty(t, kh)
   158  
   159  	pubKH, err := kh.Public()
   160  	require.NoError(t, err)
   161  	require.NotEmpty(t, pubKH)
   162  
   163  	buf := new(bytes.Buffer)
   164  	pubKeyWriter := NewWriter(buf)
   165  	require.NotEmpty(t, pubKeyWriter)
   166  
   167  	err = pubKH.WriteWithNoSecrets(pubKeyWriter)
   168  
   169  	if expectError {
   170  		require.Error(t, err)
   171  		return nil, kh
   172  	}
   173  
   174  	require.NoError(t, err)
   175  	require.NotEmpty(t, buf.Bytes())
   176  
   177  	return buf.Bytes(), kh
   178  }
   179  
   180  func TestNegativeCases(t *testing.T) {
   181  	t.Run("test publicKeyBytesToHandle with empty pubKey", func(t *testing.T) {
   182  		kh, err := PublicKeyBytesToHandle([]byte{}, kms.ECDSAP256TypeIEEEP1363)
   183  		require.EqualError(t, err, "pubKey is empty")
   184  		require.Empty(t, kh)
   185  	})
   186  
   187  	t.Run("test publicKeyBytesToHandle with empty KeyType", func(t *testing.T) {
   188  		kh, err := PublicKeyBytesToHandle([]byte{1}, "")
   189  		require.EqualError(t, err, "error getting marshalled proto key: invalid key type")
   190  		require.Empty(t, kh)
   191  	})
   192  
   193  	t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP256TypeDER", func(t *testing.T) {
   194  		kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP256TypeDER)
   195  		require.EqualError(t, err, "error getting marshalled proto key: asn1: syntax error: truncated tag or length")
   196  		require.Empty(t, kh)
   197  	})
   198  
   199  	t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP256TypeIEEEP1363", func(t *testing.T) {
   200  		kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP256TypeIEEEP1363)
   201  		require.EqualError(t, err, "error getting marshalled proto key: failed to unamrshal public ecdsa key")
   202  		require.Empty(t, kh)
   203  	})
   204  
   205  	t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP384TypeDER", func(t *testing.T) {
   206  		kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP384TypeDER)
   207  		require.EqualError(t, err, "error getting marshalled proto key: asn1: syntax error: truncated tag or length")
   208  		require.Empty(t, kh)
   209  	})
   210  
   211  	t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP384TypeIEEEP1363", func(t *testing.T) {
   212  		kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP384TypeIEEEP1363)
   213  		require.EqualError(t, err, "error getting marshalled proto key: failed to unamrshal public ecdsa key")
   214  		require.Empty(t, kh)
   215  	})
   216  
   217  	t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP521TypeDER", func(t *testing.T) {
   218  		kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP521TypeDER)
   219  		require.EqualError(t, err, "error getting marshalled proto key: asn1: syntax error: truncated tag or length")
   220  		require.Empty(t, kh)
   221  	})
   222  
   223  	t.Run("test publicKeyBytesToHandle with bad pubKey and ECDSAP521TypeIEEEP1363", func(t *testing.T) {
   224  		kh, err := PublicKeyBytesToHandle([]byte{1}, kms.ECDSAP521TypeIEEEP1363)
   225  		require.EqualError(t, err, "error getting marshalled proto key: failed to unamrshal public ecdsa key")
   226  		require.Empty(t, kh)
   227  	})
   228  
   229  	t.Run("test getMarshalledECDSAKey with empty curveName", func(t *testing.T) {
   230  		kh, err := getMarshalledECDSADERKey([]byte{},
   231  			"",
   232  			commonpb.EllipticCurveType_NIST_P521,
   233  			commonpb.HashType_SHA512)
   234  		require.EqualError(t, err, "undefined curve")
   235  		require.Empty(t, kh)
   236  	})
   237  
   238  	t.Run("test getMarshalledECDSAKey with empty curveName", func(t *testing.T) {
   239  		kh, err := getMarshalledECDSAIEEEP1363Key([]byte{},
   240  			"",
   241  			commonpb.EllipticCurveType_NIST_P521,
   242  			commonpb.HashType_SHA512)
   243  		require.EqualError(t, err, "undefined curve")
   244  		require.Empty(t, kh)
   245  	})
   246  
   247  	t.Run("test exportRawPublicKeyBytes with an unsupported key template", func(t *testing.T) {
   248  		exportedKeyBytes, _ := exportRawPublicKeyBytes(t, hybrid.ECIESHKDFAES128GCMKeyTemplate(), true)
   249  		require.Empty(t, exportedKeyBytes)
   250  	})
   251  
   252  	t.Run("test export with symmetric key should fail", func(t *testing.T) {
   253  		kt := aead.AES256GCMKeyTemplate()
   254  		kh, err := keyset.NewHandle(kt)
   255  		require.NoError(t, err)
   256  		require.NotEmpty(t, kh)
   257  
   258  		buf := new(bytes.Buffer)
   259  		pubKeyWriter := NewWriter(buf)
   260  		require.NotEmpty(t, pubKeyWriter)
   261  
   262  		err = kh.Write(pubKeyWriter, &NoLockMock{})
   263  		require.Error(t, err)
   264  		require.Empty(t, buf.Bytes())
   265  	})
   266  }
   267  
   268  // NoLockMock is a mock lock service that does no encryption/decryption of plaintext and implements tink.AEAD interface.
   269  type NoLockMock struct{}
   270  
   271  // Encrypt is a mock function of AEAD.Encrypt().
   272  func (s *NoLockMock) Encrypt(pt, aad []byte) ([]byte, error) {
   273  	return pt, nil
   274  }
   275  
   276  // Decrypt is a mock function of AEAD.Decrypt().
   277  func (s *NoLockMock) Decrypt(req, aad []byte) ([]byte, error) {
   278  	return req, nil
   279  }