github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/composite/ecdh/ecdh_x25519kw_private_key_manager_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package ecdh
     8  
     9  import (
    10  	"crypto/ed25519"
    11  	"crypto/rand"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/google/tink/go/aead"
    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/stretchr/testify/require"
    19  	"google.golang.org/protobuf/proto"
    20  
    21  	"github.com/trustbloc/kms-go/util/cryptoutil"
    22  
    23  	cbcaead "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead"
    24  	ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
    25  )
    26  
    27  func TestECDHX25519XChachaPrivateKeyManager_Primitive(t *testing.T) {
    28  	km := newX25519ECDHKWPrivateKeyManager()
    29  
    30  	t.Run("Test private key manager Primitive() with empty serialized key", func(t *testing.T) {
    31  		p, err := km.Primitive([]byte(""))
    32  		require.EqualError(t, err, errInvalidx25519ECDHKWPrivateKey.Error(),
    33  			"x25519ECDHKWPrivateKeyManager primitive from empty serialized key must fail")
    34  		require.Empty(t, p)
    35  	})
    36  
    37  	t.Run("Test private key manager Primitive() with bad serialize key", func(t *testing.T) {
    38  		p, err := km.Primitive([]byte("bad.data"))
    39  		require.EqualError(t, err, errInvalidx25519ECDHKWPrivateKey.Error(),
    40  			"x25519ECDHKWPrivateKeyManager primitive from bad serialized key must fail")
    41  		require.Empty(t, p)
    42  	})
    43  
    44  	flagTests := []struct {
    45  		tcName    string
    46  		version   uint32
    47  		curveType commonpb.EllipticCurveType
    48  		keyType   ecdhpb.KeyType
    49  		encTmp    *tinkpb.KeyTemplate
    50  	}{
    51  		{
    52  			tcName:    "private key manager Primitive() using key with bad version",
    53  			version:   9999,
    54  			curveType: commonpb.EllipticCurveType_CURVE25519,
    55  			keyType:   ecdhpb.KeyType_OKP,
    56  			encTmp:    aead.XChaCha20Poly1305KeyTemplate(),
    57  		},
    58  		{
    59  			tcName:    "private key manager Primitive() using key with bad curve",
    60  			version:   0,
    61  			curveType: commonpb.EllipticCurveType_UNKNOWN_CURVE,
    62  			keyType:   ecdhpb.KeyType_OKP,
    63  			encTmp:    aead.XChaCha20Poly1305KeyTemplate(),
    64  		},
    65  		{
    66  			tcName:    "private key manager Primitive() using key with bad key type",
    67  			version:   0,
    68  			curveType: commonpb.EllipticCurveType_CURVE25519,
    69  			keyType:   ecdhpb.KeyType_UNKNOWN_KEY_TYPE,
    70  			encTmp:    aead.XChaCha20Poly1305KeyTemplate(),
    71  		},
    72  		{
    73  			tcName:    "success private key manager Primitive()",
    74  			version:   0,
    75  			curveType: commonpb.EllipticCurveType_CURVE25519,
    76  			keyType:   ecdhpb.KeyType_OKP,
    77  			encTmp:    aead.XChaCha20Poly1305KeyTemplate(),
    78  		},
    79  		{
    80  			tcName:    "private key manager Primitive() using key with bad key template URL",
    81  			version:   0,
    82  			curveType: commonpb.EllipticCurveType_CURVE25519,
    83  			keyType:   ecdhpb.KeyType_OKP,
    84  			encTmp: &tinkpb.KeyTemplate{
    85  				TypeUrl:          "bad.type/url/value",
    86  				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
    87  			},
    88  		},
    89  		{
    90  			tcName:    "success private key manager Primitive() with AES-CBC+HMAC encTmp",
    91  			version:   0,
    92  			curveType: commonpb.EllipticCurveType_CURVE25519,
    93  			keyType:   ecdhpb.KeyType_OKP,
    94  			encTmp:    cbcaead.AES128CBCHMACSHA256KeyTemplate(),
    95  		},
    96  	}
    97  
    98  	for _, tc := range flagTests {
    99  		tt := tc
   100  		t.Run("Test "+tt.tcName, func(t *testing.T) {
   101  			pub, pvt, err := ed25519.GenerateKey(rand.Reader)
   102  			require.NoError(t, err)
   103  
   104  			x25519Pub, err := cryptoutil.PublicEd25519toCurve25519(pub)
   105  			require.NoError(t, err)
   106  
   107  			x25519Pvt, err := cryptoutil.SecretEd25519toCurve25519(pvt)
   108  			require.NoError(t, err)
   109  
   110  			params := &ecdhpb.EcdhAeadParams{
   111  				KwParams: &ecdhpb.EcdhKwParams{
   112  					KeyType:   tt.keyType,
   113  					CurveType: tt.curveType,
   114  				},
   115  				EncParams: &ecdhpb.EcdhAeadEncParams{
   116  					AeadEnc: tt.encTmp,
   117  					CEK:     []byte{},
   118  				},
   119  				EcPointFormat: commonpb.EcPointFormat_UNCOMPRESSED,
   120  			}
   121  
   122  			privKeyProto := &ecdhpb.EcdhAeadPrivateKey{
   123  				Version:  tt.version,
   124  				KeyValue: x25519Pvt,
   125  				PublicKey: &ecdhpb.EcdhAeadPublicKey{
   126  					Version: x25519ECDHKWPrivateKeyVersion,
   127  					Params:  params,
   128  					X:       x25519Pub,
   129  				},
   130  			}
   131  
   132  			sPrivKey, err := proto.Marshal(privKeyProto)
   133  			require.NoError(t, err)
   134  
   135  			p, err := km.Primitive(sPrivKey)
   136  			if strings.Contains(tt.tcName, "success") {
   137  				require.NoError(t, err)
   138  				require.NotEmpty(t, p)
   139  				return
   140  			}
   141  
   142  			require.Errorf(t, err, tt.tcName)
   143  			require.Empty(t, p)
   144  		})
   145  	}
   146  }
   147  
   148  func TestECDHX25519XChachaPrivateKeyManager_DoesSupport(t *testing.T) {
   149  	km := newX25519ECDHKWPrivateKeyManager()
   150  	require.False(t, km.DoesSupport("bad/url"))
   151  	require.True(t, km.DoesSupport(x25519ECDHKWPrivateKeyTypeURL))
   152  }
   153  
   154  func TestECDHX25519XChachaPrivateKeyManager_NewKey(t *testing.T) {
   155  	km := newX25519ECDHKWPrivateKeyManager()
   156  
   157  	t.Run("Test private key manager NewKey() with nil key", func(t *testing.T) {
   158  		k, err := km.NewKey(nil)
   159  		require.EqualError(t, err, errInvalidx25519ECDHKWPrivateKeyFormat.Error())
   160  		require.Empty(t, k)
   161  	})
   162  
   163  	t.Run("Test private key manager NewKey() with bad serialize key", func(t *testing.T) {
   164  		p, err := km.NewKey([]byte("bad.data"))
   165  		require.EqualError(t, err, errInvalidx25519ECDHKWPrivateKeyFormat.Error(),
   166  			"x25519ECDHKWPrivateKeyManager NewKey() from bad serialized key must fail")
   167  		require.Empty(t, p)
   168  	})
   169  
   170  	flagTests := []struct {
   171  		tcName    string
   172  		curveType commonpb.EllipticCurveType
   173  		keyType   ecdhpb.KeyType
   174  		encTmp    *tinkpb.KeyTemplate
   175  	}{
   176  		{
   177  			tcName:    "success private key manager NewKey() and NewKeyData()",
   178  			curveType: commonpb.EllipticCurveType_CURVE25519,
   179  			keyType:   ecdhpb.KeyType_OKP,
   180  			encTmp:    aead.XChaCha20Poly1305KeyTemplate(),
   181  		},
   182  		{
   183  			tcName:    "private key manager NewKey() and NewKeyData() using key with bad curve",
   184  			curveType: commonpb.EllipticCurveType_UNKNOWN_CURVE,
   185  			keyType:   ecdhpb.KeyType_OKP,
   186  			encTmp:    aead.XChaCha20Poly1305KeyTemplate(),
   187  		},
   188  		{
   189  			tcName:    "private key manager NewKey() and NewKeyData() using key with bad key type",
   190  			curveType: commonpb.EllipticCurveType_CURVE25519,
   191  			keyType:   ecdhpb.KeyType_EC,
   192  			encTmp:    aead.XChaCha20Poly1305KeyTemplate(),
   193  		},
   194  		{
   195  			tcName:    "private key manager NewKey() and NewKeyData() using key with bad key template URL",
   196  			curveType: commonpb.EllipticCurveType_CURVE25519,
   197  			keyType:   ecdhpb.KeyType_OKP,
   198  			encTmp: &tinkpb.KeyTemplate{
   199  				TypeUrl:          "bad.type/url/value",
   200  				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
   201  			},
   202  		},
   203  	}
   204  
   205  	for _, tc := range flagTests {
   206  		tt := tc
   207  		t.Run("Test "+tt.tcName, func(t *testing.T) {
   208  			privKeyProto := &ecdhpb.EcdhAeadKeyFormat{
   209  				Params: &ecdhpb.EcdhAeadParams{
   210  					KwParams: &ecdhpb.EcdhKwParams{
   211  						CurveType: tt.curveType, // unknown curve to force an error when calling km.NewKey()
   212  						KeyType:   tt.keyType,   // unknown key type to force an error when calling km.NewKey()
   213  					},
   214  					EncParams: &ecdhpb.EcdhAeadEncParams{
   215  						AeadEnc: tt.encTmp, // invalid data enc key template to force an error when calling km.NewKey()
   216  					},
   217  					EcPointFormat: commonpb.EcPointFormat_UNCOMPRESSED,
   218  				},
   219  			}
   220  
   221  			sPrivKey, err := proto.Marshal(privKeyProto)
   222  			require.NoError(t, err)
   223  
   224  			p, err := km.NewKey(sPrivKey)
   225  			if strings.Contains(tt.tcName, "success") {
   226  				require.NoError(t, err)
   227  				require.NotEmpty(t, p)
   228  
   229  				sp, e := proto.Marshal(p)
   230  				require.NoError(t, e)
   231  				require.NotEmpty(t, sp)
   232  
   233  				// try PublicKeyData() with bad serialized private key
   234  				pubK, e := km.PublicKeyData([]byte("bad serialized private key"))
   235  				require.Error(t, e)
   236  				require.Empty(t, pubK)
   237  
   238  				// try PublicKeyData() with valid serialized private key
   239  				pubK, e = km.PublicKeyData(sp)
   240  				require.NoError(t, e)
   241  				require.NotEmpty(t, pubK)
   242  			}
   243  
   244  			kd, err := km.NewKeyData(sPrivKey)
   245  			if strings.Contains(tt.tcName, "success") {
   246  				require.NoError(t, err)
   247  				require.NotEmpty(t, kd)
   248  				require.Equal(t, kd.TypeUrl, x25519ECDHKWPrivateKeyTypeURL)
   249  				require.Equal(t, kd.KeyMaterialType, tinkpb.KeyData_ASYMMETRIC_PRIVATE)
   250  				return
   251  			}
   252  
   253  			require.Errorf(t, err, tt.tcName)
   254  			require.Empty(t, p)
   255  		})
   256  	}
   257  }