blob: 7690a094fb4a64e30968b33447d5a23c6351b69a [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package tink_test
import (
"testing"
"github.com/golang/protobuf/proto"
"github.com/google/tink/go/aead"
"github.com/google/tink/go/mac"
subtleAead "github.com/google/tink/go/subtle/aead"
subtleMac "github.com/google/tink/go/subtle/mac"
"github.com/google/tink/go/testutil"
"github.com/google/tink/go/tink"
gcmpb "github.com/google/tink/proto/aes_gcm_go_proto"
commonpb "github.com/google/tink/proto/common_go_proto"
hmacpb "github.com/google/tink/proto/hmac_go_proto"
tinkpb "github.com/google/tink/proto/tink_go_proto"
)
func TestBasic(t *testing.T) {
// try to put a HmacKeyManager
hmacManager := mac.NewHmacKeyManager()
typeURL := mac.HmacTypeURL
tink.RegisterKeyManager(hmacManager)
tmp, existed := tink.GetKeyManager(typeURL)
if existed != nil {
t.Errorf("a HmacKeyManager should be found")
}
var _ = tmp.(*mac.HmacKeyManager)
// Get type url that doesn't exist
if _, existed := tink.GetKeyManager("some url"); existed == nil {
t.Errorf("unknown typeURL shouldn't exist in the map")
}
}
func setupRegistryTests() {
_, err := mac.RegisterStandardKeyTypes()
if err != nil {
panic("cannot register Mac key types")
}
_, err = aead.RegisterStandardKeyTypes()
if err != nil {
panic("cannot register Aead key types")
}
}
func TestKeyManagerRegistration(t *testing.T) {
var km tink.KeyManager
var err error
// register mac and aead types.
setupRegistryTests()
// get HmacKeyManager
km, err = tink.GetKeyManager(mac.HmacTypeURL)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var _ *mac.HmacKeyManager = km.(*mac.HmacKeyManager)
// get AesGcmKeyManager
km, err = tink.GetKeyManager(aead.AesGcmTypeURL)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var _ *aead.AesGcmKeyManager = km.(*aead.AesGcmKeyManager)
// some random typeurl
if _, err = tink.GetKeyManager("some url"); err == nil {
t.Errorf("expect an error when a type url doesn't exist in the registry")
}
}
func TestKeyManagerRegistrationWithCollision(t *testing.T) {
// register mac and aead types.
setupRegistryTests()
// dummyKeyManager's typeURL is equal to that of AesGcm
var dummyKeyManager tink.KeyManager = new(testutil.DummyAeadKeyManager)
// this should not overwrite the existing manager.
ok, err := tink.RegisterKeyManager(dummyKeyManager)
if ok || err != nil {
t.Errorf("AES_GCM_TYPE_URL shouldn't be registered again")
}
km, err := tink.GetKeyManager(aead.AesGcmTypeURL)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var _ *aead.AesGcmKeyManager = km.(*aead.AesGcmKeyManager)
}
func TestNewKeyData(t *testing.T) {
setupRegistryTests()
// new Keydata from a Hmac KeyTemplate
keyData, err := tink.NewKeyData(mac.HmacSha256Tag128KeyTemplate())
if err != nil {
t.Errorf("unexpected error: %s", err)
}
if keyData.TypeUrl != mac.HmacTypeURL {
t.Errorf("invalid key data")
}
key := new(hmacpb.HmacKey)
if err := proto.Unmarshal(keyData.Value, key); err != nil {
t.Errorf("unexpected error when unmarshal HmacKey: %s", err)
}
// nil
if _, err := tink.NewKeyData(nil); err == nil {
t.Errorf("expect an error when key template is nil")
}
// unregistered type url
template := &tinkpb.KeyTemplate{TypeUrl: "some url", Value: []byte{0}}
if _, err := tink.NewKeyData(template); err == nil {
t.Errorf("expect an error when key template contains unregistered typeURL")
}
}
func TestNewKeyFromKeyTemplate(t *testing.T) {
setupRegistryTests()
// aead template
aesGcmTemplate := aead.Aes128GcmKeyTemplate()
key, err := tink.NewKeyFromKeyTemplate(aesGcmTemplate)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var aesGcmKey *gcmpb.AesGcmKey = key.(*gcmpb.AesGcmKey)
aesGcmFormat := new(gcmpb.AesGcmKeyFormat)
if err := proto.Unmarshal(aesGcmTemplate.Value, aesGcmFormat); err != nil {
t.Errorf("unexpected error: %s", err)
}
if aesGcmFormat.KeySize != uint32(len(aesGcmKey.KeyValue)) {
t.Errorf("key doesn't match template")
}
//nil
if _, err := tink.NewKeyFromKeyTemplate(nil); err == nil {
t.Errorf("expect an error when key template is nil")
}
// unregistered type url
template := &tinkpb.KeyTemplate{TypeUrl: "some url", Value: []byte{0}}
if _, err := tink.NewKeyFromKeyTemplate(template); err == nil {
t.Errorf("expect an error when key template is not registered")
}
}
func TestNewKeyFromKeyFormat(t *testing.T) {
setupRegistryTests()
// use aes-gcm key format
format := aead.NewAesGcmKeyFormat(16)
key, err := tink.NewKeyFromKeyFormat(aead.AesGcmTypeURL, format)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var aesGcmKey *gcmpb.AesGcmKey = key.(*gcmpb.AesGcmKey)
if uint32(len(aesGcmKey.KeyValue)) != format.KeySize {
t.Errorf("key doesn't match format")
}
// unregistered url
if _, err := tink.NewKeyFromKeyFormat("some url", format); err == nil {
t.Errorf("expect an error when typeURL has not been registered")
}
// unmatched url
if _, err := tink.NewKeyFromKeyFormat(mac.HmacTypeURL, format); err == nil {
t.Errorf("expect an error when typeURL doesn't match format")
}
// nil format
if _, err := tink.NewKeyFromKeyFormat(mac.HmacTypeURL, nil); err == nil {
t.Errorf("expect an error when format is nil")
}
}
func TestGetPrimitiveFromKey(t *testing.T) {
setupRegistryTests()
// hmac key
key := testutil.NewHmacKey(commonpb.HashType_SHA256, 16)
p, err := tink.GetPrimitiveFromKey(mac.HmacTypeURL, key)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var _ *subtleMac.Hmac = p.(*subtleMac.Hmac)
// unregistered url
if _, err := tink.GetPrimitiveFromKey("some url", key); err == nil {
t.Errorf("expect an error when typeURL has not been registered")
}
// unmatched url
if _, err := tink.GetPrimitiveFromKey(aead.AesGcmTypeURL, key); err == nil {
t.Errorf("expect an error when typeURL doesn't match key")
}
// nil key
if _, err := tink.GetPrimitiveFromKey(aead.AesGcmTypeURL, nil); err == nil {
t.Errorf("expect an error when key is nil")
}
}
func TestGetPrimitiveFromKeyData(t *testing.T) {
setupRegistryTests()
// hmac keydata
keyData := testutil.NewHmacKeyData(commonpb.HashType_SHA256, 16)
p, err := tink.GetPrimitiveFromKeyData(keyData)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var _ *subtleMac.Hmac = p.(*subtleMac.Hmac)
// unregistered url
keyData.TypeUrl = "some url"
if _, err := tink.GetPrimitiveFromKeyData(keyData); err == nil {
t.Errorf("expect an error when typeURL has not been registered")
}
// unmatched url
keyData.TypeUrl = aead.AesGcmTypeURL
if _, err := tink.GetPrimitiveFromKeyData(keyData); err == nil {
t.Errorf("expect an error when typeURL doesn't match key")
}
// nil
if _, err := tink.GetPrimitiveFromKeyData(nil); err == nil {
t.Errorf("expect an error when key data is nil")
}
}
func TestGetPrimitiveFromSerializedKey(t *testing.T) {
setupRegistryTests()
// hmac key
key := testutil.NewHmacKey(commonpb.HashType_SHA256, 16)
serializedKey, _ := proto.Marshal(key)
p, err := tink.GetPrimitiveFromSerializedKey(mac.HmacTypeURL, serializedKey)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var _ *subtleMac.Hmac = p.(*subtleMac.Hmac)
// unregistered url
if _, err := tink.GetPrimitiveFromSerializedKey("some url", serializedKey); err == nil {
t.Errorf("expect an error when typeURL has not been registered")
}
// unmatched url
if _, err := tink.GetPrimitiveFromSerializedKey(aead.AesGcmTypeURL, serializedKey); err == nil {
t.Errorf("expect an error when typeURL doesn't match key")
}
// void key
if _, err := tink.GetPrimitiveFromSerializedKey(aead.AesGcmTypeURL, nil); err == nil {
t.Errorf("expect an error when key is nil")
}
if _, err := tink.GetPrimitiveFromSerializedKey(aead.AesGcmTypeURL, []byte{}); err == nil {
t.Errorf("expect an error when key is nil")
}
if _, err := tink.GetPrimitiveFromSerializedKey(aead.AesGcmTypeURL, []byte{0}); err == nil {
t.Errorf("expect an error when key is nil")
}
}
func TestGetPrimitives(t *testing.T) {
setupRegistryTests()
// valid input
template1 := aead.Aes128GcmKeyTemplate()
template2 := aead.Aes256GcmKeyTemplate()
keyData1, _ := tink.NewKeyData(template1)
keyData2, _ := tink.NewKeyData(template2)
keyset := tink.CreateKeyset(2, []*tinkpb.Keyset_Key{
tink.CreateKey(keyData1, tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK),
tink.CreateKey(keyData2, tinkpb.KeyStatusType_ENABLED, 2, tinkpb.OutputPrefixType_TINK),
})
handle, _ := tink.CleartextKeysetHandle().ParseKeyset(keyset)
ps, err := tink.GetPrimitives(handle)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var aesGcm *subtleAead.AesGcm = ps.Primary().Primitive().(*subtleAead.AesGcm)
if len(aesGcm.Key) != 32 {
t.Errorf("primitive doesn't match input keyset handle")
}
// custom manager
customManager := new(testutil.DummyAeadKeyManager)
ps, err = tink.GetPrimitivesWithCustomManager(handle, customManager)
if err != nil {
t.Errorf("unexpected error: %s", err)
}
var _ *testutil.DummyAead = ps.Primary().Primitive().(*testutil.DummyAead)
// keysethandle is nil
if _, err := tink.GetPrimitives(nil); err == nil {
t.Errorf("expect an error when keysethandle is nil")
}
// keyset is empty
keyset = tink.CreateKeyset(1, []*tinkpb.Keyset_Key{})
handle, _ = tink.CleartextKeysetHandle().ParseKeyset(keyset)
if _, err := tink.GetPrimitives(handle); err == nil {
t.Errorf("expect an error when keyset is empty")
}
keyset = tink.CreateKeyset(1, nil)
handle, _ = tink.CleartextKeysetHandle().ParseKeyset(keyset)
if _, err := tink.GetPrimitives(handle); err == nil {
t.Errorf("expect an error when keyset is empty")
}
// no primary key
keyset = tink.CreateKeyset(3, []*tinkpb.Keyset_Key{
tink.CreateKey(keyData1, tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK),
tink.CreateKey(keyData2, tinkpb.KeyStatusType_ENABLED, 2, tinkpb.OutputPrefixType_TINK),
})
handle, _ = tink.CleartextKeysetHandle().ParseKeyset(keyset)
if _, err := tink.GetPrimitives(handle); err == nil {
t.Errorf("expect an error when there is no primary key")
}
// there is primary key but it is disabled
keyset = tink.CreateKeyset(1, []*tinkpb.Keyset_Key{
tink.CreateKey(keyData1, tinkpb.KeyStatusType_DISABLED, 1, tinkpb.OutputPrefixType_TINK),
tink.CreateKey(keyData2, tinkpb.KeyStatusType_ENABLED, 2, tinkpb.OutputPrefixType_TINK),
})
handle, _ = tink.CleartextKeysetHandle().ParseKeyset(keyset)
if _, err := tink.GetPrimitives(handle); err == nil {
t.Errorf("expect an error when primary key is disabled")
}
// multiple primary keys
keyset = tink.CreateKeyset(1, []*tinkpb.Keyset_Key{
tink.CreateKey(keyData1, tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK),
tink.CreateKey(keyData2, tinkpb.KeyStatusType_ENABLED, 1, tinkpb.OutputPrefixType_TINK),
})
handle, _ = tink.CleartextKeysetHandle().ParseKeyset(keyset)
if _, err := tink.GetPrimitives(handle); err == nil {
t.Errorf("expect an error when there are multiple primary keys")
}
}