github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/jose/encrypter_decrypter_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_test
     8  
     9  import (
    10  	"bytes"
    11  	"crypto/ecdsa"
    12  	"crypto/ed25519"
    13  	"crypto/rand"
    14  	"crypto/rsa"
    15  	_ "embed"
    16  	"encoding/base64"
    17  	"encoding/json"
    18  	"fmt"
    19  	"math/big"
    20  	"strings"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/go-jose/go-jose/v3"
    25  	hybrid "github.com/google/tink/go/hybrid/subtle"
    26  	"github.com/google/tink/go/keyset"
    27  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    28  	"github.com/google/tink/go/subtle"
    29  	"github.com/stretchr/testify/require"
    30  
    31  	ecdhpb "github.com/hyperledger/aries-framework-go/component/kmscrypto/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
    32  	"github.com/hyperledger/aries-framework-go/component/kmscrypto/doc/jose/jwk"
    33  	"github.com/hyperledger/aries-framework-go/component/kmscrypto/doc/util/jwkkid"
    34  	cryptoapi "github.com/hyperledger/aries-framework-go/pkg/crypto"
    35  	"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto"
    36  	"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/ecdh"
    37  	"github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto/primitive/composite/keyio"
    38  	ariesjose "github.com/hyperledger/aries-framework-go/pkg/doc/jose"
    39  	"github.com/hyperledger/aries-framework-go/pkg/doc/jose/kid/resolver"
    40  	"github.com/hyperledger/aries-framework-go/pkg/doc/util/kmsdidkey"
    41  	"github.com/hyperledger/aries-framework-go/pkg/kms"
    42  	mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms"
    43  	mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage"
    44  )
    45  
    46  const (
    47  	// EnvelopeEncodingType representing the JWE 'Typ' protected type header for DIDComm V2 (example for tests).
    48  	EnvelopeEncodingType = "application/didcomm-encrypted+json"
    49  	// DIDCommContentEncodingType represent the JWE `Cty` protected type header for DIDComm V2 (example for tests).
    50  	DIDCommContentEncodingType = "application/didcomm-plain+json"
    51  
    52  	compactSerialization   = "Compact"
    53  	fullSerialization      = "Full"
    54  	flattenedSerialization = "Flattened"
    55  )
    56  
    57  //nolint:gocognit,gocyclo
    58  func TestJWEEncryptRoundTrip(t *testing.T) {
    59  	_, err := ariesjose.NewJWEEncrypt("", "", "", "", nil, nil, nil)
    60  	require.EqualError(t, err, "empty recipientsPubKeys list",
    61  		"NewJWEEncrypt should fail with empty recipientPubKeys")
    62  
    63  	singleRecipientNISTPKWError := "jwedecrypt: failed to unwrap cek: [unwrapKey: deriveKEKAndUnwrap:" +
    64  		" failed to AES unwrap key: go-jose/go-jose: key wrap input must be 8 byte blocks]"
    65  
    66  	singleRecipientX25519KWError := "jwedecrypt: failed to unwrap cek: [unwrapKey: deriveKEKAndUnwrap: failed to XC20P " +
    67  		"unwrap key: unwrap support: OKP unwrap invalid key]"
    68  
    69  	multiRecKWError := "jwedecrypt: failed to build recipients WK: unable to read " +
    70  		"JWK: invalid character 's' looking for beginning of value"
    71  
    72  	tests := []struct {
    73  		name             string
    74  		kt               *tinkpb.KeyTemplate
    75  		enc              ariesjose.EncAlg
    76  		keyType          kms.KeyType
    77  		recipientKWError string
    78  		nbRec            int
    79  		useCompact       bool
    80  	}{
    81  		{
    82  			name:             "P-256 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)",
    83  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
    84  			enc:              ariesjose.A256GCM,
    85  			keyType:          kms.NISTP256ECDHKWType,
    86  			nbRec:            2,
    87  			recipientKWError: multiRecKWError,
    88  		},
    89  		{
    90  			name:             "P-256 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)",
    91  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
    92  			enc:              ariesjose.A256GCM,
    93  			keyType:          kms.NISTP256ECDHKWType,
    94  			nbRec:            1,
    95  			recipientKWError: singleRecipientNISTPKWError,
    96  		},
    97  		{
    98  			name:             "P-256 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)",
    99  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   100  			enc:              ariesjose.A256GCM,
   101  			keyType:          kms.NISTP256ECDHKWType,
   102  			nbRec:            1,
   103  			useCompact:       true,
   104  			recipientKWError: singleRecipientNISTPKWError,
   105  		},
   106  		{
   107  			name:             "P-384 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)",
   108  			kt:               ecdh.NISTP384ECDHKWKeyTemplate(),
   109  			enc:              ariesjose.A256GCM,
   110  			keyType:          kms.NISTP384ECDHKWType,
   111  			nbRec:            2,
   112  			recipientKWError: multiRecKWError,
   113  		},
   114  		{
   115  			name:             "P-384 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)",
   116  			kt:               ecdh.NISTP384ECDHKWKeyTemplate(),
   117  			enc:              ariesjose.A256GCM,
   118  			keyType:          kms.NISTP384ECDHKWType,
   119  			nbRec:            1,
   120  			recipientKWError: singleRecipientNISTPKWError,
   121  		},
   122  		{
   123  			name:             "P-384 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)",
   124  			kt:               ecdh.NISTP384ECDHKWKeyTemplate(),
   125  			enc:              ariesjose.A256GCM,
   126  			keyType:          kms.NISTP384ECDHKWType,
   127  			nbRec:            1,
   128  			useCompact:       true,
   129  			recipientKWError: singleRecipientNISTPKWError,
   130  		},
   131  		{
   132  			name:             "P-521 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)",
   133  			kt:               ecdh.NISTP521ECDHKWKeyTemplate(),
   134  			enc:              ariesjose.A256GCM,
   135  			keyType:          kms.NISTP521ECDHKWType,
   136  			nbRec:            2,
   137  			recipientKWError: multiRecKWError,
   138  		},
   139  		{
   140  			name:             "P-521 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)",
   141  			kt:               ecdh.NISTP521ECDHKWKeyTemplate(),
   142  			enc:              ariesjose.A256GCM,
   143  			keyType:          kms.NISTP521ECDHKWType,
   144  			nbRec:            1,
   145  			recipientKWError: singleRecipientNISTPKWError,
   146  		},
   147  		{
   148  			name:             "P-521 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)",
   149  			kt:               ecdh.NISTP521ECDHKWKeyTemplate(),
   150  			enc:              ariesjose.A256GCM,
   151  			keyType:          kms.NISTP521ECDHKWType,
   152  			nbRec:            1,
   153  			useCompact:       true,
   154  			recipientKWError: singleRecipientNISTPKWError,
   155  		},
   156  		{
   157  			name:             "X25519 ECDH KW and AES256GCM encryption with 2 recipients (Full serialization)",
   158  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   159  			enc:              ariesjose.A256GCM,
   160  			keyType:          kms.X25519ECDHKWType,
   161  			nbRec:            2,
   162  			recipientKWError: multiRecKWError,
   163  		},
   164  		{
   165  			name:             "X25519 ECDH KW and AES256GCM encryption with 1 recipient (Flattened serialization)",
   166  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   167  			enc:              ariesjose.A256GCM,
   168  			keyType:          kms.X25519ECDHKWType,
   169  			nbRec:            1,
   170  			recipientKWError: singleRecipientX25519KWError,
   171  		},
   172  		{
   173  			name:             "X25519 ECDH KW and AES256GCM encryption with 1 recipient (Compact serialization)",
   174  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   175  			enc:              ariesjose.A256GCM,
   176  			keyType:          kms.X25519ECDHKWType,
   177  			nbRec:            1,
   178  			useCompact:       true,
   179  			recipientKWError: singleRecipientX25519KWError,
   180  		},
   181  		{
   182  			name:             "P-256 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
   183  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   184  			enc:              ariesjose.XC20P,
   185  			keyType:          kms.NISTP256ECDHKWType,
   186  			nbRec:            2,
   187  			recipientKWError: multiRecKWError,
   188  		},
   189  		{
   190  			name:             "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
   191  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   192  			enc:              ariesjose.XC20P,
   193  			keyType:          kms.NISTP256ECDHKWType,
   194  			nbRec:            1,
   195  			recipientKWError: singleRecipientNISTPKWError,
   196  		},
   197  		{
   198  			name:             "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
   199  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   200  			enc:              ariesjose.XC20P,
   201  			keyType:          kms.NISTP256ECDHKWType,
   202  			nbRec:            1,
   203  			useCompact:       true,
   204  			recipientKWError: singleRecipientNISTPKWError,
   205  		},
   206  		{
   207  			name:             "P-384 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
   208  			kt:               ecdh.NISTP384ECDHKWKeyTemplate(),
   209  			enc:              ariesjose.XC20P,
   210  			keyType:          kms.NISTP384ECDHKWType,
   211  			nbRec:            2,
   212  			recipientKWError: multiRecKWError,
   213  		},
   214  		{
   215  			name:             "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
   216  			kt:               ecdh.NISTP384ECDHKWKeyTemplate(),
   217  			enc:              ariesjose.XC20P,
   218  			keyType:          kms.NISTP384ECDHKWType,
   219  			nbRec:            1,
   220  			recipientKWError: singleRecipientNISTPKWError,
   221  		},
   222  		{
   223  			name:             "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
   224  			kt:               ecdh.NISTP384ECDHKWKeyTemplate(),
   225  			enc:              ariesjose.XC20P,
   226  			keyType:          kms.NISTP384ECDHKWType,
   227  			nbRec:            1,
   228  			useCompact:       true,
   229  			recipientKWError: singleRecipientNISTPKWError,
   230  		},
   231  		{
   232  			name:             "P-521 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
   233  			kt:               ecdh.NISTP521ECDHKWKeyTemplate(),
   234  			enc:              ariesjose.XC20P,
   235  			keyType:          kms.NISTP521ECDHKWType,
   236  			nbRec:            2,
   237  			recipientKWError: multiRecKWError,
   238  		},
   239  		{
   240  			name:             "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
   241  			kt:               ecdh.NISTP521ECDHKWKeyTemplate(),
   242  			enc:              ariesjose.XC20P,
   243  			keyType:          kms.NISTP521ECDHKWType,
   244  			nbRec:            1,
   245  			recipientKWError: singleRecipientNISTPKWError,
   246  		},
   247  		{
   248  			name:             "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
   249  			kt:               ecdh.NISTP521ECDHKWKeyTemplate(),
   250  			enc:              ariesjose.XC20P,
   251  			keyType:          kms.NISTP521ECDHKWType,
   252  			nbRec:            1,
   253  			useCompact:       true,
   254  			recipientKWError: singleRecipientNISTPKWError,
   255  		},
   256  		{
   257  			name:             "X25519 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
   258  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   259  			enc:              ariesjose.XC20P,
   260  			keyType:          kms.X25519ECDHKWType,
   261  			nbRec:            2,
   262  			recipientKWError: multiRecKWError,
   263  		},
   264  		{
   265  			name:             "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
   266  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   267  			enc:              ariesjose.XC20P,
   268  			keyType:          kms.X25519ECDHKWType,
   269  			nbRec:            1,
   270  			recipientKWError: singleRecipientX25519KWError,
   271  		},
   272  		{
   273  			name:             "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
   274  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   275  			enc:              ariesjose.XC20P,
   276  			keyType:          kms.X25519ECDHKWType,
   277  			nbRec:            1,
   278  			useCompact:       true,
   279  			recipientKWError: singleRecipientX25519KWError,
   280  		},
   281  		{
   282  			name:             "P-256 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)",
   283  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   284  			enc:              ariesjose.A128CBCHS256,
   285  			keyType:          kms.NISTP256ECDHKWType,
   286  			nbRec:            2,
   287  			recipientKWError: multiRecKWError,
   288  		},
   289  		{
   290  			name:             "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)",
   291  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   292  			enc:              ariesjose.A128CBCHS256,
   293  			keyType:          kms.NISTP256ECDHKWType,
   294  			nbRec:            1,
   295  			recipientKWError: singleRecipientNISTPKWError,
   296  		},
   297  		{
   298  			name:             "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)",
   299  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   300  			enc:              ariesjose.A128CBCHS256,
   301  			keyType:          kms.NISTP256ECDHKWType,
   302  			nbRec:            1,
   303  			useCompact:       true,
   304  			recipientKWError: singleRecipientNISTPKWError,
   305  		},
   306  		{
   307  			name:             "X25519 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)",
   308  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   309  			enc:              ariesjose.A128CBCHS256,
   310  			keyType:          kms.X25519ECDHKWType,
   311  			nbRec:            2,
   312  			recipientKWError: multiRecKWError,
   313  		},
   314  		{
   315  			name:             "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)",
   316  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   317  			enc:              ariesjose.A128CBCHS256,
   318  			keyType:          kms.X25519ECDHKWType,
   319  			nbRec:            1,
   320  			recipientKWError: singleRecipientX25519KWError,
   321  		},
   322  		{
   323  			name:             "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)",
   324  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   325  			enc:              ariesjose.A128CBCHS256,
   326  			keyType:          kms.X25519ECDHKWType,
   327  			nbRec:            1,
   328  			useCompact:       true,
   329  			recipientKWError: singleRecipientX25519KWError,
   330  		},
   331  		{
   332  			name:             "P-256 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)",
   333  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   334  			enc:              ariesjose.A192CBCHS384,
   335  			keyType:          kms.NISTP256ECDHKWType,
   336  			nbRec:            2,
   337  			recipientKWError: multiRecKWError,
   338  		},
   339  		{
   340  			name:             "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)",
   341  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   342  			enc:              ariesjose.A192CBCHS384,
   343  			keyType:          kms.NISTP256ECDHKWType,
   344  			nbRec:            1,
   345  			recipientKWError: singleRecipientNISTPKWError,
   346  		},
   347  		{
   348  			name:             "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)",
   349  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   350  			enc:              ariesjose.A192CBCHS384,
   351  			keyType:          kms.NISTP256ECDHKWType,
   352  			nbRec:            1,
   353  			useCompact:       true,
   354  			recipientKWError: singleRecipientNISTPKWError,
   355  		},
   356  		{
   357  			name:             "X25519 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)",
   358  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   359  			enc:              ariesjose.A192CBCHS384,
   360  			keyType:          kms.X25519ECDHKWType,
   361  			nbRec:            2,
   362  			recipientKWError: multiRecKWError,
   363  		},
   364  		{
   365  			name:             "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)",
   366  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   367  			enc:              ariesjose.A192CBCHS384,
   368  			keyType:          kms.X25519ECDHKWType,
   369  			nbRec:            1,
   370  			recipientKWError: singleRecipientX25519KWError,
   371  		},
   372  		{
   373  			name:             "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)",
   374  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   375  			enc:              ariesjose.A192CBCHS384,
   376  			keyType:          kms.X25519ECDHKWType,
   377  			nbRec:            1,
   378  			useCompact:       true,
   379  			recipientKWError: singleRecipientX25519KWError,
   380  		},
   381  		{
   382  			name:             "P-256 ECDH KW and A256CBCHS384 encryption with 2 recipients (Full serialization)",
   383  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   384  			enc:              ariesjose.A256CBCHS384,
   385  			keyType:          kms.NISTP256ECDHKWType,
   386  			nbRec:            2,
   387  			recipientKWError: multiRecKWError,
   388  		},
   389  		{
   390  			name:             "P-256 ECDH KW and A256CBCHS384 encryption with 1 recipient (Flattened serialization)",
   391  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   392  			enc:              ariesjose.A256CBCHS384,
   393  			keyType:          kms.NISTP256ECDHKWType,
   394  			nbRec:            1,
   395  			recipientKWError: singleRecipientNISTPKWError,
   396  		},
   397  		{
   398  			name:             "P-256 ECDH KW and A256CBCHS384 encryption with 1 recipient (Compact serialization)",
   399  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   400  			enc:              ariesjose.A256CBCHS384,
   401  			keyType:          kms.NISTP256ECDHKWType,
   402  			nbRec:            1,
   403  			useCompact:       true,
   404  			recipientKWError: singleRecipientNISTPKWError,
   405  		},
   406  		{
   407  			name:             "X25519 ECDH KW and A256CBCHS384 encryption with 2 recipients (Full serialization)",
   408  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   409  			enc:              ariesjose.A256CBCHS384,
   410  			keyType:          kms.X25519ECDHKWType,
   411  			nbRec:            2,
   412  			recipientKWError: multiRecKWError,
   413  		},
   414  		{
   415  			name:             "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Flattened serialization)",
   416  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   417  			enc:              ariesjose.A256CBCHS384,
   418  			keyType:          kms.X25519ECDHKWType,
   419  			nbRec:            1,
   420  			recipientKWError: singleRecipientX25519KWError,
   421  		},
   422  		{
   423  			name:             "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Compact serialization)",
   424  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   425  			enc:              ariesjose.A256CBCHS384,
   426  			keyType:          kms.X25519ECDHKWType,
   427  			nbRec:            1,
   428  			useCompact:       true,
   429  			recipientKWError: singleRecipientX25519KWError,
   430  		},
   431  		{
   432  			name:             "P-256 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)",
   433  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   434  			enc:              ariesjose.A256CBCHS512,
   435  			keyType:          kms.NISTP256ECDHKWType,
   436  			nbRec:            2,
   437  			recipientKWError: multiRecKWError,
   438  		},
   439  		{
   440  			name:             "P-256 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)",
   441  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   442  			enc:              ariesjose.A256CBCHS512,
   443  			keyType:          kms.NISTP256ECDHKWType,
   444  			nbRec:            1,
   445  			recipientKWError: singleRecipientNISTPKWError,
   446  		},
   447  		{
   448  			name:             "P-256 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)",
   449  			kt:               ecdh.NISTP256ECDHKWKeyTemplate(),
   450  			enc:              ariesjose.A256CBCHS512,
   451  			keyType:          kms.NISTP256ECDHKWType,
   452  			nbRec:            1,
   453  			useCompact:       true,
   454  			recipientKWError: singleRecipientNISTPKWError,
   455  		},
   456  		{
   457  			name:             "X25519 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)",
   458  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   459  			enc:              ariesjose.A256CBCHS512,
   460  			keyType:          kms.X25519ECDHKWType,
   461  			nbRec:            2,
   462  			recipientKWError: multiRecKWError,
   463  		},
   464  		{
   465  			name:             "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)",
   466  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   467  			enc:              ariesjose.A256CBCHS512,
   468  			keyType:          kms.X25519ECDHKWType,
   469  			nbRec:            1,
   470  			recipientKWError: singleRecipientX25519KWError,
   471  		},
   472  		{
   473  			name:             "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)",
   474  			kt:               ecdh.X25519ECDHKWKeyTemplate(),
   475  			enc:              ariesjose.A256CBCHS512,
   476  			keyType:          kms.X25519ECDHKWType,
   477  			nbRec:            1,
   478  			useCompact:       true,
   479  			recipientKWError: singleRecipientX25519KWError,
   480  		},
   481  	}
   482  
   483  	for _, tt := range tests {
   484  		tc := tt
   485  		t.Run(tc.name, func(t *testing.T) {
   486  			t.Log("creating recipients keys..")
   487  			recECKeys, recKHs, _, recDIDKeys := createRecipientsByKeyTemplate(t, tc.nbRec, tc.kt, tc.keyType)
   488  
   489  			cryptoSvc, kmsSvc := createCryptoAndKMSServices(t, recKHs)
   490  
   491  			_, err = ariesjose.NewJWEEncrypt("", "", "", "", nil, recECKeys, cryptoSvc)
   492  			require.EqualError(t, err, "encryption algorithm '' not supported",
   493  				"NewJWEEncrypt should fail with empty encAlg")
   494  
   495  			jweEncrypter, err := ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType,
   496  				DIDCommContentEncodingType, "", nil, recECKeys, cryptoSvc)
   497  			require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys")
   498  
   499  			pt := []byte("secret message")
   500  			aad := []byte("aad value")
   501  
   502  			if tc.useCompact { // compact serialization does not use AAD
   503  				aad = nil
   504  			}
   505  
   506  			testEncTime := time.Now()
   507  			jwe, err := jweEncrypter.EncryptWithAuthData(pt, aad)
   508  			t.Logf("ECDH-ES KW in EncryptWithAuthData took %v", time.Since(testEncTime))
   509  			require.NoError(t, err)
   510  			require.Equal(t, len(recECKeys), len(jwe.Recipients))
   511  
   512  			cty, ok := jwe.ProtectedHeaders.ContentType()
   513  			require.True(t, ok)
   514  			require.Equal(t, DIDCommContentEncodingType, cty)
   515  
   516  			typ, ok := jwe.ProtectedHeaders.Type()
   517  			require.True(t, ok)
   518  			require.Equal(t, EnvelopeEncodingType, typ)
   519  
   520  			alg, ok := jwe.ProtectedHeaders.Algorithm()
   521  			if alg != "" {
   522  				require.True(t, ok)
   523  				require.Contains(t, []string{"ECDH-ES+A256KW", "ECDH-ES+XC20PKW"}, alg)
   524  			} else {
   525  				require.False(t, ok)
   526  			}
   527  
   528  			kid, ok := jwe.ProtectedHeaders.KeyID()
   529  			if kid != "" {
   530  				require.True(t, ok)
   531  				require.NotEmpty(t, kid)
   532  			} else {
   533  				require.False(t, ok)
   534  			}
   535  
   536  			var serializedJWE, jweStr string
   537  			serialization := fullSerialization
   538  
   539  			if tc.useCompact {
   540  				testSerTime := time.Now()
   541  				serializedJWE, err = jwe.CompactSerialize(json.Marshal)
   542  				t.Logf("CompactSerilize took %v", time.Since(testSerTime))
   543  				require.NoError(t, err)
   544  				require.NotEmpty(t, serializedJWE)
   545  
   546  				jweStr = serializedJWE
   547  				serialization = compactSerialization
   548  			} else {
   549  				testSerTime := time.Now()
   550  				serializedJWE, err = jwe.FullSerialize(json.Marshal)
   551  				t.Logf("JSON Serialize took %v", time.Since(testSerTime))
   552  				require.NoError(t, err)
   553  				require.NotEmpty(t, serializedJWE)
   554  
   555  				jweStr, err = prettyPrint([]byte(serializedJWE))
   556  				require.NoError(t, err)
   557  				if tc.nbRec == 1 {
   558  					serialization = flattenedSerialization
   559  				}
   560  			}
   561  
   562  			t.Logf("* anoncrypt JWE (%s serialization): %s", serialization, jweStr)
   563  
   564  			mPh, err := json.Marshal(jwe.ProtectedHeaders)
   565  			require.NoError(t, err)
   566  
   567  			protectedHeadersStr, err := prettyPrint(mPh)
   568  			require.NoError(t, err)
   569  
   570  			t.Logf("* protected headers: %s", protectedHeadersStr)
   571  
   572  			// try to deserialize with go-jose (can't decrypt in go-jose since private key is protected by Tink)
   573  			joseJWE, err := jose.ParseEncrypted(serializedJWE)
   574  			require.NoError(t, err)
   575  			require.NotEmpty(t, joseJWE)
   576  
   577  			// try to deserialize with local package
   578  			testDeserTime := time.Now()
   579  			localJWE, err := ariesjose.Deserialize(serializedJWE)
   580  			t.Logf("JWE Deserialize took %v", time.Since(testDeserTime))
   581  			require.NoError(t, err)
   582  
   583  			t.Run("Decrypting JWE tests failures", func(t *testing.T) {
   584  				jweDecrypter := ariesjose.NewJWEDecrypt(nil, cryptoSvc, kmsSvc)
   585  
   586  				// decrypt empty JWE
   587  				_, err = jweDecrypter.Decrypt(nil)
   588  				require.EqualError(t, err, "jwedecrypt: jwe is nil")
   589  
   590  				var badJWE *ariesjose.JSONWebEncryption
   591  
   592  				badJWE, err = ariesjose.Deserialize(serializedJWE)
   593  				require.NoError(t, err)
   594  
   595  				ph := badJWE.ProtectedHeaders
   596  				badJWE.ProtectedHeaders = nil
   597  
   598  				// decrypt JWE with empty ProtectHeaders
   599  				_, err = jweDecrypter.Decrypt(badJWE)
   600  				require.EqualError(t, err, "jwedecrypt: jwe is missing protected headers")
   601  
   602  				badJWE.ProtectedHeaders = ariesjose.Headers{}
   603  				badJWE.ProtectedHeaders["somKey"] = "badKey"
   604  				_, err = jweDecrypter.Decrypt(badJWE)
   605  				require.EqualError(t, err, "jwedecrypt: jwe is missing encryption algorithm 'enc' header")
   606  
   607  				badJWE.ProtectedHeaders = map[string]interface{}{
   608  					ariesjose.HeaderEncryption: "badEncHeader",
   609  					ariesjose.HeaderType:       "test",
   610  				}
   611  
   612  				// decrypt JWE with bad Enc header value
   613  				_, err = jweDecrypter.Decrypt(badJWE)
   614  				require.EqualError(t, err, "jwedecrypt: encryption algorithm 'badEncHeader' not supported")
   615  
   616  				badJWE.ProtectedHeaders = ph
   617  
   618  				// decrypt JWE with invalid recipient key
   619  				badJWE.Recipients = []*ariesjose.Recipient{
   620  					{
   621  						EncryptedKey: "someKey",
   622  						Header: &ariesjose.RecipientHeaders{
   623  							EPK: []byte("somerawbytes"),
   624  						},
   625  					},
   626  				}
   627  
   628  				if tc.nbRec > 1 {
   629  					badJWE.Recipients = append(badJWE.Recipients, &ariesjose.Recipient{
   630  						EncryptedKey: "someOtherKey",
   631  						Header: &ariesjose.RecipientHeaders{
   632  							EPK: []byte("someotherrawbytes"),
   633  						},
   634  					})
   635  				}
   636  
   637  				_, err = jweDecrypter.Decrypt(badJWE)
   638  				require.EqualError(t, err, tc.recipientKWError)
   639  
   640  				// decrypt JWE with unsupported recipient key
   641  				var privKey *rsa.PrivateKey
   642  
   643  				privKey, err = rsa.GenerateKey(rand.Reader, 2048)
   644  
   645  				unsupportedJWK := jwk.JWK{
   646  					JSONWebKey: jose.JSONWebKey{
   647  						Key: &privKey.PublicKey,
   648  					},
   649  				}
   650  
   651  				var mk []byte
   652  
   653  				mk, err = unsupportedJWK.MarshalJSON()
   654  				require.NoError(t, err)
   655  
   656  				badJWE.Recipients = []*ariesjose.Recipient{
   657  					{
   658  						EncryptedKey: "someKey",
   659  						Header: &ariesjose.RecipientHeaders{
   660  							EPK: mk,
   661  						},
   662  					},
   663  				}
   664  
   665  				if tc.nbRec > 1 {
   666  					badJWE.Recipients = append(badJWE.Recipients, &ariesjose.Recipient{
   667  						EncryptedKey: "someOtherKey",
   668  						Header: &ariesjose.RecipientHeaders{
   669  							EPK: mk,
   670  						},
   671  					})
   672  				}
   673  
   674  				_, err = jweDecrypter.Decrypt(badJWE)
   675  				if tc.nbRec == 1 {
   676  					require.EqualError(t, err, tc.recipientKWError)
   677  				} else {
   678  					require.EqualError(t, err, "jwedecrypt: failed to build recipients WK: unsupported recipient key type")
   679  				}
   680  			})
   681  
   682  			t.Run("Decrypting JWE test success ", func(t *testing.T) {
   683  				jweDecrypter := ariesjose.NewJWEDecrypt(nil, cryptoSvc, kmsSvc)
   684  
   685  				var msg []byte
   686  
   687  				testDecTime := time.Now()
   688  				msg, err = jweDecrypter.Decrypt(localJWE)
   689  				t.Logf("JWE Decrypt took %v", time.Since(testDecTime))
   690  				require.NoError(t, err)
   691  				require.EqualValues(t, pt, msg)
   692  			})
   693  
   694  			t.Run("ECDH-ES Encrypt and Decrypt JWE test success with kid as did:key", func(t *testing.T) {
   695  				recKeys := make([]*cryptoapi.PublicKey, 0)
   696  				for i, k := range recECKeys {
   697  					k.KID = recDIDKeys[i]
   698  					recKeys = append(recKeys, k)
   699  				}
   700  
   701  				jweEncrypter, err = ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType,
   702  					DIDCommContentEncodingType, "", nil, recKeys, cryptoSvc)
   703  				require.NoError(t, err)
   704  
   705  				testEncTime = time.Now()
   706  				jwe, err = jweEncrypter.EncryptWithAuthData(pt, aad)
   707  				t.Logf("ECDH-ES KW in EncryptWithAuthData with kid as did:key took %v", time.Since(testEncTime))
   708  				require.NoError(t, err)
   709  				require.Equal(t, len(recECKeys), len(jwe.Recipients))
   710  
   711  				if tc.useCompact {
   712  					testSerTime := time.Now()
   713  					serializedJWE, err = jwe.CompactSerialize(json.Marshal)
   714  					t.Logf("CompactSerilize JWE with as did:key took %v", time.Since(testSerTime))
   715  					require.NoError(t, err)
   716  					require.NotEmpty(t, serializedJWE)
   717  
   718  					jweStr = serializedJWE
   719  					serialization = compactSerialization
   720  				} else {
   721  					testSerTime := time.Now()
   722  					serializedJWE, err = jwe.FullSerialize(json.Marshal)
   723  					t.Logf("JSON Serialize with kid as did:key took %v", time.Since(testSerTime))
   724  					require.NoError(t, err)
   725  					require.NotEmpty(t, serializedJWE)
   726  
   727  					jweStr, err = prettyPrint([]byte(serializedJWE))
   728  					require.NoError(t, err)
   729  					if tc.nbRec == 1 {
   730  						serialization = flattenedSerialization
   731  					}
   732  				}
   733  
   734  				t.Logf("* anoncrypt JWE (%s serialization) with kid as did:key: %s", serialization, jweStr)
   735  
   736  				// try to deserialize with go-jose (can't decrypt in go-jose since private key is protected by Tink)
   737  				joseJWE, err := jose.ParseEncrypted(serializedJWE)
   738  				require.NoError(t, err)
   739  				require.NotEmpty(t, joseJWE)
   740  
   741  				// try to deserialize with local package
   742  				testDeserTime := time.Now()
   743  				localJWE, err = ariesjose.Deserialize(serializedJWE)
   744  				t.Logf("JWE with kid as did:key Deserialize took %v", time.Since(testDeserTime))
   745  				require.NoError(t, err)
   746  
   747  				jweDecrypter := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{&resolver.DIDKeyResolver{}}, cryptoSvc, kmsSvc)
   748  
   749  				var msg []byte
   750  
   751  				testDecTime := time.Now()
   752  				msg, err = jweDecrypter.Decrypt(localJWE)
   753  				t.Logf("JWE with kid as did:key Decrypt took %v", time.Since(testDecTime))
   754  				require.NoError(t, err)
   755  				require.EqualValues(t, pt, msg)
   756  
   757  				if tc.nbRec > 1 {
   758  					t.Run("decrypt with failing kid resolver", func(t *testing.T) {
   759  						failingResolver := &mockResolver{resolveError: fmt.Errorf("resolve kid failure")}
   760  						jweDecrypter := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{failingResolver}, cryptoSvc, kmsSvc)
   761  
   762  						_, err = jweDecrypter.Decrypt(localJWE)
   763  						require.EqualError(t, err, "jwedecrypt: failed to unwrap cek: [resolveKID: "+
   764  							"[resolve kid failure] resolveKID: [resolve kid failure]]")
   765  					})
   766  				}
   767  			})
   768  		})
   769  	}
   770  }
   771  
   772  type mockResolver struct {
   773  	resolveValue *cryptoapi.PublicKey
   774  	resolveError error
   775  }
   776  
   777  func (m *mockResolver) Resolve(kid string) (*cryptoapi.PublicKey, error) {
   778  	return m.resolveValue, m.resolveError
   779  }
   780  
   781  func TestInteropWithGoJoseEncryptAndLocalJoseDecryptUsingCompactSerialize(t *testing.T) {
   782  	recECKeys, recKHs, recKIDs, _ := createRecipients(t, 1)
   783  	gjRecipients := convertToGoJoseRecipients(t, recECKeys, recKIDs)
   784  
   785  	c, k := createCryptoAndKMSServices(t, recKHs)
   786  
   787  	eo := &jose.EncrypterOptions{}
   788  	gjEncrypter, err := jose.NewEncrypter(jose.A256GCM, gjRecipients[0],
   789  		eo.WithType(EnvelopeEncodingType))
   790  	require.NoError(t, err)
   791  
   792  	pt := []byte("Test secret message")
   793  
   794  	// encrypt pt using go-jose encryption
   795  	gjJWEEncrypter, err := gjEncrypter.Encrypt(pt)
   796  	require.NoError(t, err)
   797  
   798  	// get go-jose serialized JWE
   799  	gjSerializedJWE, err := gjJWEEncrypter.CompactSerialize()
   800  	require.NoError(t, err)
   801  
   802  	// deserialize using local jose package
   803  	localJWE, err := ariesjose.Deserialize(gjSerializedJWE)
   804  	require.NoError(t, err)
   805  
   806  	t.Run("Decrypting JWE message encrypted by go-jose test success", func(t *testing.T) {
   807  		jweDecrypter := ariesjose.NewJWEDecrypt(nil, c, k)
   808  
   809  		var msg []byte
   810  
   811  		msg, err = jweDecrypter.Decrypt(localJWE)
   812  		require.NoError(t, err)
   813  		require.EqualValues(t, pt, msg)
   814  	})
   815  }
   816  
   817  func TestInteropWithGoJoseEncryptAndLocalJoseDecrypt(t *testing.T) {
   818  	recECKeys, recKHs, recKIDs, _ := createRecipients(t, 3)
   819  	gjRecipients := convertToGoJoseRecipients(t, recECKeys, recKIDs)
   820  
   821  	c, k := createCryptoAndKMSServices(t, recKHs)
   822  
   823  	eo := &jose.EncrypterOptions{}
   824  	gjEncrypter, err := jose.NewMultiEncrypter(jose.A256GCM, gjRecipients,
   825  		eo.WithType(EnvelopeEncodingType))
   826  	require.NoError(t, err)
   827  
   828  	pt := []byte("Test secret message")
   829  	aad := []byte("Test some auth data")
   830  
   831  	// encrypt pt using go-jose encryption
   832  	gjJWEEncrypter, err := gjEncrypter.EncryptWithAuthData(pt, aad)
   833  	require.NoError(t, err)
   834  
   835  	// get go-jose serialized JWE
   836  	gjSerializedJWE := gjJWEEncrypter.FullSerialize()
   837  
   838  	// deserialize using local jose package
   839  	localJWE, err := ariesjose.Deserialize(gjSerializedJWE)
   840  	require.NoError(t, err)
   841  
   842  	t.Run("Decrypting JWE message encrypted by go-jose test success", func(t *testing.T) {
   843  		jweDecrypter := ariesjose.NewJWEDecrypt(nil, c, k)
   844  
   845  		var msg []byte
   846  
   847  		msg, err = jweDecrypter.Decrypt(localJWE)
   848  		require.NoError(t, err)
   849  		require.EqualValues(t, pt, msg)
   850  	})
   851  }
   852  
   853  func TestInteropWithLocalJoseEncryptAndGoJoseDecrypt(t *testing.T) {
   854  	c, err := tinkcrypto.New()
   855  	require.NoError(t, err)
   856  
   857  	// get two generated recipient Tink keys
   858  	recECKeys, _, _, _ := createRecipients(t, 2) //nolint:dogsled
   859  	// create a normal recipient key (not using Tink)
   860  	rec3PrivKey, err := ecdsa.GenerateKey(subtle.GetCurve(recECKeys[0].Curve), rand.Reader)
   861  	require.NoError(t, err)
   862  
   863  	// add third key to recECKeys
   864  	recECKeys = append(recECKeys, &cryptoapi.PublicKey{
   865  		X:     rec3PrivKey.PublicKey.X.Bytes(),
   866  		Y:     rec3PrivKey.PublicKey.Y.Bytes(),
   867  		Curve: rec3PrivKey.PublicKey.Curve.Params().Name,
   868  		Type:  "EC",
   869  	})
   870  
   871  	// encrypt using local jose package
   872  	jweEncrypter, err := ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType,
   873  		"", nil, recECKeys, c)
   874  	require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys")
   875  
   876  	pt := []byte("some msg")
   877  	jwe, err := jweEncrypter.EncryptWithAuthData(pt, []byte("aad value"))
   878  	require.NoError(t, err)
   879  	require.Equal(t, len(recECKeys), len(jwe.Recipients))
   880  
   881  	serializedJWE, err := jwe.FullSerialize(json.Marshal)
   882  	require.NoError(t, err)
   883  
   884  	// now parse serializedJWE using go-jose
   885  	gjParsedJWE, err := jose.ParseEncrypted(serializedJWE)
   886  	require.NoError(t, err)
   887  
   888  	// Decrypt with third recipient's private key (non Tink key)
   889  	i, _, msg, err := gjParsedJWE.DecryptMulti(rec3PrivKey)
   890  	require.NoError(t, err)
   891  	require.EqualValues(t, pt, msg)
   892  
   893  	// the third recipient's index is 2
   894  	require.Equal(t, 2, i)
   895  }
   896  
   897  func TestInteropWithLocalJoseEncryptAndGoJoseDecryptUsingCompactSerialization(t *testing.T) {
   898  	var recECKeys []*cryptoapi.PublicKey
   899  	// create a normal recipient key (not using Tink)
   900  	recPrivKey, err := ecdsa.GenerateKey(subtle.GetCurve("NIST_P256"), rand.Reader)
   901  	require.NoError(t, err)
   902  
   903  	c, err := tinkcrypto.New()
   904  	require.NoError(t, err)
   905  
   906  	recECKeys = append(recECKeys, &cryptoapi.PublicKey{
   907  		X:     recPrivKey.PublicKey.X.Bytes(),
   908  		Y:     recPrivKey.PublicKey.Y.Bytes(),
   909  		Curve: recPrivKey.PublicKey.Curve.Params().Name,
   910  		Type:  "EC",
   911  	})
   912  
   913  	// encrypt using local jose package
   914  	jweEncrypter, err := ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType,
   915  		"", nil, recECKeys, c)
   916  	require.NoError(t, err, "NewJWEEncrypt should not fail with non empty recipientPubKeys")
   917  
   918  	pt := []byte("some msg")
   919  	jwe, err := jweEncrypter.Encrypt(pt)
   920  	require.NoError(t, err)
   921  	require.Equal(t, len(recECKeys), len(jwe.Recipients))
   922  
   923  	serializedJWE, err := jwe.CompactSerialize(json.Marshal)
   924  	require.NoError(t, err)
   925  
   926  	// now parse serializedJWE using go-jose
   927  	gjParsedJWE, err := jose.ParseEncrypted(serializedJWE)
   928  	require.NoError(t, err)
   929  
   930  	// Decrypt with recipient's private key
   931  	msg, err := gjParsedJWE.Decrypt(recPrivKey)
   932  	require.NoError(t, err)
   933  	require.EqualValues(t, pt, msg)
   934  }
   935  
   936  func convertToGoJoseRecipients(t *testing.T, keys []*cryptoapi.PublicKey, kids []string) []jose.Recipient {
   937  	t.Helper()
   938  
   939  	var joseRecipients []jose.Recipient
   940  
   941  	for i, key := range keys {
   942  		c := subtle.GetCurve(key.Curve)
   943  		gjKey := jose.Recipient{
   944  			KeyID:     kids[i],
   945  			Algorithm: jose.ECDH_ES_A256KW,
   946  			Key: &ecdsa.PublicKey{
   947  				Curve: c,
   948  				X:     new(big.Int).SetBytes(key.X),
   949  				Y:     new(big.Int).SetBytes(key.Y),
   950  			},
   951  		}
   952  
   953  		joseRecipients = append(joseRecipients, gjKey)
   954  	}
   955  
   956  	return joseRecipients
   957  }
   958  
   959  func createRecipients(t *testing.T,
   960  	nbOfEntities int) ([]*cryptoapi.PublicKey, map[string]*keyset.Handle, []string, []string) {
   961  	return createRecipientsByKeyTemplate(t, nbOfEntities, ecdh.NISTP256ECDHKWKeyTemplate(), kms.NISTP256ECDHKWType)
   962  }
   963  
   964  // createRecipients and return their public key and keyset.Handle.
   965  func createRecipientsByKeyTemplate(t *testing.T, nbOfEntities int, kt *tinkpb.KeyTemplate,
   966  	keyType kms.KeyType) ([]*cryptoapi.PublicKey, map[string]*keyset.Handle, []string, []string) {
   967  	t.Helper()
   968  
   969  	r := make([]*cryptoapi.PublicKey, 0)
   970  	rKH := make(map[string]*keyset.Handle)
   971  	rKID := make([]string, 0)
   972  	rDIDKey := make([]string, 0)
   973  
   974  	for i := 0; i < nbOfEntities; i++ {
   975  		mrKey, kh, kid, didKey := createAndMarshalEntityKey(t, kt, keyType)
   976  
   977  		ecPubKey := new(cryptoapi.PublicKey)
   978  		err := json.Unmarshal(mrKey, ecPubKey)
   979  		require.NoError(t, err)
   980  
   981  		ecPubKey.KID = kid
   982  		rKH[kid] = kh
   983  
   984  		r = append(r, ecPubKey)
   985  		rKID = append(rKID, kid)
   986  		rDIDKey = append(rDIDKey, didKey)
   987  	}
   988  
   989  	return r, rKH, rKID, rDIDKey
   990  }
   991  
   992  // createAndMarshalEntityKey creates a new recipient keyset.Handle, extracts public key, marshals it and returns
   993  // both marshalled public key and original recipient keyset.Handle.
   994  func createAndMarshalEntityKey(t *testing.T, kt *tinkpb.KeyTemplate,
   995  	keyType kms.KeyType) ([]byte, *keyset.Handle, string, string) {
   996  	t.Helper()
   997  
   998  	kh, err := keyset.NewHandle(kt)
   999  	require.NoError(t, err)
  1000  
  1001  	pubKH, err := kh.Public()
  1002  	require.NoError(t, err)
  1003  
  1004  	buf := new(bytes.Buffer)
  1005  	pubKeyWriter := keyio.NewWriter(buf)
  1006  	require.NotEmpty(t, pubKeyWriter)
  1007  
  1008  	err = pubKH.WriteWithNoSecrets(pubKeyWriter)
  1009  	require.NoError(t, err)
  1010  
  1011  	mKeyBytes := buf.Bytes()
  1012  
  1013  	kid, err := jwkkid.CreateKID(mKeyBytes, keyType)
  1014  	require.NoError(t, err)
  1015  
  1016  	didKey, err := kmsdidkey.BuildDIDKeyByKeyType(mKeyBytes, keyType)
  1017  	require.NoError(t, err)
  1018  
  1019  	printKey(t, mKeyBytes, kid)
  1020  
  1021  	return mKeyBytes, kh, kid, didKey
  1022  }
  1023  
  1024  func printKey(t *testing.T, mPubKey []byte, kid string) {
  1025  	t.Helper()
  1026  
  1027  	pubKey := new(cryptoapi.PublicKey)
  1028  	err := json.Unmarshal(mPubKey, pubKey)
  1029  	require.NoError(t, err)
  1030  
  1031  	switch pubKey.Type {
  1032  	case ecdhpb.KeyType_EC.String():
  1033  		t.Logf("** EC key: %s, kid: %s", getPrintedECPubKey(t, pubKey), kid)
  1034  	case ecdhpb.KeyType_OKP.String():
  1035  		t.Logf("** X25519 key: %s, kid: %s", getPrintedX25519PubKey(t, pubKey), kid)
  1036  	default:
  1037  		t.Errorf("not supported key type: %s", pubKey.Type)
  1038  	}
  1039  }
  1040  
  1041  func prettyPrint(msg []byte) (string, error) {
  1042  	var prettyJSON bytes.Buffer
  1043  
  1044  	err := json.Indent(&prettyJSON, msg, "", "\t")
  1045  	if err != nil {
  1046  		return "", err
  1047  	}
  1048  
  1049  	return prettyJSON.String(), nil
  1050  }
  1051  
  1052  func getPrintedECPubKey(t *testing.T, pubKey *cryptoapi.PublicKey) string {
  1053  	crv, err := hybrid.GetCurve(pubKey.Curve)
  1054  	require.NoError(t, err)
  1055  
  1056  	j := jose.JSONWebKey{
  1057  		Key: &ecdsa.PublicKey{
  1058  			Curve: crv,
  1059  			X:     new(big.Int).SetBytes(pubKey.X),
  1060  			Y:     new(big.Int).SetBytes(pubKey.Y),
  1061  		},
  1062  	}
  1063  
  1064  	jwkByte, err := j.MarshalJSON()
  1065  	require.NoError(t, err)
  1066  	jwkStr, err := prettyPrint(jwkByte)
  1067  	require.NoError(t, err)
  1068  
  1069  	return jwkStr
  1070  }
  1071  
  1072  func getPrintedX25519PubKey(t *testing.T, pubKeyType *cryptoapi.PublicKey) string {
  1073  	j := jose.JSONWebKey{
  1074  		Key: ed25519.PublicKey(pubKeyType.X),
  1075  	}
  1076  
  1077  	jwkByte, err := j.MarshalJSON()
  1078  	require.NoError(t, err)
  1079  
  1080  	jwkStr, err := prettyPrint(jwkByte)
  1081  	require.NoError(t, err)
  1082  
  1083  	return strings.Replace(jwkStr, "Ed25519", "X25519", 1)
  1084  }
  1085  
  1086  func TestFailNewJWEEncrypt(t *testing.T) {
  1087  	c, err := tinkcrypto.New()
  1088  	require.NoError(t, err)
  1089  
  1090  	recipients, recsKH, kids, _ := createRecipients(t, 2)
  1091  
  1092  	t.Run("test with missing skid", func(t *testing.T) {
  1093  		_, err = ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType,
  1094  			"", recsKH[kids[0]], recipients, c)
  1095  		require.EqualError(t, err, "senderKID is required with senderKH")
  1096  	})
  1097  
  1098  	t.Run("test with missing crypto", func(t *testing.T) {
  1099  		_, err = ariesjose.NewJWEEncrypt(ariesjose.A256GCM, EnvelopeEncodingType, DIDCommContentEncodingType,
  1100  			kids[0], recsKH[kids[0]], recipients, nil)
  1101  		require.EqualError(t, err, "crypto service is required to create a JWEEncrypt instance")
  1102  	})
  1103  }
  1104  
  1105  //nolint:gocognit
  1106  func TestECDH1PU(t *testing.T) {
  1107  	tests := []struct {
  1108  		name       string
  1109  		kt         *tinkpb.KeyTemplate
  1110  		enc        ariesjose.EncAlg
  1111  		keyType    kms.KeyType
  1112  		nbRec      int
  1113  		useCompact bool
  1114  	}{
  1115  		{
  1116  			name:    "P-256 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
  1117  			kt:      ecdh.NISTP256ECDHKWKeyTemplate(),
  1118  			enc:     ariesjose.XC20P,
  1119  			keyType: kms.NISTP256ECDHKWType,
  1120  			nbRec:   2,
  1121  		},
  1122  		{
  1123  			name:    "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
  1124  			kt:      ecdh.NISTP256ECDHKWKeyTemplate(),
  1125  			enc:     ariesjose.XC20P,
  1126  			keyType: kms.NISTP256ECDHKWType,
  1127  			nbRec:   1,
  1128  		},
  1129  		{
  1130  			name:       "P-256 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
  1131  			kt:         ecdh.NISTP256ECDHKWKeyTemplate(),
  1132  			enc:        ariesjose.XC20P,
  1133  			keyType:    kms.NISTP256ECDHKWType,
  1134  			nbRec:      1,
  1135  			useCompact: true,
  1136  		},
  1137  		{
  1138  			name:    "P-384 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
  1139  			kt:      ecdh.NISTP384ECDHKWKeyTemplate(),
  1140  			enc:     ariesjose.XC20P,
  1141  			keyType: kms.NISTP384ECDHKWType,
  1142  			nbRec:   2,
  1143  		},
  1144  		{
  1145  			name:    "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
  1146  			kt:      ecdh.NISTP384ECDHKWKeyTemplate(),
  1147  			enc:     ariesjose.XC20P,
  1148  			keyType: kms.NISTP384ECDHKWType,
  1149  			nbRec:   1,
  1150  		},
  1151  		{
  1152  			name:       "P-384 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
  1153  			kt:         ecdh.NISTP384ECDHKWKeyTemplate(),
  1154  			enc:        ariesjose.XC20P,
  1155  			keyType:    kms.NISTP384ECDHKWType,
  1156  			nbRec:      1,
  1157  			useCompact: true,
  1158  		},
  1159  		{
  1160  			name:    "P-521 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
  1161  			kt:      ecdh.NISTP521ECDHKWKeyTemplate(),
  1162  			enc:     ariesjose.XC20P,
  1163  			keyType: kms.NISTP521ECDHKWType,
  1164  			nbRec:   2,
  1165  		},
  1166  		{
  1167  			name:    "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
  1168  			kt:      ecdh.NISTP521ECDHKWKeyTemplate(),
  1169  			enc:     ariesjose.XC20P,
  1170  			keyType: kms.NISTP521ECDHKWType,
  1171  			nbRec:   1,
  1172  		},
  1173  		{
  1174  			name:       "P-521 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
  1175  			kt:         ecdh.NISTP521ECDHKWKeyTemplate(),
  1176  			enc:        ariesjose.XC20P,
  1177  			keyType:    kms.NISTP521ECDHKWType,
  1178  			nbRec:      1,
  1179  			useCompact: true,
  1180  		},
  1181  		{
  1182  			name:    "X25519 ECDH KW and XChacha20Poly1305 encryption with 2 recipients (Full serialization)",
  1183  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1184  			enc:     ariesjose.XC20P,
  1185  			keyType: kms.X25519ECDHKWType,
  1186  			nbRec:   2,
  1187  		},
  1188  		{
  1189  			name:    "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Flattened serialization)",
  1190  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1191  			enc:     ariesjose.XC20P,
  1192  			keyType: kms.X25519ECDHKWType,
  1193  			nbRec:   1,
  1194  		},
  1195  		{
  1196  			name:       "X25519 ECDH KW and XChacha20Poly1305 encryption with 1 recipient (Compact serialization)",
  1197  			kt:         ecdh.X25519ECDHKWKeyTemplate(),
  1198  			enc:        ariesjose.XC20P,
  1199  			keyType:    kms.X25519ECDHKWType,
  1200  			nbRec:      1,
  1201  			useCompact: true,
  1202  		},
  1203  		{
  1204  			name:    "P-256 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)",
  1205  			kt:      ecdh.NISTP256ECDHKWKeyTemplate(),
  1206  			enc:     ariesjose.A128CBCHS256,
  1207  			keyType: kms.NISTP256ECDHKWType,
  1208  			nbRec:   2,
  1209  		},
  1210  		{
  1211  			name:    "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)",
  1212  			kt:      ecdh.NISTP256ECDHKWKeyTemplate(),
  1213  			enc:     ariesjose.A128CBCHS256,
  1214  			keyType: kms.NISTP256ECDHKWType,
  1215  			nbRec:   1,
  1216  		},
  1217  		{
  1218  			name:       "P-256 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)",
  1219  			kt:         ecdh.NISTP256ECDHKWKeyTemplate(),
  1220  			enc:        ariesjose.A128CBCHS256,
  1221  			keyType:    kms.NISTP256ECDHKWType,
  1222  			nbRec:      1,
  1223  			useCompact: true,
  1224  		},
  1225  		{
  1226  			name:    "X25519 ECDH KW and A128CBCHS256 encryption with 2 recipients (Full serialization)",
  1227  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1228  			enc:     ariesjose.A128CBCHS256,
  1229  			keyType: kms.X25519ECDHKWType,
  1230  			nbRec:   2,
  1231  		},
  1232  		{
  1233  			name:    "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Flattened serialization)",
  1234  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1235  			enc:     ariesjose.A128CBCHS256,
  1236  			keyType: kms.X25519ECDHKWType,
  1237  			nbRec:   1,
  1238  		},
  1239  		{
  1240  			name:       "X25519 ECDH KW and A128CBCHS256 encryption with 1 recipient (Compact serialization)",
  1241  			kt:         ecdh.X25519ECDHKWKeyTemplate(),
  1242  			enc:        ariesjose.A128CBCHS256,
  1243  			keyType:    kms.X25519ECDHKWType,
  1244  			nbRec:      1,
  1245  			useCompact: true,
  1246  		},
  1247  		{
  1248  			name:    "P-256 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)",
  1249  			kt:      ecdh.NISTP256ECDHKWKeyTemplate(),
  1250  			enc:     ariesjose.A192CBCHS384,
  1251  			keyType: kms.NISTP256ECDHKWType,
  1252  			nbRec:   2,
  1253  		},
  1254  		{
  1255  			name:    "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)",
  1256  			kt:      ecdh.NISTP256ECDHKWKeyTemplate(),
  1257  			enc:     ariesjose.A192CBCHS384,
  1258  			keyType: kms.NISTP256ECDHKWType,
  1259  			nbRec:   1,
  1260  		},
  1261  		{
  1262  			name:       "P-256 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)",
  1263  			kt:         ecdh.NISTP256ECDHKWKeyTemplate(),
  1264  			enc:        ariesjose.A192CBCHS384,
  1265  			keyType:    kms.NISTP256ECDHKWType,
  1266  			nbRec:      1,
  1267  			useCompact: true,
  1268  		},
  1269  		{
  1270  			name:    "P-384 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)",
  1271  			kt:      ecdh.NISTP384ECDHKWKeyTemplate(),
  1272  			enc:     ariesjose.A192CBCHS384,
  1273  			keyType: kms.NISTP384ECDHKWType,
  1274  			nbRec:   2,
  1275  		},
  1276  		{
  1277  			name:    "P-384 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)",
  1278  			kt:      ecdh.NISTP384ECDHKWKeyTemplate(),
  1279  			enc:     ariesjose.A192CBCHS384,
  1280  			keyType: kms.NISTP384ECDHKWType,
  1281  			nbRec:   1,
  1282  		},
  1283  		{
  1284  			name:       "P-384 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)",
  1285  			kt:         ecdh.NISTP384ECDHKWKeyTemplate(),
  1286  			enc:        ariesjose.A192CBCHS384,
  1287  			keyType:    kms.NISTP384ECDHKWType,
  1288  			nbRec:      1,
  1289  			useCompact: true,
  1290  		},
  1291  		{
  1292  			name:    "X25519 ECDH KW and A192CBCHS384 encryption with 2 recipients (Full serialization)",
  1293  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1294  			enc:     ariesjose.A192CBCHS384,
  1295  			keyType: kms.X25519ECDHKWType,
  1296  			nbRec:   2,
  1297  		},
  1298  		{
  1299  			name:    "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Flattened serialization)",
  1300  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1301  			enc:     ariesjose.A192CBCHS384,
  1302  			keyType: kms.X25519ECDHKWType,
  1303  			nbRec:   1,
  1304  		},
  1305  		{
  1306  			name:       "X25519 ECDH KW and A192CBCHS384 encryption with 1 recipient (Compact serialization)",
  1307  			kt:         ecdh.X25519ECDHKWKeyTemplate(),
  1308  			enc:        ariesjose.A192CBCHS384,
  1309  			keyType:    kms.X25519ECDHKWType,
  1310  			nbRec:      1,
  1311  			useCompact: true,
  1312  		},
  1313  		{
  1314  			name:    "X25519 ECDH KW and A256CBCHS384 encryption with 2 recipients (Full serialization)",
  1315  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1316  			enc:     ariesjose.A256CBCHS384,
  1317  			keyType: kms.X25519ECDHKWType,
  1318  			nbRec:   2,
  1319  		},
  1320  		{
  1321  			name:    "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Flattened serialization)",
  1322  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1323  			enc:     ariesjose.A256CBCHS384,
  1324  			keyType: kms.X25519ECDHKWType,
  1325  			nbRec:   1,
  1326  		},
  1327  		{
  1328  			name:       "X25519 ECDH KW and A256CBCHS384 encryption with 1 recipient (Compact serialization)",
  1329  			kt:         ecdh.X25519ECDHKWKeyTemplate(),
  1330  			enc:        ariesjose.A256CBCHS384,
  1331  			keyType:    kms.X25519ECDHKWType,
  1332  			nbRec:      1,
  1333  			useCompact: true,
  1334  		},
  1335  		{
  1336  			name:    "P-521 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)",
  1337  			kt:      ecdh.NISTP521ECDHKWKeyTemplate(),
  1338  			enc:     ariesjose.A256CBCHS512,
  1339  			keyType: kms.NISTP521ECDHKWType,
  1340  			nbRec:   2,
  1341  		},
  1342  		{
  1343  			name:    "P-521 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)",
  1344  			kt:      ecdh.NISTP521ECDHKWKeyTemplate(),
  1345  			enc:     ariesjose.A256CBCHS512,
  1346  			keyType: kms.NISTP521ECDHKWType,
  1347  			nbRec:   1,
  1348  		},
  1349  		{
  1350  			name:       "P-521 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)",
  1351  			kt:         ecdh.NISTP521ECDHKWKeyTemplate(),
  1352  			enc:        ariesjose.A256CBCHS512,
  1353  			keyType:    kms.NISTP521ECDHKWType,
  1354  			nbRec:      1,
  1355  			useCompact: true,
  1356  		},
  1357  		{
  1358  			name:    "X25519 ECDH KW and A256CBCHS512 encryption with 2 recipients (Full serialization)",
  1359  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1360  			enc:     ariesjose.A256CBCHS512,
  1361  			keyType: kms.X25519ECDHKWType,
  1362  			nbRec:   2,
  1363  		},
  1364  		{
  1365  			name:    "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Flattened serialization)",
  1366  			kt:      ecdh.X25519ECDHKWKeyTemplate(),
  1367  			enc:     ariesjose.A256CBCHS512,
  1368  			keyType: kms.X25519ECDHKWType,
  1369  			nbRec:   1,
  1370  		},
  1371  		{
  1372  			name:       "X25519 ECDH KW and A256CBCHS512 encryption with 1 recipient (Compact serialization)",
  1373  			kt:         ecdh.X25519ECDHKWKeyTemplate(),
  1374  			enc:        ariesjose.A256CBCHS512,
  1375  			keyType:    kms.X25519ECDHKWType,
  1376  			nbRec:      1,
  1377  			useCompact: true,
  1378  		},
  1379  	}
  1380  
  1381  	for _, tt := range tests {
  1382  		tc := tt
  1383  		t.Run(tc.name, func(t *testing.T) {
  1384  			t.Log("creating Sender key..")
  1385  			senders, senderKHs, senderKIDs, senderDIDKeys := createRecipientsByKeyTemplate(t, 1, tc.kt, tc.keyType)
  1386  			t.Log("creating recipients keys..")
  1387  			recipientsKeys, recKHs, _, recDIDKeys := createRecipientsByKeyTemplate(t, tc.nbRec, tc.kt, tc.keyType)
  1388  
  1389  			cryptoSvc, kmsSvc := createCryptoAndKMSServices(t, recKHs)
  1390  
  1391  			senderPubKey, err := json.Marshal(senders[0])
  1392  			require.NoError(t, err)
  1393  
  1394  			jweEncrypter, err := ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType, DIDCommContentEncodingType,
  1395  				senderKIDs[0], senderKHs[senderKIDs[0]], recipientsKeys, cryptoSvc)
  1396  			require.NoError(t, err)
  1397  			require.NotEmpty(t, jweEncrypter)
  1398  
  1399  			mockStoreMap := make(map[string]mockstorage.DBEntry)
  1400  			mockStore := &mockstorage.MockStore{
  1401  				Store: mockStoreMap,
  1402  			}
  1403  
  1404  			storeResolver := []resolver.KIDResolver{&resolver.StoreResolver{Store: mockStore}}
  1405  
  1406  			pt := []byte("secret message")
  1407  			aad := []byte("aad value")
  1408  
  1409  			if tc.useCompact { // Compact serialization does not use aad
  1410  				aad = nil
  1411  			}
  1412  
  1413  			// test JWEEncrypt for ECDH1PU
  1414  			testEncTime := time.Now()
  1415  			jwe, err := jweEncrypter.EncryptWithAuthData(pt, aad)
  1416  			t.Logf("ECDH-1PU KW in EncryptWithAuthData took %v", time.Since(testEncTime))
  1417  			require.NoError(t, err)
  1418  
  1419  			cty, ok := jwe.ProtectedHeaders.ContentType()
  1420  			require.True(t, ok)
  1421  			require.Equal(t, DIDCommContentEncodingType, cty)
  1422  
  1423  			typ, ok := jwe.ProtectedHeaders.Type()
  1424  			require.True(t, ok)
  1425  			require.Equal(t, EnvelopeEncodingType, typ)
  1426  
  1427  			alg, ok := jwe.ProtectedHeaders.Algorithm()
  1428  			if alg != "" {
  1429  				cbcHMACAlgs := []string{
  1430  					tinkcrypto.ECDH1PUA128KWAlg, tinkcrypto.ECDH1PUA192KWAlg,
  1431  					tinkcrypto.ECDH1PUA256KWAlg, tinkcrypto.ECDH1PUXC20PKWAlg,
  1432  				}
  1433  
  1434  				require.True(t, ok)
  1435  				require.Contains(t, cbcHMACAlgs, alg)
  1436  			} else {
  1437  				require.False(t, ok)
  1438  			}
  1439  
  1440  			kid, ok := jwe.ProtectedHeaders.KeyID()
  1441  			if kid != "" {
  1442  				require.True(t, ok)
  1443  				require.NotEmpty(t, kid)
  1444  			} else {
  1445  				require.False(t, ok)
  1446  			}
  1447  
  1448  			var serializedJWE, jweStr string
  1449  			serialization := fullSerialization
  1450  
  1451  			if tc.useCompact {
  1452  				testSerTime := time.Now()
  1453  				serializedJWE, err = jwe.CompactSerialize(json.Marshal)
  1454  				t.Logf("Compact serialize took %v", time.Since(testSerTime))
  1455  				require.NoError(t, err)
  1456  				require.NotEmpty(t, serializedJWE)
  1457  
  1458  				jweStr = serializedJWE
  1459  				serialization = compactSerialization
  1460  			} else {
  1461  				testSerTime := time.Now()
  1462  				serializedJWE, err = jwe.FullSerialize(json.Marshal)
  1463  				t.Logf("JSON serialize took %v", time.Since(testSerTime))
  1464  				require.NoError(t, err)
  1465  				require.NotEmpty(t, serializedJWE)
  1466  
  1467  				jweStr, err = prettyPrint([]byte(serializedJWE))
  1468  				require.NoError(t, err)
  1469  				if tc.nbRec == 1 {
  1470  					serialization = flattenedSerialization
  1471  				}
  1472  			}
  1473  
  1474  			t.Logf("* authcrypt JWE (%s serialization): %s", serialization, jweStr)
  1475  
  1476  			mPh, err := json.Marshal(jwe.ProtectedHeaders)
  1477  			require.NoError(t, err)
  1478  
  1479  			protectedHeadersStr, err := prettyPrint(mPh)
  1480  			require.NoError(t, err)
  1481  
  1482  			t.Logf("* protected headers: %s", protectedHeadersStr)
  1483  
  1484  			testDeserTime := time.Now()
  1485  			localJWE, err := ariesjose.Deserialize(serializedJWE)
  1486  			t.Logf("JWE deserialize took %v", time.Since(testDeserTime))
  1487  			require.NoError(t, err)
  1488  
  1489  			t.Run("ECDH-1PU JWE message without kid key in the KID storeResolver's store should fail", func(t *testing.T) {
  1490  				jd := ariesjose.NewJWEDecrypt(storeResolver, cryptoSvc, kmsSvc)
  1491  				require.NotEmpty(t, jd)
  1492  
  1493  				_, err = jd.Decrypt(localJWE)
  1494  				require.EqualError(t, err, "jwedecrypt: failed to add sender public key for skid: fetchSenderPubKey: "+
  1495  					"resolveKID: [storeResolver: failed to resolve kid from store: data not found]")
  1496  			})
  1497  
  1498  			// add sender pubkey into the recipient's mock store to prepare for a successful JWEDecrypt() for each recipient
  1499  			mockStoreMap[senderKIDs[0]] = mockstorage.DBEntry{Value: senderPubKey}
  1500  
  1501  			t.Run("Decrypting JWE message test success", func(t *testing.T) {
  1502  				jd := ariesjose.NewJWEDecrypt(storeResolver, cryptoSvc, kmsSvc)
  1503  				require.NotEmpty(t, jd)
  1504  
  1505  				var msg []byte
  1506  
  1507  				testDecTime := time.Now()
  1508  				msg, err = jd.Decrypt(localJWE)
  1509  				t.Logf("JWE deserialize took %v", time.Since(testDecTime))
  1510  				require.NoError(t, err)
  1511  				require.EqualValues(t, pt, msg)
  1512  			})
  1513  
  1514  			t.Run("ECDH-1PU Encrypt and Decrypt JWE test success with skid/kid as did:key", func(t *testing.T) {
  1515  				recKeys := make([]*cryptoapi.PublicKey, 0)
  1516  				for i, k := range recipientsKeys {
  1517  					k.KID = recDIDKeys[i]
  1518  					recKeys = append(recKeys, k)
  1519  				}
  1520  
  1521  				jweEncrypter, err = ariesjose.NewJWEEncrypt(tc.enc, EnvelopeEncodingType,
  1522  					DIDCommContentEncodingType, senderDIDKeys[0], senderKHs[senderKIDs[0]], recKeys, cryptoSvc)
  1523  				require.NoError(t, err)
  1524  
  1525  				testEncTime = time.Now()
  1526  				jwe, err = jweEncrypter.EncryptWithAuthData(pt, aad)
  1527  				t.Logf("ECDH-1PU KW in EncryptWithAuthData with kid as did:key took %v", time.Since(testEncTime))
  1528  				require.NoError(t, err)
  1529  				require.Equal(t, len(recipientsKeys), len(jwe.Recipients))
  1530  
  1531  				if tc.useCompact {
  1532  					testSerTime := time.Now()
  1533  					serializedJWE, err = jwe.CompactSerialize(json.Marshal)
  1534  					t.Logf("CompactSerilize JWE with as did:key took %v", time.Since(testSerTime))
  1535  					require.NoError(t, err)
  1536  					require.NotEmpty(t, serializedJWE)
  1537  
  1538  					jweStr = serializedJWE
  1539  					serialization = compactSerialization
  1540  				} else {
  1541  					testSerTime := time.Now()
  1542  					serializedJWE, err = jwe.FullSerialize(json.Marshal)
  1543  					t.Logf("JSON Serialize with kid as did:key took %v", time.Since(testSerTime))
  1544  					require.NoError(t, err)
  1545  					require.NotEmpty(t, serializedJWE)
  1546  
  1547  					jweStr, err = prettyPrint([]byte(serializedJWE))
  1548  					require.NoError(t, err)
  1549  					if tc.nbRec == 1 {
  1550  						serialization = flattenedSerialization
  1551  					}
  1552  				}
  1553  
  1554  				t.Logf("* authcrypt JWE (%s serialization) with kid as did:key: %s", serialization, jweStr)
  1555  
  1556  				// try to deserialize with go-jose (can't decrypt in go-jose since private key is protected by Tink)
  1557  				joseJWE, err := jose.ParseEncrypted(serializedJWE)
  1558  				require.NoError(t, err)
  1559  				require.NotEmpty(t, joseJWE)
  1560  
  1561  				// try to deserialize with local package
  1562  				testDeserTime := time.Now()
  1563  				localJWE, err = ariesjose.Deserialize(serializedJWE)
  1564  				t.Logf("JWE with kid as did:key Deserialize took %v", time.Since(testDeserTime))
  1565  				require.NoError(t, err)
  1566  
  1567  				jweDecrypter := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{&resolver.DIDKeyResolver{}}, cryptoSvc, kmsSvc)
  1568  
  1569  				var msg []byte
  1570  
  1571  				testDecTime := time.Now()
  1572  				msg, err = jweDecrypter.Decrypt(localJWE)
  1573  				t.Logf("JWE with kid as did:key Decrypt took %v", time.Since(testDecTime))
  1574  				require.NoError(t, err)
  1575  				require.EqualValues(t, pt, msg)
  1576  			})
  1577  		})
  1578  	}
  1579  }
  1580  
  1581  func createCryptoAndKMSServices(t *testing.T, keys map[string]*keyset.Handle) (cryptoapi.Crypto, kms.KeyManager) {
  1582  	c, err := tinkcrypto.New()
  1583  	require.NoError(t, err)
  1584  
  1585  	k := &mockKMSGetter{
  1586  		keys: keys,
  1587  	}
  1588  
  1589  	require.NoError(t, err)
  1590  
  1591  	return c, k
  1592  }
  1593  
  1594  type mockKMSGetter struct {
  1595  	mockkms.KeyManager
  1596  	keys map[string]*keyset.Handle
  1597  }
  1598  
  1599  func (k *mockKMSGetter) Get(kid string) (interface{}, error) {
  1600  	return k.keys[kid], nil
  1601  }
  1602  
  1603  // nolint:gochecknoglobals // embedded test data
  1604  var (
  1605  	// test vector retrieved from:
  1606  	//nolint:lll
  1607  	// (github: https://github.com/NeilMadden/jose-ecdh-1pu/blob/master/draft-madden-jose-ecdh-1pu-04/draft-madden-jose-ecdh-1pu-04.txt#L740)
  1608  	// (ietf draft: https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04#appendix-B)
  1609  	//go:embed testdata/alice_key_ref.json
  1610  	aliceKeyRef string
  1611  	//go:embed testdata/bob_key_ref.json
  1612  	bobKeyRef string
  1613  	//go:embed testdata/charlie_key_ref.json
  1614  	charlieKeyRef string
  1615  	//go:embed testdata/jwe_ref.json
  1616  	jweRef string
  1617  )
  1618  
  1619  func Test1PUDraft4ExampleBDecrypt(t *testing.T) {
  1620  	testJWE := trimSpace(jweRef)
  1621  	aliceKey := trimSpace(aliceKeyRef)
  1622  	bobKey := trimSpace(bobKeyRef)
  1623  	charlieKey := trimSpace(charlieKeyRef)
  1624  
  1625  	skid := "Alice"
  1626  	keys := convertX25519ToKH(t, []string{aliceKey, bobKey, charlieKey}, []string{skid, "bob-key-2", "2021-05-06"})
  1627  
  1628  	c, k := createCryptoAndKMSServices(t, keys)
  1629  
  1630  	mockStoreMap := make(map[string]mockstorage.DBEntry)
  1631  
  1632  	pubKH, err := keys[skid].Public()
  1633  	require.NoError(t, err)
  1634  
  1635  	senderPubKey, err := keyio.ExtractPrimaryPublicKey(pubKH)
  1636  	require.NoError(t, err)
  1637  
  1638  	mSenderPubKey, err := json.Marshal(senderPubKey)
  1639  	require.NoError(t, err)
  1640  
  1641  	mockStoreMap[skid] = mockstorage.DBEntry{Value: mSenderPubKey}
  1642  
  1643  	mockStore := &mockstorage.MockStore{
  1644  		Store: mockStoreMap,
  1645  	}
  1646  
  1647  	localJWE, err := ariesjose.Deserialize(testJWE)
  1648  	require.NoError(t, err)
  1649  	require.NotEmpty(t, localJWE)
  1650  
  1651  	dec := ariesjose.NewJWEDecrypt([]resolver.KIDResolver{&resolver.StoreResolver{Store: mockStore}}, c, k)
  1652  	require.NotEmpty(t, dec)
  1653  
  1654  	pt, err := dec.Decrypt(localJWE)
  1655  	require.NoError(t, err)
  1656  	require.EqualValues(t, []byte("Three is a magic number."), pt)
  1657  }
  1658  
  1659  func trimSpace(s string) string {
  1660  	s = strings.ReplaceAll(s, " ", "")
  1661  	s = strings.ReplaceAll(s, "\n", "")
  1662  
  1663  	return s
  1664  }
  1665  
  1666  func convertX25519ToKH(t *testing.T, keys, kids []string) map[string]*keyset.Handle {
  1667  	t.Helper()
  1668  
  1669  	var err error
  1670  
  1671  	khs := make(map[string]*keyset.Handle)
  1672  
  1673  	for i, k := range keys {
  1674  		delim := ",\"d\""
  1675  		idx := strings.Index(k, delim)
  1676  		mPubKey := k[:idx] + "}"
  1677  		pubKey := &jwk.JWK{}
  1678  		err = json.Unmarshal([]byte(mPubKey), pubKey)
  1679  		require.NoError(t, err)
  1680  
  1681  		var d []byte
  1682  
  1683  		dVal := k[idx+len(delim)+2 : len(k)-2]
  1684  		d, err = base64.RawURLEncoding.DecodeString(dVal)
  1685  		require.NoError(t, err)
  1686  
  1687  		privKey := &cryptoapi.PrivateKey{
  1688  			PublicKey: cryptoapi.PublicKey{
  1689  				X:     pubKey.Key.([]byte),
  1690  				Curve: pubKey.Crv,
  1691  				Type:  pubKey.Kty,
  1692  			},
  1693  			D: d,
  1694  		}
  1695  
  1696  		var kh *keyset.Handle
  1697  
  1698  		kh, err = keyio.PrivateKeyToKeysetHandle(privKey, ecdh.XC20P)
  1699  		require.NoError(t, err)
  1700  
  1701  		khs[kids[i]] = kh
  1702  	}
  1703  
  1704  	return khs
  1705  }