github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/primitive/composite/ecdh/ecdh_nistpkw_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 "bytes" 11 "crypto/elliptic" 12 "crypto/rand" 13 "strings" 14 "testing" 15 16 "github.com/google/tink/go/aead" 17 hybrid "github.com/google/tink/go/hybrid/subtle" 18 gcmpb "github.com/google/tink/go/proto/aes_gcm_go_proto" 19 commonpb "github.com/google/tink/go/proto/common_go_proto" 20 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 21 "github.com/stretchr/testify/require" 22 "google.golang.org/protobuf/proto" 23 24 cbcaead "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead" 25 "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite" 26 ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto" 27 ) 28 29 func TestECDHNISTPAESPrivateKeyManager_Primitive(t *testing.T) { 30 km := newECDHNISTPAESPrivateKeyManager() 31 32 t.Run("Test private key manager Primitive() with empty serialized key", func(t *testing.T) { 33 p, err := km.Primitive([]byte("")) 34 require.EqualError(t, err, errInvalidNISTPECDHKWPrivateKey.Error(), 35 "nistPECDHKWPrivateKeyManager primitive from empty serialized key must fail") 36 require.Empty(t, p) 37 }) 38 39 t.Run("Test private key manager Primitive() with bad serialize key", func(t *testing.T) { 40 p, err := km.Primitive([]byte("bad.data")) 41 require.EqualError(t, err, errInvalidNISTPECDHKWPrivateKey.Error(), 42 "nistPECDHKWPrivateKeyManager primitive from bad serialized key must fail") 43 require.Empty(t, p) 44 }) 45 46 format := &gcmpb.AesGcmKeyFormat{ 47 KeySize: 32, 48 } 49 serializedFormat, err := proto.Marshal(format) 50 require.NoError(t, err) 51 52 format = &gcmpb.AesGcmKeyFormat{ 53 KeySize: 99, // bad AES128GCM size 54 } 55 56 badSerializedFormat, err := proto.Marshal(format) 57 require.NoError(t, err) 58 59 flagTests := []struct { 60 tcName string 61 version uint32 62 curveType commonpb.EllipticCurveType 63 keyType ecdhpb.KeyType 64 ecPtFmt commonpb.EcPointFormat 65 encTmp *tinkpb.KeyTemplate 66 }{ 67 { 68 tcName: "private key manager Primitive() using key with bad version", 69 version: 9999, 70 curveType: commonpb.EllipticCurveType_NIST_P256, 71 keyType: ecdhpb.KeyType_EC, 72 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 73 encTmp: aead.AES128GCMKeyTemplate(), 74 }, 75 { 76 tcName: "private key manager Primitive() using key with bad curve", 77 version: 0, 78 curveType: commonpb.EllipticCurveType_UNKNOWN_CURVE, 79 keyType: ecdhpb.KeyType_EC, 80 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 81 encTmp: aead.AES128GCMKeyTemplate(), 82 }, 83 { 84 tcName: "private key manager Primitive() using key with bad key type", 85 version: 0, 86 curveType: commonpb.EllipticCurveType_NIST_P256, 87 keyType: ecdhpb.KeyType_UNKNOWN_KEY_TYPE, 88 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 89 encTmp: aead.AES128GCMKeyTemplate(), 90 }, 91 { 92 tcName: "success private key manager Primitive()", 93 version: 0, 94 curveType: commonpb.EllipticCurveType_NIST_P256, 95 keyType: ecdhpb.KeyType_EC, 96 ecPtFmt: commonpb.EcPointFormat_UNCOMPRESSED, 97 encTmp: aead.AES128GCMKeyTemplate(), 98 }, 99 { 100 tcName: "private key manager Primitive() using key with bad key template URL", 101 version: 0, 102 curveType: commonpb.EllipticCurveType_NIST_P256, 103 keyType: ecdhpb.KeyType_EC, 104 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 105 encTmp: &tinkpb.KeyTemplate{ 106 TypeUrl: "bad.type/url/value", 107 Value: serializedFormat, 108 OutputPrefixType: tinkpb.OutputPrefixType_RAW, 109 }, 110 }, 111 { 112 tcName: "private key manager Primitive() using key with bad dem key size", 113 version: 0, 114 curveType: commonpb.EllipticCurveType_NIST_P256, 115 keyType: ecdhpb.KeyType_EC, 116 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 117 encTmp: &tinkpb.KeyTemplate{ 118 TypeUrl: composite.AESGCMTypeURL, 119 Value: badSerializedFormat, 120 OutputPrefixType: tinkpb.OutputPrefixType_RAW, 121 }, 122 }, 123 } 124 125 for _, tc := range flagTests { 126 tt := tc 127 t.Run("Test "+tt.tcName, func(t *testing.T) { 128 c := tt.curveType 129 encT := tt.encTmp 130 ptFmt := tt.ecPtFmt 131 v := tt.version 132 133 // temporarily reset curvType if its unknown type so subtle.GetCurve() below doesn't fail 134 if tt.curveType.String() == commonpb.EllipticCurveType_UNKNOWN_CURVE.String() { 135 c = commonpb.EllipticCurveType_NIST_P256 136 } 137 138 crv, err := hybrid.GetCurve(c.String()) 139 require.NoError(t, err) 140 d, x, y, err := elliptic.GenerateKey(crv, rand.Reader) 141 require.NoError(t, err) 142 143 // set back curvType if it was unknown to proceed with the test 144 if tt.curveType.String() == commonpb.EllipticCurveType_UNKNOWN_CURVE.String() { 145 c = tt.curveType 146 } 147 148 privKeyProto := &ecdhpb.EcdhAeadPrivateKey{ 149 Version: v, 150 PublicKey: &ecdhpb.EcdhAeadPublicKey{ 151 Version: v, // if v > 0 to force an error when calling km.Primitive() 152 Params: &ecdhpb.EcdhAeadParams{ 153 KwParams: &ecdhpb.EcdhKwParams{ 154 CurveType: c, // unknown curve type to force an error when calling km.Primitive() 155 KeyType: tt.keyType, // invalid key type to force error when calling km.Primitive() 156 }, 157 EncParams: &ecdhpb.EcdhAeadEncParams{ 158 AeadEnc: encT, // invalid data enc key template to get an error when calling km.Primitive() 159 }, 160 EcPointFormat: ptFmt, 161 }, 162 X: x.Bytes(), 163 Y: y.Bytes(), 164 }, 165 KeyValue: d, 166 } 167 168 sPrivKey, err := proto.Marshal(privKeyProto) 169 require.NoError(t, err) 170 171 p, err := km.Primitive(sPrivKey) 172 if bytes.Equal(tt.encTmp.Value, badSerializedFormat) { 173 require.EqualError(t, err, errInvalidNISTPECDHKWPrivateKey.Error(), 174 "nistPECDHKWPrivateKeyManager primitive from serialized key with invalid serialized key") 175 require.Empty(t, p) 176 177 return 178 } 179 180 if strings.Contains(tt.tcName, "success") { 181 require.NoError(t, err) 182 require.NotEmpty(t, p) 183 return 184 } 185 186 require.Errorf(t, err, tt.tcName) 187 require.Empty(t, p) 188 }) 189 } 190 } 191 192 func TestEcdhNISTPAESPrivateKeyManager_DoesSupport(t *testing.T) { 193 km := newECDHNISTPAESPrivateKeyManager() 194 require.False(t, km.DoesSupport("bad/url")) 195 require.True(t, km.DoesSupport(nistpECDHKWPrivateKeyTypeURL)) 196 } 197 198 func TestEcdhNISTPAESPrivateKeyManager_NewKey(t *testing.T) { 199 km := newECDHNISTPAESPrivateKeyManager() 200 201 t.Run("Test private key manager NewKey() with nil key", func(t *testing.T) { 202 k, err := km.NewKey(nil) 203 require.EqualError(t, err, errInvalidNISTPECDHKWPrivateKeyFormat.Error()) 204 require.Empty(t, k) 205 }) 206 207 t.Run("Test private key manager NewKey() with bad serialize key", func(t *testing.T) { 208 p, err := km.NewKey([]byte("bad.data")) 209 require.EqualError(t, err, errInvalidNISTPECDHKWPrivateKeyFormat.Error(), 210 "ECDHESPrivate NewKey() from bad serialized key must fail") 211 require.Empty(t, p) 212 }) 213 214 format := &gcmpb.AesGcmKeyFormat{ 215 KeySize: 32, 216 } 217 218 serializedFormat, err := proto.Marshal(format) 219 require.NoError(t, err) 220 221 format = &gcmpb.AesGcmKeyFormat{ 222 KeySize: 99, // bad AES128GCM size 223 } 224 225 badSerializedFormat, err := proto.Marshal(format) 226 require.NoError(t, err) 227 228 flagTests := []struct { 229 tcName string 230 curveType commonpb.EllipticCurveType 231 keyType ecdhpb.KeyType 232 ecPtFmt commonpb.EcPointFormat 233 encTmp *tinkpb.KeyTemplate 234 }{ 235 { 236 tcName: "success private key manager NewKey() and NewKeyData()", 237 curveType: commonpb.EllipticCurveType_NIST_P256, 238 keyType: ecdhpb.KeyType_EC, 239 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 240 encTmp: aead.AES128GCMKeyTemplate(), 241 }, 242 { 243 tcName: "private key manager NewKey() and NewKeyData() using key with bad curve", 244 curveType: commonpb.EllipticCurveType_UNKNOWN_CURVE, 245 keyType: ecdhpb.KeyType_EC, 246 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 247 encTmp: aead.AES128GCMKeyTemplate(), 248 }, 249 { 250 tcName: "private key manager NewKey() and NewKeyData() using key with bad key type", 251 curveType: commonpb.EllipticCurveType_NIST_P256, 252 keyType: ecdhpb.KeyType_UNKNOWN_KEY_TYPE, 253 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 254 encTmp: aead.AES256GCMKeyTemplate(), 255 }, 256 { 257 tcName: "private key manager NewKey() and NewKeyData() using key with bad key template URL", 258 curveType: commonpb.EllipticCurveType_NIST_P256, 259 keyType: ecdhpb.KeyType_EC, 260 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 261 encTmp: &tinkpb.KeyTemplate{ 262 TypeUrl: "bad.type/url/value", 263 Value: serializedFormat, 264 OutputPrefixType: tinkpb.OutputPrefixType_RAW, 265 }, 266 }, 267 { 268 tcName: "private key manager NewKey() and NewKeyData() using key with bad dem key size", 269 curveType: commonpb.EllipticCurveType_NIST_P256, 270 keyType: ecdhpb.KeyType_EC, 271 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 272 encTmp: &tinkpb.KeyTemplate{ 273 TypeUrl: composite.AESGCMTypeURL, 274 Value: badSerializedFormat, 275 OutputPrefixType: tinkpb.OutputPrefixType_RAW, 276 }, 277 }, 278 { 279 tcName: "success private key manager NewKey() and NewKeyData() with AES-CBC+HMAC encTmp", 280 curveType: commonpb.EllipticCurveType_NIST_P256, 281 keyType: ecdhpb.KeyType_EC, 282 ecPtFmt: commonpb.EcPointFormat_COMPRESSED, 283 encTmp: cbcaead.AES128CBCHMACSHA256KeyTemplate(), 284 }, 285 } 286 287 for _, tc := range flagTests { 288 tt := tc 289 t.Run("Test "+tt.tcName, func(t *testing.T) { 290 encT := tt.encTmp 291 ptFmt := tt.ecPtFmt 292 293 privKeyProto := &ecdhpb.EcdhAeadKeyFormat{ 294 Params: &ecdhpb.EcdhAeadParams{ 295 KwParams: &ecdhpb.EcdhKwParams{ 296 CurveType: tt.curveType, // unknown curve type to force an error when calling km.NewKey() 297 KeyType: tt.keyType, // unknown curve type to force an error when calling km.NewKey() 298 }, 299 EncParams: &ecdhpb.EcdhAeadEncParams{ 300 AeadEnc: encT, // invalid data enc key template to force an error when calling km.NewKey() 301 }, 302 EcPointFormat: ptFmt, // unknown EC Point format type to force an error when calling km.NewKey() 303 }, 304 } 305 306 sPrivKey, err := proto.Marshal(privKeyProto) 307 require.NoError(t, err) 308 309 p, err := km.NewKey(sPrivKey) 310 if strings.Contains(tt.tcName, "success") { 311 require.NoError(t, err) 312 require.NotEmpty(t, p) 313 314 sp, e := proto.Marshal(p) 315 require.NoError(t, e) 316 require.NotEmpty(t, sp) 317 318 // try PublicKeyData() with bad serialized private key 319 pubK, e := km.PublicKeyData([]byte("bad serialized private key")) 320 require.Error(t, e) 321 require.Empty(t, pubK) 322 323 // try PublicKeyData() with valid serialized private key 324 pubK, e = km.PublicKeyData(sp) 325 require.NoError(t, e) 326 require.NotEmpty(t, pubK) 327 } 328 329 kd, err := km.NewKeyData(sPrivKey) 330 if strings.Contains(tt.tcName, "success") { 331 require.NoError(t, err) 332 require.NotEmpty(t, kd) 333 require.Equal(t, kd.TypeUrl, nistpECDHKWPrivateKeyTypeURL) 334 require.Equal(t, kd.KeyMaterialType, tinkpb.KeyData_ASYMMETRIC_PRIVATE) 335 return 336 } 337 338 if bytes.Equal(tt.encTmp.Value, badSerializedFormat) { 339 require.EqualError(t, err, errInvalidNISTPECDHKWPrivateKeyFormat.Error(), 340 "nistPECDHKWPrivateKeyManager NewKey from serialized key with invalid serialized key") 341 require.Empty(t, p) 342 343 return 344 } 345 346 require.Errorf(t, err, tt.tcName) 347 require.Empty(t, p) 348 }) 349 } 350 }