github.com/trustbloc/kms-go@v1.1.2/crypto/tinkcrypto/crypto_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tinkcrypto
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"math/big"
    14  	"testing"
    15  
    16  	tinkaead "github.com/google/tink/go/aead"
    17  	tinkaeadsubtle "github.com/google/tink/go/aead/subtle"
    18  	hybrid "github.com/google/tink/go/hybrid/subtle"
    19  	"github.com/google/tink/go/keyset"
    20  	"github.com/google/tink/go/mac"
    21  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    22  	"github.com/google/tink/go/signature"
    23  	"github.com/google/tink/go/subtle/random"
    24  	"github.com/stretchr/testify/require"
    25  	chacha "golang.org/x/crypto/chacha20poly1305"
    26  
    27  	cryptoapi "github.com/trustbloc/kms-go/spi/crypto"
    28  
    29  	"github.com/trustbloc/kms-go/crypto"
    30  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead"
    31  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead/subtle"
    32  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/bbs"
    33  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/ecdh"
    34  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/composite/keyio"
    35  	ecdhpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/ecdh_aead_go_proto"
    36  	"github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/secp256k1"
    37  )
    38  
    39  const testMessage = "test message"
    40  
    41  // Assert that Crypto implements the Crypto interface.
    42  var _ cryptoapi.Crypto = (*Crypto)(nil)
    43  
    44  func TestNew(t *testing.T) {
    45  	_, err := New()
    46  	require.NoError(t, err)
    47  }
    48  
    49  func TestCrypto_EncryptDecrypt(t *testing.T) {
    50  	tests := []struct {
    51  		name         string
    52  		ivSize       int
    53  		aeadTemplate *tinkpb.KeyTemplate
    54  	}{
    55  		{
    56  			name:         "test XChacha20Poly1305 encryption",
    57  			ivSize:       chacha.NonceSizeX,
    58  			aeadTemplate: tinkaead.XChaCha20Poly1305KeyTemplate(),
    59  		},
    60  		{
    61  			name:         "test AES256GCM encryption",
    62  			ivSize:       tinkaeadsubtle.AESGCMIVSize,
    63  			aeadTemplate: tinkaead.AES256GCMKeyTemplate(),
    64  		},
    65  		{
    66  			name:         "test AES128CBCHMACSHA256 encryption",
    67  			ivSize:       subtle.AESCBCIVSize,
    68  			aeadTemplate: aead.AES128CBCHMACSHA256KeyTemplate(),
    69  		},
    70  		{
    71  			name:         "test AES192CBCHMACSHA384 encryption",
    72  			ivSize:       subtle.AESCBCIVSize,
    73  			aeadTemplate: aead.AES192CBCHMACSHA384KeyTemplate(),
    74  		},
    75  		{
    76  			name:         "test AES256CBCHMACSHA384 encryption",
    77  			ivSize:       subtle.AESCBCIVSize,
    78  			aeadTemplate: aead.AES256CBCHMACSHA384KeyTemplate(),
    79  		},
    80  		{
    81  			name:         "test AES256CBCHMACSHA512 encryption",
    82  			ivSize:       subtle.AESCBCIVSize,
    83  			aeadTemplate: aead.AES256CBCHMACSHA512KeyTemplate(),
    84  		},
    85  	}
    86  
    87  	t.Parallel()
    88  
    89  	for _, test := range tests {
    90  		tc := test
    91  		t.Run(tc.name, func(t *testing.T) {
    92  			kh, err := keyset.NewHandle(tc.aeadTemplate)
    93  			require.NoError(t, err)
    94  
    95  			c := Crypto{}
    96  			msg := []byte(testMessage)
    97  			aad := []byte("some additional data")
    98  			cipherText, nonce, err := c.Encrypt(msg, aad, kh)
    99  			require.NoError(t, err)
   100  			require.NotEmpty(t, nonce)
   101  			require.Equal(t, tc.ivSize, len(nonce))
   102  
   103  			plainText, err := c.Decrypt(cipherText, aad, nonce, kh)
   104  			require.NoError(t, err)
   105  			require.Equal(t, msg, plainText)
   106  
   107  			// decrypt with bad nonce - should fail
   108  			plainText, err = c.Decrypt(cipherText, aad, []byte("bad nonce"), kh)
   109  			require.Error(t, err)
   110  			require.Empty(t, plainText)
   111  
   112  			// decrypt with bad cipher - should fail
   113  			plainText, err = c.Decrypt([]byte("bad cipher"), aad, nonce, kh)
   114  			require.Error(t, err)
   115  			require.Empty(t, plainText)
   116  		})
   117  	}
   118  
   119  	t.Run("test bad/nil kh encryption", func(t *testing.T) {
   120  		kh, err := keyset.NewHandle(tinkaead.AES256GCMKeyTemplate())
   121  		require.NoError(t, err)
   122  
   123  		c := Crypto{}
   124  		msg := []byte(testMessage)
   125  		aad := []byte("some additional data")
   126  		cipherText, nonce, err := c.Encrypt(msg, aad, kh)
   127  		require.NoError(t, err)
   128  		require.NotEmpty(t, nonce)
   129  		require.Equal(t, tinkaeadsubtle.AESGCMIVSize, len(nonce))
   130  
   131  		// encrypt with nil key handle - should fail
   132  		_, _, err = c.Encrypt(msg, aad, nil)
   133  		require.Error(t, err)
   134  		require.Equal(t, errBadKeyHandleFormat, err)
   135  
   136  		plainText, err := c.Decrypt(cipherText, aad, nonce, kh)
   137  		require.NoError(t, err)
   138  		require.Equal(t, msg, plainText)
   139  
   140  		// decrypt with bad nonce - should fail
   141  		plainText, err = c.Decrypt(cipherText, aad, []byte("bad nonce"), kh)
   142  		require.Error(t, err)
   143  		require.Empty(t, plainText)
   144  
   145  		// decrypt with bad cipher - should fail
   146  		plainText, err = c.Decrypt([]byte("bad cipher"), aad, nonce, kh)
   147  		require.Error(t, err)
   148  		require.Empty(t, plainText)
   149  
   150  		// decrypt with nil key handle - should fail
   151  		_, err = c.Decrypt(cipherText, aad, nonce, nil)
   152  		require.Error(t, err)
   153  		require.Equal(t, errBadKeyHandleFormat, err)
   154  	})
   155  }
   156  
   157  func TestCrypto_SignVerify(t *testing.T) {
   158  	t.Run("test with Ed25519 signature", func(t *testing.T) {
   159  		kh, err := keyset.NewHandle(signature.ED25519KeyTemplate())
   160  		require.NoError(t, err)
   161  
   162  		badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil))
   163  		require.NoError(t, err)
   164  
   165  		c := Crypto{}
   166  		msg := []byte(testMessage)
   167  		s, err := c.Sign(msg, kh)
   168  		require.NoError(t, err)
   169  
   170  		// sign with nil key handle - should fail
   171  		_, err = c.Sign(msg, nil)
   172  		require.Error(t, err)
   173  		require.Equal(t, errBadKeyHandleFormat, err)
   174  
   175  		// sign with bad key handle - should fail
   176  		_, err = c.Sign(msg, badKH)
   177  		require.Error(t, err)
   178  
   179  		// get corresponding public key handle to verify
   180  		pubKH, err := kh.Public()
   181  		require.NoError(t, err)
   182  
   183  		err = c.Verify(s, msg, pubKH)
   184  		require.NoError(t, err)
   185  	})
   186  
   187  	t.Run("test with P-256 signature", func(t *testing.T) {
   188  		kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate())
   189  		require.NoError(t, err)
   190  
   191  		badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil))
   192  		require.NoError(t, err)
   193  
   194  		c := Crypto{}
   195  		msg := []byte(testMessage)
   196  		s, err := c.Sign(msg, kh)
   197  		require.NoError(t, err)
   198  
   199  		// get corresponding public key handle to verify
   200  		pubKH, err := kh.Public()
   201  		require.NoError(t, err)
   202  
   203  		err = c.Verify(s, msg, pubKH)
   204  		require.NoError(t, err)
   205  
   206  		// verify with nil key handle - should fail
   207  		err = c.Verify(s, msg, nil)
   208  		require.Error(t, err)
   209  		require.Equal(t, errBadKeyHandleFormat, err)
   210  
   211  		// verify with bad key handle - should fail
   212  		err = c.Verify(s, msg, badKH)
   213  		require.Error(t, err)
   214  	})
   215  
   216  	t.Run("test with P-384 signature", func(t *testing.T) {
   217  		kh, err := keyset.NewHandle(signature.ECDSAP384KeyTemplate())
   218  		require.NoError(t, err)
   219  
   220  		badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil))
   221  		require.NoError(t, err)
   222  
   223  		c := Crypto{}
   224  		msg := []byte(testMessage)
   225  		s, err := c.Sign(msg, kh)
   226  		require.NoError(t, err)
   227  
   228  		// get corresponding public key handle to verify
   229  		pubKH, err := kh.Public()
   230  		require.NoError(t, err)
   231  
   232  		err = c.Verify(s, msg, pubKH)
   233  		require.NoError(t, err)
   234  
   235  		// verify with nil key handle - should fail
   236  		err = c.Verify(s, msg, nil)
   237  		require.Error(t, err)
   238  		require.Equal(t, errBadKeyHandleFormat, err)
   239  
   240  		// verify with bad key handle - should fail
   241  		err = c.Verify(s, msg, badKH)
   242  		require.Error(t, err)
   243  	})
   244  
   245  	t.Run("test with secp256k1 signature", func(t *testing.T) {
   246  		derTemplate, err := secp256k1.DERKeyTemplate()
   247  		require.NoError(t, err)
   248  
   249  		kh, err := keyset.NewHandle(derTemplate)
   250  		require.NoError(t, err)
   251  
   252  		badKH, err := keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil))
   253  		require.NoError(t, err)
   254  
   255  		c := Crypto{}
   256  		msg := []byte(testMessage)
   257  		s, err := c.Sign(msg, kh)
   258  		require.NoError(t, err)
   259  
   260  		// get corresponding public key handle to verify
   261  		pubKH, err := kh.Public()
   262  		require.NoError(t, err)
   263  
   264  		err = c.Verify(s, msg, pubKH)
   265  		require.NoError(t, err)
   266  
   267  		// verify with nil key handle - should fail
   268  		err = c.Verify(s, msg, nil)
   269  		require.Error(t, err)
   270  		require.Equal(t, errBadKeyHandleFormat, err)
   271  
   272  		// verify with bad key handle - should fail
   273  		err = c.Verify(s, msg, badKH)
   274  		require.Error(t, err)
   275  	})
   276  }
   277  
   278  func TestCrypto_ComputeMAC(t *testing.T) {
   279  	t.Run("success", func(t *testing.T) {
   280  		kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
   281  		require.NoError(t, err)
   282  		require.NotNil(t, kh)
   283  
   284  		c := Crypto{}
   285  		msg := []byte(testMessage)
   286  		macBytes, err := c.ComputeMAC(msg, kh)
   287  		require.NoError(t, err)
   288  		require.NotEmpty(t, macBytes)
   289  	})
   290  	t.Run("success - message to compute MAC with nil data - should be treated as empty data", func(t *testing.T) {
   291  		kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
   292  		require.NoError(t, err)
   293  		require.NotNil(t, kh)
   294  
   295  		c := Crypto{}
   296  		macBytes, err := c.ComputeMAC(nil, kh)
   297  		require.NoError(t, err)
   298  		require.NotEmpty(t, macBytes)
   299  	})
   300  	t.Run("invalid key handle", func(t *testing.T) {
   301  		c := Crypto{}
   302  		macBytes, err := c.ComputeMAC(nil, nil)
   303  		require.Equal(t, errBadKeyHandleFormat, err)
   304  		require.Empty(t, macBytes)
   305  	})
   306  	t.Run("fail - wrong key type", func(t *testing.T) {
   307  		kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate())
   308  		require.NoError(t, err)
   309  		require.NotNil(t, kh)
   310  
   311  		c := Crypto{}
   312  		msg := []byte(testMessage)
   313  		macBytes, err := c.ComputeMAC(msg, kh)
   314  		require.EqualError(t, err, "mac_factory: not a MAC primitive")
   315  		require.Empty(t, macBytes)
   316  	})
   317  }
   318  
   319  func TestCrypto_VerifyMAC(t *testing.T) {
   320  	t.Run("success", func(t *testing.T) {
   321  		kh, err := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
   322  		require.NoError(t, err)
   323  		require.NotNil(t, kh)
   324  
   325  		c := Crypto{}
   326  		msg := []byte(testMessage)
   327  		macBytes, err := c.ComputeMAC(msg, kh)
   328  		require.NoError(t, err)
   329  		require.NotEmpty(t, macBytes)
   330  
   331  		err = c.VerifyMAC(macBytes, msg, kh)
   332  		require.NoError(t, err)
   333  	})
   334  	t.Run("bad key handle format", func(t *testing.T) {
   335  		c := Crypto{}
   336  		err := c.VerifyMAC(nil, nil, nil)
   337  		require.Equal(t, errBadKeyHandleFormat, err)
   338  	})
   339  	t.Run("fail - wrong key type", func(t *testing.T) {
   340  		kh, err := keyset.NewHandle(signature.ECDSAP256KeyTemplate())
   341  		require.NoError(t, err)
   342  		require.NotNil(t, kh)
   343  
   344  		c := Crypto{}
   345  		err = c.VerifyMAC(nil, nil, kh)
   346  		require.EqualError(t, err, "mac_factory: not a MAC primitive")
   347  	})
   348  }
   349  
   350  func TestCrypto_ECDHES_Wrap_Unwrap_Key(t *testing.T) {
   351  	recipientKeyHandle, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate())
   352  	require.NoError(t, err)
   353  
   354  	c, err := New()
   355  	require.NoError(t, err)
   356  
   357  	cek := random.GetRandomBytes(uint32(crypto.DefKeySize))
   358  	apu := random.GetRandomBytes(uint32(10)) // or sender name
   359  	apv := random.GetRandomBytes(uint32(10)) // or recipient name
   360  
   361  	// test WrapKey with nil recipientKey
   362  	_, err = c.WrapKey(cek, apu, apv, nil)
   363  	require.EqualError(t, err, "wrapKey: recipient public key is required")
   364  
   365  	// now test WrapKey with good key
   366  	recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle)
   367  	require.NoError(t, err)
   368  
   369  	wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey)
   370  	require.NoError(t, err)
   371  	require.NotEmpty(t, wrappedKey.EncryptedCEK)
   372  	require.NotEmpty(t, wrappedKey.EPK)
   373  	require.EqualValues(t, wrappedKey.APU, apu)
   374  	require.EqualValues(t, wrappedKey.APV, apv)
   375  	require.Equal(t, wrappedKey.Alg, ECDHESA256KWAlg)
   376  
   377  	// test UnwrapKey with empty recWK and/or kh
   378  	_, err = c.UnwrapKey(nil, nil)
   379  	require.EqualError(t, err, "unwrapKey: RecipientWrappedKey is empty")
   380  
   381  	_, err = c.UnwrapKey(nil, recipientKeyHandle)
   382  	require.EqualError(t, err, "unwrapKey: RecipientWrappedKey is empty")
   383  
   384  	_, err = c.UnwrapKey(wrappedKey, nil)
   385  	require.EqualError(t, err, "unwrapKey: deriveKEKAndUnwrap: bad key handle format")
   386  
   387  	// test UnwrapKey with ECDHES key but different curve
   388  	ecdh384Key, err := keyset.NewHandle(ecdh.NISTP384ECDHKWKeyTemplate())
   389  	require.NoError(t, err)
   390  
   391  	_, err = c.UnwrapKey(wrappedKey, ecdh384Key)
   392  	require.EqualError(t, err, "unwrapKey: deriveKEKAndUnwrap: error ECDH-ES kek derivation: deriveESKEKForUnwrap:"+
   393  		" error: deriveESWithECKeyForUnwrap: recipient and ephemeral keys are not on the same curve")
   394  
   395  	// test UnwrapKey with wrappedKey using different algorithm
   396  	origAlg := wrappedKey.Alg
   397  	wrappedKey.Alg = "badAlg"
   398  	_, err = c.UnwrapKey(wrappedKey, recipientKeyHandle)
   399  	require.EqualError(t, err, "unwrapKey: deriveKEKAndUnwrap: unsupported JWE KW Alg 'badAlg'")
   400  
   401  	wrappedKey.Alg = origAlg
   402  
   403  	// finally test with valid wrappedKey and recipientKey
   404  	uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle) // UnwrapKey will extract private key from recipientKey
   405  	require.NoError(t, err)
   406  	require.EqualValues(t, cek, uCEK)
   407  }
   408  
   409  func TestCrypto_ECDHES_Wrap_Unwrap_ForAllKeyTypes(t *testing.T) {
   410  	tests := []struct {
   411  		tcName   string
   412  		keyTempl *tinkpb.KeyTemplate
   413  		kwAlg    string
   414  		keyType  string
   415  		keyCurve string
   416  		useXC20P bool
   417  		senderKT *tinkpb.KeyTemplate
   418  		err      string
   419  	}{
   420  		{
   421  			tcName:   "key wrap using ECDH-ES with NIST P-256 key and A256GCM kw",
   422  			keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(),
   423  			kwAlg:    ECDHESA256KWAlg,
   424  			keyType:  ecdhpb.KeyType_EC.String(),
   425  			keyCurve: elliptic.P256().Params().Name,
   426  		},
   427  		{
   428  			tcName:   "key wrap using ECDH-ES with NIST P-384 key and A256GCM kw",
   429  			keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(),
   430  			kwAlg:    ECDHESA256KWAlg,
   431  			keyType:  ecdhpb.KeyType_EC.String(),
   432  			keyCurve: elliptic.P384().Params().Name,
   433  		},
   434  		{
   435  			tcName:   "key wrap using ECDH-ES with NIST P-521 key and A256GCM kw",
   436  			keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(),
   437  			kwAlg:    ECDHESA256KWAlg,
   438  			keyType:  ecdhpb.KeyType_EC.String(),
   439  			keyCurve: elliptic.P521().Params().Name,
   440  		},
   441  		{
   442  			tcName:   "key wrap using ECDH-ES with X25519 key and A256GCM kw",
   443  			keyTempl: ecdh.X25519ECDHKWKeyTemplate(),
   444  			kwAlg:    ECDHESA256KWAlg,
   445  			keyType:  ecdhpb.KeyType_OKP.String(),
   446  			keyCurve: "X25519",
   447  		},
   448  		{
   449  			tcName:   "key wrap using ECDH-ES with NIST P-256 key and XC20P kw",
   450  			keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(),
   451  			kwAlg:    ECDHESXC20PKWAlg,
   452  			keyType:  ecdhpb.KeyType_EC.String(),
   453  			keyCurve: elliptic.P256().Params().Name,
   454  			useXC20P: true,
   455  		},
   456  		{
   457  			tcName:   "key wrap using ECDH-ES with NIST P-384 key and XC20P kw",
   458  			keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(),
   459  			kwAlg:    ECDHESXC20PKWAlg,
   460  			keyType:  ecdhpb.KeyType_EC.String(),
   461  			keyCurve: elliptic.P384().Params().Name,
   462  			useXC20P: true,
   463  		},
   464  		{
   465  			tcName:   "key wrap using ECDH-ES with NIST P-521 key and XC20P kw",
   466  			keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(),
   467  			kwAlg:    ECDHESXC20PKWAlg,
   468  			keyType:  ecdhpb.KeyType_EC.String(),
   469  			keyCurve: elliptic.P521().Params().Name,
   470  			useXC20P: true,
   471  		},
   472  		{
   473  			tcName:   "key wrap using ECDH-ES with X25519 key and XC20P kw",
   474  			keyTempl: ecdh.X25519ECDHKWKeyTemplate(),
   475  			kwAlg:    ECDHESXC20PKWAlg,
   476  			keyType:  ecdhpb.KeyType_OKP.String(),
   477  			keyCurve: "X25519",
   478  			useXC20P: true,
   479  		},
   480  		{
   481  			tcName:   "key wrap using ECDH-1PU with NIST P-256 key and A128GCM kw",
   482  			keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(),
   483  			kwAlg:    ECDH1PUA128KWAlg,
   484  			keyType:  ecdhpb.KeyType_EC.String(),
   485  			keyCurve: elliptic.P256().Params().Name,
   486  			senderKT: ecdh.NISTP256ECDHKWKeyTemplate(),
   487  		},
   488  		{
   489  			tcName:   "key wrap using ECDH-1PU with NIST P-384 key and A192GCM kw",
   490  			keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(),
   491  			kwAlg:    ECDH1PUA192KWAlg,
   492  			keyType:  ecdhpb.KeyType_EC.String(),
   493  			keyCurve: elliptic.P384().Params().Name,
   494  			senderKT: ecdh.NISTP384ECDHKWKeyTemplate(),
   495  		},
   496  		{
   497  			tcName:   "key wrap using ECDH-1PU with NIST P-521 key and A256GCM kw",
   498  			keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(),
   499  			kwAlg:    ECDH1PUA256KWAlg,
   500  			keyType:  ecdhpb.KeyType_EC.String(),
   501  			keyCurve: elliptic.P521().Params().Name,
   502  			senderKT: ecdh.NISTP521ECDHKWKeyTemplate(),
   503  		},
   504  		{
   505  			tcName:   "key wrap using ECDH-1PU with NIST P-384 key and A256GCM kw",
   506  			keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(),
   507  			kwAlg:    ECDH1PUA256KWAlg,
   508  			keyType:  ecdhpb.KeyType_EC.String(),
   509  			keyCurve: elliptic.P384().Params().Name,
   510  			senderKT: ecdh.NISTP384ECDHKWKeyTemplate(),
   511  		},
   512  		{
   513  			tcName:   "key wrap using ECDH-1PU with NIST P-521 key and A256GCM kw",
   514  			keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(),
   515  			kwAlg:    ECDH1PUA256KWAlg,
   516  			keyType:  ecdhpb.KeyType_EC.String(),
   517  			keyCurve: elliptic.P521().Params().Name,
   518  			senderKT: ecdh.NISTP521ECDHKWKeyTemplate(),
   519  		},
   520  		{
   521  			tcName:   "key wrap using ECDH-1PU with X25519 key and A256GCM kw",
   522  			keyTempl: ecdh.X25519ECDHKWKeyTemplate(),
   523  			kwAlg:    ECDH1PUA256KWAlg,
   524  			keyType:  ecdhpb.KeyType_OKP.String(),
   525  			keyCurve: "X25519",
   526  			senderKT: ecdh.X25519ECDHKWKeyTemplate(),
   527  		},
   528  		{
   529  			tcName:   "key wrap using ECDH-1PU with NIST P-256 key and XC20P kw",
   530  			keyTempl: ecdh.NISTP256ECDHKWKeyTemplate(),
   531  			kwAlg:    ECDH1PUXC20PKWAlg,
   532  			keyType:  ecdhpb.KeyType_EC.String(),
   533  			keyCurve: elliptic.P256().Params().Name,
   534  			senderKT: ecdh.NISTP256ECDHKWKeyTemplate(),
   535  			useXC20P: true,
   536  		},
   537  		{
   538  			tcName:   "key wrap using ECDH-1PU with NIST P-384 key and XC20P kw",
   539  			keyTempl: ecdh.NISTP384ECDHKWKeyTemplate(),
   540  			kwAlg:    ECDH1PUXC20PKWAlg,
   541  			keyType:  ecdhpb.KeyType_EC.String(),
   542  			keyCurve: elliptic.P384().Params().Name,
   543  			senderKT: ecdh.NISTP384ECDHKWKeyTemplate(),
   544  			useXC20P: true,
   545  		},
   546  		{
   547  			tcName:   "key wrap using ECDH-1PU with NIST P-521 key and XC20P kw",
   548  			keyTempl: ecdh.NISTP521ECDHKWKeyTemplate(),
   549  			kwAlg:    ECDH1PUXC20PKWAlg,
   550  			keyType:  ecdhpb.KeyType_EC.String(),
   551  			keyCurve: elliptic.P521().Params().Name,
   552  			senderKT: ecdh.NISTP521ECDHKWKeyTemplate(),
   553  			useXC20P: true,
   554  		},
   555  		{
   556  			tcName:   "key wrap using ECDH-1PU with X25519 key and XC20P kw",
   557  			keyTempl: ecdh.X25519ECDHKWKeyTemplate(),
   558  			kwAlg:    ECDH1PUXC20PKWAlg,
   559  			keyType:  ecdhpb.KeyType_OKP.String(),
   560  			keyCurve: "X25519",
   561  			senderKT: ecdh.X25519ECDHKWKeyTemplate(),
   562  			useXC20P: true,
   563  		},
   564  	}
   565  
   566  	c, err := New()
   567  	require.NoError(t, err)
   568  
   569  	apu := random.GetRandomBytes(uint32(10)) // or sender name
   570  	apv := random.GetRandomBytes(uint32(10)) // or recipient name
   571  
   572  	for _, tt := range tests {
   573  		tc := tt
   574  		t.Run("Test "+tc.tcName, func(t *testing.T) {
   575  			keySize := aesCEKSize1PU(tc.kwAlg)
   576  
   577  			cek := random.GetRandomBytes(uint32(keySize))
   578  			recipientKeyHandle, err := keyset.NewHandle(tc.keyTempl)
   579  			require.NoError(t, err)
   580  
   581  			recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle)
   582  			require.NoError(t, err)
   583  
   584  			var senderKH *keyset.Handle
   585  
   586  			var wrapKeyOtps []cryptoapi.WrapKeyOpts
   587  			if tc.useXC20P {
   588  				// WithXC20OKW option used for WrapKey() only. UnwrapKey() does not check this option, it checks kwAlg.
   589  				wrapKeyOtps = append(wrapKeyOtps, cryptoapi.WithXC20PKW())
   590  			}
   591  
   592  			if tc.senderKT != nil {
   593  				senderKH, err = keyset.NewHandle(tc.senderKT)
   594  				require.NoError(t, err)
   595  
   596  				wrapKeyOtps = append(wrapKeyOtps, cryptoapi.WithSender(senderKH))
   597  			}
   598  
   599  			wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey, wrapKeyOtps...)
   600  			require.NoError(t, err)
   601  			require.NotEmpty(t, wrappedKey.EncryptedCEK)
   602  			require.NotEmpty(t, wrappedKey.EPK)
   603  			require.EqualValues(t, wrappedKey.APU, apu)
   604  			require.EqualValues(t, wrappedKey.APV, apv)
   605  			require.Equal(t, tc.kwAlg, wrappedKey.Alg)
   606  			require.Equal(t, tc.keyCurve, wrappedKey.EPK.Curve)
   607  			require.Equal(t, tc.keyType, wrappedKey.EPK.Type)
   608  
   609  			if senderKH != nil {
   610  				var senderPubKey *cryptoapi.PublicKey
   611  
   612  				// mimic recipient side (by using sender public key for unwrapping instead of the private key)
   613  				senderPubKey, err = keyio.ExtractPrimaryPublicKey(senderKH)
   614  				require.NoError(t, err)
   615  
   616  				// reset wrapKeyOpts because UnwrapKey only uses WithSender() option.
   617  				wrapKeyOtps = []cryptoapi.WrapKeyOpts{cryptoapi.WithSender(senderPubKey)}
   618  			}
   619  
   620  			uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle, wrapKeyOtps...)
   621  			require.NoError(t, err)
   622  			require.EqualValues(t, cek, uCEK)
   623  		})
   624  	}
   625  }
   626  
   627  func TestCrypto_ECDH1PU_Wrap_Unwrap_Key(t *testing.T) {
   628  	recipientKeyHandle, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate())
   629  	require.NoError(t, err)
   630  
   631  	recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle)
   632  	require.NoError(t, err)
   633  
   634  	senderKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate())
   635  	require.NoError(t, err)
   636  
   637  	c, err := New()
   638  	require.NoError(t, err)
   639  
   640  	cek := random.GetRandomBytes(uint32(crypto.DefKeySize * 2))
   641  	apu := random.GetRandomBytes(uint32(10)) // or sender name
   642  	apv := random.GetRandomBytes(uint32(10)) // or recipient name
   643  
   644  	// test with bad senderKH value
   645  	_, err = c.WrapKey(cek, apu, apv, recipientKey, cryptoapi.WithSender("badKey"))
   646  	require.EqualError(t, err, "wrapKey: deriveKEKAndWrap: error ECDH-1PU kek derivation: derive1PUKEK: EC key"+
   647  		" derivation error derive1PUWithECKey: failed to retrieve sender key: ksToPrivateECDSAKey: bad key handle "+
   648  		"format")
   649  
   650  	// now test WrapKey with good key
   651  	wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey, cryptoapi.WithSender(senderKH))
   652  	require.NoError(t, err)
   653  	require.NotEmpty(t, wrappedKey.EncryptedCEK)
   654  	require.NotEmpty(t, wrappedKey.EPK)
   655  	require.EqualValues(t, wrappedKey.APU, apu)
   656  	require.EqualValues(t, wrappedKey.APV, apv)
   657  	require.Equal(t, wrappedKey.Alg, ECDH1PUA256KWAlg)
   658  
   659  	// test with valid wrappedKey, senderKH (public key) and recipientKey
   660  	senderPubKH, err := senderKH.Public()
   661  	require.NoError(t, err)
   662  
   663  	uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderPubKH))
   664  	require.NoError(t, err)
   665  	require.EqualValues(t, cek, uCEK)
   666  
   667  	// extract sender public key and try Unwrap using extracted key
   668  	senderPubKey, err := keyio.ExtractPrimaryPublicKey(senderKH)
   669  	require.NoError(t, err)
   670  
   671  	crv, err := hybrid.GetCurve(senderPubKey.Curve)
   672  	require.NoError(t, err)
   673  
   674  	senderECPubKey := &ecdsa.PublicKey{
   675  		Curve: crv,
   676  		X:     new(big.Int).SetBytes(senderPubKey.X),
   677  		Y:     new(big.Int).SetBytes(senderPubKey.Y),
   678  	}
   679  
   680  	uCEK, err = c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderECPubKey))
   681  	require.NoError(t, err)
   682  	require.EqualValues(t, cek, uCEK)
   683  }
   684  
   685  func TestCrypto_ECDH1PU_Wrap_Unwrap_Key_Using_CryptoPubKey_as_SenderKey(t *testing.T) {
   686  	recipientKeyHandle, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate())
   687  	require.NoError(t, err)
   688  
   689  	recipientKey, err := keyio.ExtractPrimaryPublicKey(recipientKeyHandle)
   690  	require.NoError(t, err)
   691  
   692  	senderKH, err := keyset.NewHandle(ecdh.NISTP256ECDHKWKeyTemplate())
   693  	require.NoError(t, err)
   694  
   695  	c, err := New()
   696  	require.NoError(t, err)
   697  
   698  	cek := random.GetRandomBytes(uint32(crypto.DefKeySize * 2))
   699  	apu := random.GetRandomBytes(uint32(10)) // or sender name
   700  	apv := random.GetRandomBytes(uint32(10)) // or recipient name
   701  
   702  	// extract sender public key as crypto.Public key to be used in WithSender()
   703  	senderPubKey, err := keyio.ExtractPrimaryPublicKey(senderKH)
   704  	require.NoError(t, err)
   705  
   706  	// test WrapKey with extacted crypto.PublicKey above directly
   707  	// WrapKey() only accepts senderKH as keyset.Handle because it will use its private key.
   708  	wrappedKey, err := c.WrapKey(cek, apu, apv, recipientKey, cryptoapi.WithSender(senderKH))
   709  	require.NoError(t, err)
   710  	require.NotEmpty(t, wrappedKey.EncryptedCEK)
   711  	require.NotEmpty(t, wrappedKey.EPK)
   712  	require.EqualValues(t, wrappedKey.APU, apu)
   713  	require.EqualValues(t, wrappedKey.APV, apv)
   714  	require.Equal(t, wrappedKey.Alg, ECDH1PUA256KWAlg)
   715  
   716  	// UnwrapKey require sender public key used here or keyset.Handle which was tested in the previous function above
   717  	uCEK, err := c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderPubKey))
   718  	require.NoError(t, err)
   719  	require.EqualValues(t, cek, uCEK)
   720  
   721  	crv, err := hybrid.GetCurve(senderPubKey.Curve)
   722  	require.NoError(t, err)
   723  
   724  	senderECPubKey := &ecdsa.PublicKey{
   725  		Curve: crv,
   726  		X:     new(big.Int).SetBytes(senderPubKey.X),
   727  		Y:     new(big.Int).SetBytes(senderPubKey.Y),
   728  	}
   729  
   730  	uCEK, err = c.UnwrapKey(wrappedKey, recipientKeyHandle, cryptoapi.WithSender(senderECPubKey))
   731  	require.NoError(t, err)
   732  	require.EqualValues(t, cek, uCEK)
   733  }
   734  
   735  func TestBBSCrypto_SignVerify_DeriveProofVerifyProof(t *testing.T) {
   736  	c := Crypto{}
   737  	msg := [][]byte{
   738  		[]byte(testMessage + "0"), []byte(testMessage + "1"), []byte(testMessage + "2"),
   739  		[]byte(testMessage + "3"), []byte(testMessage + "4"), []byte(testMessage + "5"),
   740  	}
   741  
   742  	var (
   743  		s     []byte
   744  		pubKH *keyset.Handle
   745  		badKH *keyset.Handle
   746  	)
   747  
   748  	t.Run("test with BBS+ signature", func(t *testing.T) {
   749  		kh, err := keyset.NewHandle(bbs.BLS12381G2KeyTemplate())
   750  		require.NoError(t, err)
   751  
   752  		badKH, err = keyset.NewHandle(tinkaead.KMSEnvelopeAEADKeyTemplate("babdUrl", nil))
   753  		require.NoError(t, err)
   754  
   755  		s, err = c.SignMulti(msg, kh)
   756  		require.NoError(t, err)
   757  
   758  		// sign with nil key handle - should fail
   759  		_, err = c.SignMulti(msg, nil)
   760  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   761  
   762  		// sign with bad key type - should fail
   763  		_, err = c.SignMulti(msg, "bad key type")
   764  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   765  
   766  		// sign with empty messages - should fail
   767  		_, err = c.SignMulti([][]byte{}, kh)
   768  		require.EqualError(t, err, "BBS+ sign msg: messages are not defined")
   769  
   770  		// sign with bad key handle - should fail
   771  		_, err = c.SignMulti(msg, badKH)
   772  		require.Error(t, err)
   773  
   774  		// get corresponding public key handle to verify
   775  		pubKH, err = kh.Public()
   776  		require.NoError(t, err)
   777  
   778  		err = c.VerifyMulti(msg, s, nil)
   779  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   780  
   781  		err = c.VerifyMulti(msg, s, "bad key type")
   782  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   783  
   784  		err = c.VerifyMulti(msg, s, badKH)
   785  		require.Error(t, err)
   786  
   787  		err = c.VerifyMulti([][]byte{}, s, pubKH)
   788  		require.EqualError(t, err, "BBS+ verify msg: bbs_verifier_factory: invalid signature")
   789  
   790  		err = c.VerifyMulti(msg, s, pubKH)
   791  		require.NoError(t, err)
   792  	})
   793  
   794  	require.NotEmpty(t, s)
   795  
   796  	t.Run("test with BBS+ proof", func(t *testing.T) {
   797  		revealedIndexes := []int{0, 2}
   798  		nonce := make([]byte, 32)
   799  
   800  		_, err := rand.Read(nonce)
   801  		require.NoError(t, err)
   802  
   803  		_, err = c.DeriveProof(msg, s, nonce, revealedIndexes, nil)
   804  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   805  
   806  		_, err = c.DeriveProof(msg, s, nonce, revealedIndexes, "bad key type")
   807  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   808  
   809  		_, err = c.DeriveProof(msg, s, nonce, revealedIndexes, badKH)
   810  		require.Error(t, err)
   811  
   812  		_, err = c.DeriveProof([][]byte{}, s, nonce, revealedIndexes, pubKH)
   813  		require.EqualError(t, err, "verify proof msg: bbs_verifier_factory: invalid signature proof")
   814  
   815  		proof, err := c.DeriveProof(msg, s, nonce, revealedIndexes, pubKH)
   816  		require.NoError(t, err)
   817  
   818  		err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, nil)
   819  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   820  
   821  		err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, "bad key type")
   822  		require.EqualError(t, err, errBadKeyHandleFormat.Error())
   823  
   824  		err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, badKH)
   825  		require.Error(t, err)
   826  
   827  		err = c.VerifyProof([][]byte{msg[3], msg[4]}, proof, nonce, pubKH)
   828  		require.EqualError(t, err, "verify proof msg: bbs_verifier_factory: invalid signature proof")
   829  
   830  		err = c.VerifyProof([][]byte{msg[0], msg[2]}, proof, nonce, pubKH)
   831  		require.NoError(t, err)
   832  	})
   833  }