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

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package composite
     8  
     9  import (
    10  	"encoding/hex"
    11  	"encoding/json"
    12  	"fmt"
    13  	"testing"
    14  
    15  	"github.com/golang/protobuf/proto"
    16  	"github.com/google/tink/go/aead"
    17  	subtleaead "github.com/google/tink/go/aead/subtle"
    18  	"github.com/google/tink/go/mac"
    19  	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
    20  	"github.com/google/tink/go/signature"
    21  	"github.com/google/tink/go/subtle/random"
    22  	"github.com/stretchr/testify/require"
    23  	"golang.org/x/crypto/chacha20poly1305"
    24  	"golang.org/x/crypto/poly1305"
    25  
    26  	cbchmacaead "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead"
    27  	subtlecbchmacaead "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/aead/subtle"
    28  	aeadpb "github.com/trustbloc/kms-go/crypto/tinkcrypto/primitive/proto/aes_cbc_hmac_aead_go_proto"
    29  )
    30  
    31  func newKeyTemplates() ([]*tinkpb.KeyTemplate, []int) {
    32  	twoKeys := 2
    33  
    34  	return []*tinkpb.KeyTemplate{
    35  			aead.ChaCha20Poly1305KeyTemplate(),
    36  			aead.XChaCha20Poly1305KeyTemplate(),
    37  			aead.AES256GCMKeyTemplate(),
    38  			aead.AES128GCMKeyTemplate(),
    39  			cbchmacaead.AES128CBCHMACSHA256KeyTemplate(),
    40  			cbchmacaead.AES192CBCHMACSHA384KeyTemplate(),
    41  			cbchmacaead.AES256CBCHMACSHA384KeyTemplate(),
    42  			cbchmacaead.AES256CBCHMACSHA512KeyTemplate(),
    43  		},
    44  		[]int{
    45  			chacha20poly1305.KeySize,
    46  			chacha20poly1305.KeySize,
    47  			subtlecbchmacaead.AES256Size,
    48  			subtlecbchmacaead.AES128Size,
    49  			subtlecbchmacaead.AES128Size * twoKeys,
    50  			subtlecbchmacaead.AES192Size * twoKeys,
    51  			subtlecbchmacaead.AES256Size + subtlecbchmacaead.AES192Size,
    52  			subtlecbchmacaead.AES256Size * twoKeys,
    53  		}
    54  }
    55  
    56  func TestCipherGetters(t *testing.T) {
    57  	keyTemplates, _ := newKeyTemplates()
    58  
    59  	for _, c := range keyTemplates {
    60  		rDem, err := NewRegisterCompositeAEADEncHelper(c)
    61  		require.NoError(t, err, "error generating a content encryption helper")
    62  
    63  		switch rDem.encKeyURL {
    64  		case AESCBCHMACAEADTypeURL:
    65  			require.EqualValues(t, subtlecbchmacaead.AESCBCIVSize, rDem.GetIVSize())
    66  
    67  			format := new(aeadpb.AesCbcHmacAeadKeyFormat)
    68  			err = proto.Unmarshal(c.Value, format)
    69  			require.NoError(t, err)
    70  
    71  			require.EqualValues(t, format.HmacKeyFormat.Params.TagSize, rDem.GetTagSize())
    72  		case AESGCMTypeURL:
    73  			require.EqualValues(t, subtleaead.AESGCMIVSize, rDem.GetIVSize())
    74  			require.EqualValues(t, subtleaead.AESGCMTagSize, rDem.GetTagSize())
    75  		case ChaCha20Poly1305TypeURL:
    76  			require.EqualValues(t, chacha20poly1305.NonceSize, rDem.GetIVSize())
    77  			require.EqualValues(t, poly1305.TagSize, rDem.GetTagSize())
    78  		case XChaCha20Poly1305TypeURL:
    79  			require.EqualValues(t, chacha20poly1305.NonceSizeX, rDem.GetIVSize())
    80  			require.EqualValues(t, poly1305.TagSize, rDem.GetTagSize())
    81  		}
    82  	}
    83  }
    84  
    85  func TestCipherGettersFailures(t *testing.T) {
    86  	tests := []struct {
    87  		name       string
    88  		typeURL    string
    89  		formatName string
    90  	}{
    91  		{
    92  			name:       "AESCBCHMAC AEAD error",
    93  			typeURL:    AESCBCHMACAEADTypeURL,
    94  			formatName: "cbcHMACKeyFormat",
    95  		},
    96  		{
    97  			name:       "AESGCM AEAD error",
    98  			typeURL:    AESGCMTypeURL,
    99  			formatName: "gcmKeyFormat",
   100  		},
   101  		{
   102  			name:       "C20P AEAD error",
   103  			typeURL:    ChaCha20Poly1305TypeURL,
   104  			formatName: "chachaKeyFormat",
   105  		},
   106  		{
   107  			name:       "XC20P AEAD error",
   108  			typeURL:    XChaCha20Poly1305TypeURL,
   109  			formatName: "xChachaKeyFormat",
   110  		},
   111  	}
   112  
   113  	t.Parallel()
   114  
   115  	for _, tt := range tests {
   116  		tc := tt
   117  		t.Run(tc.name, func(t *testing.T) {
   118  			c := &tinkpb.KeyTemplate{
   119  				TypeUrl:          tc.typeURL,
   120  				Value:            []byte("bad serialized key"),
   121  				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
   122  			}
   123  
   124  			rDem, err := NewRegisterCompositeAEADEncHelper(c)
   125  			require.Error(t, err)
   126  			require.Contains(t, err.Error(), fmt.Sprintf("compositeAEADEncHelper: failed to unmarshal %s", tc.formatName))
   127  			require.Empty(t, rDem)
   128  		})
   129  	}
   130  }
   131  
   132  func TestUnsupportedKeyTemplates(t *testing.T) {
   133  	uTemplates := []*tinkpb.KeyTemplate{
   134  		signature.ECDSAP256KeyTemplate(),
   135  		mac.HMACSHA256Tag256KeyTemplate(),
   136  		{TypeUrl: "some url", Value: []byte{0}},
   137  		{TypeUrl: AESGCMTypeURL},
   138  		{TypeUrl: AESGCMTypeURL, Value: []byte("123")},
   139  	}
   140  
   141  	for _, l := range uTemplates {
   142  		_, err := NewRegisterCompositeAEADEncHelper(l)
   143  		require.Errorf(t, err, "unsupported key template %s should have generated error: %v", l)
   144  	}
   145  }
   146  
   147  func TestAead(t *testing.T) {
   148  	keyTemplates, keysSizes := newKeyTemplates()
   149  
   150  	for i, c := range keyTemplates {
   151  		pt := random.GetRandomBytes(20)
   152  		ad := random.GetRandomBytes(20)
   153  		rEnc, err := NewRegisterCompositeAEADEncHelper(c)
   154  		require.NoError(t, err, "error generating a content encryption helper")
   155  
   156  		keySize := uint32(keysSizes[i])
   157  		sk := random.GetRandomBytes(keySize)
   158  		a, err := rEnc.GetAEAD(sk)
   159  		require.NoError(t, err, "error getting AEAD primitive")
   160  
   161  		ct, err := a.Encrypt(pt, ad)
   162  		require.NoError(t, err, "error encrypting")
   163  
   164  		dt, err := a.Decrypt(ct, ad)
   165  		require.NoError(t, err, "error decrypting")
   166  
   167  		require.EqualValuesf(t, pt, dt, "decryption not inverse of encryption,\n want :%s,\n got: %s",
   168  			hex.Dump(pt), hex.Dump(dt))
   169  
   170  		// shorter symmetric key
   171  		sk = random.GetRandomBytes(keySize - 1)
   172  		_, err = rEnc.GetAEAD(sk)
   173  		require.Error(t, err, "retrieving AEAD primitive should have failed")
   174  
   175  		// longer symmetric key
   176  		sk = random.GetRandomBytes(keySize + 1)
   177  		_, err = rEnc.GetAEAD(sk)
   178  		require.Error(t, err, "retrieving AEAD primitive should have failed")
   179  
   180  		// set bad keyData
   181  		tmpKeyData := rEnc.keyData
   182  		rEnc.keyData = []byte{0, 1, 3}
   183  		sk = random.GetRandomBytes(keySize)
   184  		_, err = rEnc.GetAEAD(sk)
   185  		require.Error(t, err, "retrieving AEAD primitive should have failed")
   186  
   187  		// set bad key URL
   188  		rEnc.keyData = tmpKeyData
   189  		rEnc.encKeyURL = "bad.url"
   190  		_, err = rEnc.GetAEAD(sk)
   191  		require.Error(t, err, "retrieving AEAD primitive should have failed")
   192  	}
   193  }
   194  
   195  func TestBuildEncDecData(t *testing.T) {
   196  	rEnc, err := NewRegisterCompositeAEADEncHelper(aead.AES256GCMKeyTemplate())
   197  	require.NoError(t, err)
   198  
   199  	refEncData := &EncryptedData{
   200  		IV:         random.GetRandomBytes(uint32(rEnc.GetIVSize())),
   201  		Ciphertext: []byte("ciphertext"),
   202  		Tag:        random.GetRandomBytes(uint32(rEnc.GetTagSize())),
   203  	}
   204  
   205  	preBuiltCT := append(refEncData.IV, refEncData.Ciphertext...)
   206  	preBuiltCT = append(preBuiltCT, refEncData.Tag...)
   207  
   208  	// test BuildDecData
   209  	finalCT := rEnc.BuildDecData(refEncData)
   210  	require.EqualValues(t, preBuiltCT, finalCT)
   211  
   212  	// test BuildEncData
   213  	mEncData, err := rEnc.BuildEncData(preBuiltCT)
   214  	require.NoError(t, err)
   215  
   216  	mRefEncData, err := json.Marshal(refEncData)
   217  	require.NoError(t, err)
   218  	require.EqualValues(t, mRefEncData, mEncData)
   219  }