github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/jose/encrypt_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package jose 8 9 import ( 10 "bytes" 11 "crypto/elliptic" 12 "encoding/base64" 13 "encoding/json" 14 "fmt" 15 "testing" 16 17 "github.com/google/tink/go/aead" 18 "github.com/google/tink/go/keyset" 19 "github.com/stretchr/testify/require" 20 21 cryptoapi "github.com/hyperledger/aries-framework-go/pkg/crypto" 22 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" 23 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/ecdh" 24 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/keyio" 25 ) 26 27 func TestFailConvertRecKeyToMarshalledJWK(t *testing.T) { 28 t.Run("test convertRecEPKToMarshalledJWK using EPK with bad curve", func(t *testing.T) { 29 recKey := &cryptoapi.RecipientWrappedKey{ 30 EPK: cryptoapi.PublicKey{ 31 Curve: "badCurveName", 32 Type: "EC", 33 }, 34 } 35 36 _, err := convertRecEPKToMarshalledJWK(&recKey.EPK) 37 require.EqualError(t, err, "unsupported curve") 38 }) 39 40 t.Run("test convertRecEPKToMarshalledJWK and buildRecipientHeaders using EPK with bad key type", func(t *testing.T) { 41 recKey := &cryptoapi.RecipientWrappedKey{ 42 EPK: cryptoapi.PublicKey{ 43 Curve: "P-256", 44 }, 45 } 46 47 _, err := convertRecEPKToMarshalledJWK(&recKey.EPK) 48 require.EqualError(t, err, "invalid key type") 49 50 _, err = buildRecipientHeaders(recKey, false) 51 require.EqualError(t, err, "failed to convert recipient key to marshalled JWK: invalid key type") 52 }) 53 } 54 55 func TestBuildRecsWithEPKMissingKeyTypeFailure(t *testing.T) { 56 recKey := &cryptoapi.RecipientWrappedKey{ 57 EPK: cryptoapi.PublicKey{ 58 Curve: "P-256", 59 }, 60 } 61 62 c, err := tinkcrypto.New() 63 require.NoError(t, err) 64 65 recipients, recsKH := createRecipients(t, 2) 66 67 enc, err := NewJWEEncrypt(A256GCM, testEncType, testPayloadType, 68 "0", recsKH["0"], recipients, c) 69 require.NoError(t, err) 70 71 _, _, err = enc.buildRecs([]*cryptoapi.RecipientWrappedKey{recKey}, true) 72 require.EqualError(t, err, "failed to convert recipient key to marshalled JWK: invalid key type") 73 } 74 75 func TestBadSenderKeyType(t *testing.T) { 76 c, err := tinkcrypto.New() 77 require.NoError(t, err) 78 79 // create a keyset.Handle that fails JWE/ECDH primitive execution (must come from an ECDH key template). 80 aeadKT := aead.AES256GCMKeyTemplate() 81 aeadKH, err := keyset.NewHandle(aeadKT) 82 require.NoError(t, err) 83 84 recipients, _ := createRecipients(t, 2) 85 86 // create jweEncrypter manually with a bad sender type 87 jweEncrypter := JWEEncrypt{ 88 skid: "123", 89 senderKH: aeadKH, 90 recipientsKeys: recipients, 91 crypto: c, 92 encAlg: A256GCM, 93 } 94 95 _, err = jweEncrypter.Encrypt([]byte{}) 96 require.EqualError(t, err, "jweencryptWithSender: failed to wrap cek: wrapCEKForRecipientsWithTagAndEPK: "+ 97 "wrapKey: 1 failed: wrapKey: deriveKEKAndWrap: error ECDH-1PU kek derivation: derive1PUKEK: EC key derivation "+ 98 "error derive1PUWithECKey: failed to retrieve sender key: ksToPrivateECDSAKey: failed to extract sender key: "+ 99 "extractPrivKey: can't extract unsupported private key 'type.googleapis.com/google.crypto.tink.AesGcmKey'") 100 } 101 102 func TestMergeSingleRecipientsHeadersFailureWithUnsetCurve(t *testing.T) { 103 aad := map[string]string{"enc": "test"} 104 105 mAAD, err := json.Marshal(aad) 106 require.NoError(t, err) 107 108 wk := &cryptoapi.RecipientWrappedKey{ 109 EPK: cryptoapi.PublicKey{Type: "EC"}, 110 } 111 112 // fail with aad not base64URL encoded 113 _, err = mergeSingleRecipientHeaders(wk, []byte("aad not base64URL encoded"), json.Marshal) 114 require.EqualError(t, err, "illegal base64 data at input byte 3") 115 116 badAAD := base64.RawURLEncoding.EncodeToString([]byte("aad not a json format")) 117 118 // fail with aad not being a marshalled json 119 _, err = mergeSingleRecipientHeaders(wk, []byte(badAAD), json.Marshal) 120 require.EqualError(t, err, "invalid character 'a' looking for beginning of value") 121 122 // fail with epk curve not set 123 _, err = mergeSingleRecipientHeaders(wk, []byte(base64.RawURLEncoding.EncodeToString(mAAD)), json.Marshal) 124 require.EqualError(t, err, "unsupported curve") 125 126 // set epk curve for subsequent tests 127 wk.EPK.Curve = elliptic.P256().Params().Name 128 129 fm := &failingMarshaller{ 130 numTimesMarshalCalledBeforeReturnErr: 0, 131 } 132 133 // fail KID marshalling 134 _, err = mergeSingleRecipientHeaders(wk, []byte(base64.RawURLEncoding.EncodeToString(mAAD)), fm.failingMarshal) 135 require.EqualError(t, err, errFailingMarshal.Error()) 136 137 fm = &failingMarshaller{ 138 numTimesMarshalCalledBeforeReturnErr: 1, 139 } 140 141 // fail Alg marshalling 142 _, err = mergeSingleRecipientHeaders(wk, []byte(base64.RawURLEncoding.EncodeToString(mAAD)), fm.failingMarshal) 143 require.EqualError(t, err, errFailingMarshal.Error()) 144 145 fm = &failingMarshaller{ 146 numTimesMarshalCalledBeforeReturnErr: 1, 147 } 148 149 // fail EPK marshalling 150 _, err = mergeSingleRecipientHeaders(wk, []byte(base64.RawURLEncoding.EncodeToString(mAAD)), fm.failingMarshal) 151 require.EqualError(t, err, errFailingMarshal.Error()) 152 } 153 154 func TestEmptyComputeAuthData(t *testing.T) { 155 protecteHeaders := new(map[string]interface{}) 156 aad := []byte("") 157 _, err := computeAuthData(*protecteHeaders, "", aad) 158 require.NoError(t, err, "computeAuthData with empty protectedHeaders and empty aad should not fail") 159 } 160 161 // createRecipients and return their public key and keyset.Handle. 162 func createRecipients(t *testing.T, numberOfEntities int) ([]*cryptoapi.PublicKey, map[string]*keyset.Handle) { 163 t.Helper() 164 165 r := make([]*cryptoapi.PublicKey, 0) 166 rKH := make(map[string]*keyset.Handle) 167 168 for i := 0; i < numberOfEntities; i++ { 169 mrKey, kh := createAndMarshalEntityKey(t) 170 ecPubKey := new(cryptoapi.PublicKey) 171 err := json.Unmarshal(mrKey, ecPubKey) 172 require.NoError(t, err) 173 174 ecPubKey.KID = fmt.Sprint(i) 175 176 r = append(r, ecPubKey) 177 rKH[fmt.Sprint(i)] = kh 178 } 179 180 return r, rKH 181 } 182 183 // createAndMarshalEntityKey creates a new recipient keyset.Handle, extracts public key, marshals it and returns 184 // both marshalled public key and original recipient keyset.Handle. 185 func createAndMarshalEntityKey(t *testing.T) ([]byte, *keyset.Handle) { 186 t.Helper() 187 188 tmpl := ecdh.NISTP256ECDHKWKeyTemplate() 189 190 kh, err := keyset.NewHandle(tmpl) 191 require.NoError(t, err) 192 193 pubKH, err := kh.Public() 194 require.NoError(t, err) 195 196 buf := new(bytes.Buffer) 197 pubKeyWriter := keyio.NewWriter(buf) 198 require.NotEmpty(t, pubKeyWriter) 199 200 err = pubKH.WriteWithNoSecrets(pubKeyWriter) 201 require.NoError(t, err) 202 203 return buf.Bytes(), kh 204 } 205 206 const ( 207 testEncType = "application/test-encrypted+json" 208 testPayloadType = "application/test-content+json" 209 ) 210 211 func TestFailJWEEncrypt(t *testing.T) { 212 c, err := tinkcrypto.New() 213 require.NoError(t, err) 214 215 recipients, recsKH := createRecipients(t, 2) 216 217 enc, err := NewJWEEncrypt(A256GCM, testEncType, testPayloadType, 218 "0", recsKH["0"], recipients, c) 219 require.NoError(t, err) 220 221 enc.encAlg = "Undefined" 222 223 _, err = enc.Encrypt([]byte("test")) 224 require.EqualError(t, err, "jweencrypt: failed to get encryption primitive: getECDHEncPrimitive: encAlg"+ 225 " not supported: 'Undefined'") 226 } 227 228 func TestFailJWEDecrypt(t *testing.T) { 229 c, err := tinkcrypto.New() 230 require.NoError(t, err) 231 232 recipients, _ := createRecipients(t, 2) 233 234 // encrypt using local jose package 235 jweEncrypter, err := NewJWEEncrypt(A256GCM, testEncType, testPayloadType, 236 "", nil, recipients, c) 237 require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys") 238 239 pt := []byte("some msg") 240 jwe, err := jweEncrypter.Encrypt(pt) 241 require.NoError(t, err) 242 require.Equal(t, len(recipients), len(jwe.Recipients)) 243 244 dec := NewJWEDecrypt(nil, c, nil) 245 require.NotEmpty(t, dec) 246 247 jwe.ProtectedHeaders[HeaderEncryption] = "Undefined" 248 249 _, err = dec.decryptJWE(jwe, []byte("")) 250 require.EqualError(t, err, "jwedecrypt: failed to get decryption primitive: invalid content encAlg: 'Undefined'") 251 252 delete(jwe.ProtectedHeaders, HeaderEncryption) 253 254 _, err = dec.decryptJWE(jwe, []byte("")) 255 require.EqualError(t, err, "jwedecrypt: JWE 'enc' protected header is missing") 256 } 257 258 func TestBuildAPUAPVFailures(t *testing.T) { 259 c, err := tinkcrypto.New() 260 require.NoError(t, err) 261 262 recipients, _ := createRecipients(t, 3) 263 264 // encrypt using local jose package 265 jweEncrypter, err := NewJWEEncrypt(A256GCM, testEncType, testPayloadType, 266 "", nil, recipients, c) 267 require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys") 268 269 t.Run("call encryptWithSender and buildAPUAPV with JWEEncrypter having empty skid", func(t *testing.T) { 270 _, err = jweEncrypter.encryptWithSender(nil, nil, nil, nil, nil) 271 require.EqualError(t, err, "jweencryptWithSender: cannot create APU/APV with empty sender skid") 272 273 _, _, err = jweEncrypter.buildAPUAPV() 274 require.EqualError(t, err, "cannot create APU/APV with empty sender skid") 275 }) 276 277 t.Run("call buildAPUAPV with JWEEncrypter having empty recipients", func(t *testing.T) { 278 jweEncrypter.skid = "skid" 279 jweEncrypter.recipientsKeys = nil 280 281 _, _, err = jweEncrypter.buildAPUAPV() 282 require.EqualError(t, err, "cannot create APU/APV with empty recipient keys") 283 }) 284 } 285 286 func TestGenerateEPKAndUpdateAuthDataFor1PUFailure(t *testing.T) { 287 c, err := tinkcrypto.New() 288 require.NoError(t, err) 289 290 recipients, _ := createRecipients(t, 5) 291 292 recipients[0].Type = "invalidType" 293 294 // encrypt using local jose package 295 jweEncrypter, err := NewJWEEncrypt(A256GCM, testEncType, testPayloadType, 296 "", nil, recipients, c) 297 require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys") 298 299 epk, authData, authJSON, err := jweEncrypter.generateEPKAndUpdateAuthDataFor1PU(nil, nil, nil, nil) 300 require.EqualError(t, err, "generateEPKAndUpdateAuthDataFor1PU: newEPK: invalid key type 'invalidType'") 301 require.Empty(t, epk) 302 require.Empty(t, authData) 303 require.Empty(t, authJSON) 304 305 recipients[0].Type = "EC" 306 recipients[0].Curve = "invalid" 307 308 _, _, err = jweEncrypter.newEPK([]byte("")) 309 require.EqualError(t, err, "newEPK: ecEPKAndAlg: getCurve: unsupported curve") 310 } 311 312 func TestBuildCommonAuthDataFailure(t *testing.T) { 313 c, err := tinkcrypto.New() 314 require.NoError(t, err) 315 316 recipients, _ := createRecipients(t, 5) 317 318 recipients[0].Type = "invalid" 319 320 // encrypt using local jose package 321 jweEncrypter, err := NewJWEEncrypt(A256GCM, testEncType, testPayloadType, 322 "", nil, recipients, c) 323 require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys") 324 325 t.Run("buildCommonAuthData with authData having invalid b64 format", func(t *testing.T) { 326 epk, authData, authJSON, err := jweEncrypter.buildCommonAuthData(0, "", "==Badb64Str$$#^", 327 nil, nil, nil, nil) 328 require.EqualError(t, err, "buildCommonAuthData: authdata decode: illegal base64 data at input byte 0") 329 require.Empty(t, epk) 330 require.Empty(t, authData) 331 require.Empty(t, authJSON) 332 }) 333 334 t.Run("buildCommonAuthData with authData having invalid json format", func(t *testing.T) { 335 epk, authData, authJSON, err := jweEncrypter.buildCommonAuthData(0, "", "badjsonunmarshal", 336 nil, nil, nil, nil) 337 require.EqualError(t, err, "buildCommonAuthData: authData unmarshall: invalid character 'm' looking "+ 338 "for beginning of value") 339 require.Empty(t, epk) 340 require.Empty(t, authData) 341 require.Empty(t, authJSON) 342 }) 343 344 t.Run("buildCommonAuthData with epk having invalid public key type", func(t *testing.T) { 345 epk, authData, authJSON, err := jweEncrypter.buildCommonAuthData(0, "", "eyJ0ZXN0IjoidGVzdCJ9", 346 nil, nil, nil, &cryptoapi.PrivateKey{ 347 PublicKey: cryptoapi.PublicKey{Type: "invalid"}, 348 D: nil, 349 }) 350 require.EqualError(t, err, "buildCommonAuthData: epk marshall: invalid key type") 351 require.Empty(t, epk) 352 require.Empty(t, authData) 353 require.Empty(t, authJSON) 354 }) 355 } 356 357 func TestDecodeAPUAPVFailure(t *testing.T) { 358 t.Run("decodeAPUAPV with recipient APU header as invalid b64 []byte", func(t *testing.T) { 359 _, _, err := decodeAPUAPV(&RecipientHeaders{APU: "=Badb64Str$$#^"}) 360 require.EqualError(t, err, "illegal base64 data at input byte 0") 361 }) 362 363 t.Run("decodeAPUAPV with recipient APV header as invalid b64 []byte", func(t *testing.T) { 364 _, _, err := decodeAPUAPV(&RecipientHeaders{APV: "=Badb64Str$$#^"}) 365 require.EqualError(t, err, "illegal base64 data at input byte 0") 366 }) 367 } 368 369 func TestJWKMarshalEPKFailure(t *testing.T) { 370 t.Run("jwkMarshalEPK with protectedHeadersJSON having 'epk' with invalid json format", func(t *testing.T) { 371 err := jwkMarshalEPK(map[string]json.RawMessage{HeaderEPK: []byte("badjsonunmarshal")}) 372 require.EqualError(t, err, "unable to read JWK: invalid character 'b' looking for beginning of value") 373 }) 374 }