From 8eb30841184d49f1981a6983a327a349e9f8318b Mon Sep 17 00:00:00 2001 From: Moreno Ambrosin Date: Fri, 10 Jan 2025 01:39:27 -0800 Subject: [PATCH] Create primitive from proto key serialization in XChaCha20Poly1305 key manager PiperOrigin-RevId: 713959133 Change-Id: Iec0c82c3559c83a46e8114721be8b073789e14a0 --- aead/xchacha20poly1305/key_manager.go | 27 ++++++---- aead/xchacha20poly1305/key_manager_test.go | 61 ++++++++++++---------- 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/aead/xchacha20poly1305/key_manager.go b/aead/xchacha20poly1305/key_manager.go index 632a759..06fa0eb 100644 --- a/aead/xchacha20poly1305/key_manager.go +++ b/aead/xchacha20poly1305/key_manager.go @@ -20,11 +20,12 @@ import ( "golang.org/x/crypto/chacha20poly1305" "google.golang.org/protobuf/proto" - "github.com/tink-crypto/tink-go/v2/aead/subtle" "github.com/tink-crypto/tink-go/v2/core/registry" + "github.com/tink-crypto/tink-go/v2/internal/protoserialization" "github.com/tink-crypto/tink-go/v2/keyset" "github.com/tink-crypto/tink-go/v2/subtle/random" + tinkpb "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto" tpb "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto" xpb "github.com/tink-crypto/tink-go/v2/proto/xchacha20_poly1305_go_proto" ) @@ -44,19 +45,25 @@ var _ registry.KeyManager = (*keyManager)(nil) // Primitive constructs a XChaCha20Poly1305 for the given serialized // [xpb.XChaCha20Poly1305Key]. func (km *keyManager) Primitive(serializedKey []byte) (any, error) { - if len(serializedKey) == 0 { - return nil, fmt.Errorf("xchacha20poly1305_key_manager: empty key") - } - key := new(xpb.XChaCha20Poly1305Key) - if err := proto.Unmarshal(serializedKey, key); err != nil { - return nil, fmt.Errorf("xchacha20poly1305_key_manager: invalid key") + keySerialization, err := protoserialization.NewKeySerialization(&tinkpb.KeyData{ + TypeUrl: typeURL, + Value: serializedKey, + KeyMaterialType: tinkpb.KeyData_SYMMETRIC, + }, tinkpb.OutputPrefixType_RAW, 0) + if err != nil { + return nil, err } - if err := km.validateKey(key); err != nil { + key, err := protoserialization.ParseKey(keySerialization) + if err != nil { return nil, err } - ret, err := subtle.NewXChaCha20Poly1305(key.KeyValue) + xChaCha20Poly1305Key, ok := key.(*Key) + if !ok { + return nil, fmt.Errorf("xchacha20poly1305_key_manager: invalid key type: got %T, want %T", key, (*Key)(nil)) + } + ret, err := newAEAD(xChaCha20Poly1305Key) if err != nil { - return nil, fmt.Errorf("xchacha20poly1305_key_manager: cannot create new primitive: %v", err) + return nil, fmt.Errorf("xchacha20poly1305_key_manager: %v", err) } return ret, nil } diff --git a/aead/xchacha20poly1305/key_manager_test.go b/aead/xchacha20poly1305/key_manager_test.go index 119c60c..9ec5e60 100644 --- a/aead/xchacha20poly1305/key_manager_test.go +++ b/aead/xchacha20poly1305/key_manager_test.go @@ -23,10 +23,12 @@ import ( "github.com/google/go-cmp/cmp" "golang.org/x/crypto/chacha20poly1305" "google.golang.org/protobuf/proto" + aeadtestutil "github.com/tink-crypto/tink-go/v2/aead/internal/testutil" "github.com/tink-crypto/tink-go/v2/core/registry" "github.com/tink-crypto/tink-go/v2/internal/internalregistry" "github.com/tink-crypto/tink-go/v2/subtle/random" "github.com/tink-crypto/tink-go/v2/testutil" + "github.com/tink-crypto/tink-go/v2/tink" "github.com/tink-crypto/tink-go/v2/aead/subtle" tpb "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto" @@ -54,8 +56,19 @@ func TestKeyManagerGetPrimitive(t *testing.T) { if err != nil { t.Errorf("km.Primitive(%v) = %v; want nil", serializedKey, err) } - if err := validateXChaCha20Poly1305Primitive(p, key); err != nil { - t.Errorf("validateXChaCha20Poly1305Primitive(p, key) = %v; want nil", err) + aead, ok := p.(tink.AEAD) + if !ok { + t.Fatalf("km.Primitive(serializedKey) = %T, want tink.AEAD", p) + } + expectedAEAD, err := subtle.NewXChaCha20Poly1305(key.GetKeyValue()) + if err != nil { + t.Fatalf("subtle.NewXChaCha20Poly1305(%v) err = %v, want nil", key.GetKeyValue(), err) + } + if err := aeadtestutil.EncryptDecrypt(aead, expectedAEAD); err != nil { + t.Errorf("aeadtestutil.EncryptDecrypt(aead, expectedAEAD) = %v; want nil", err) + } + if err := aeadtestutil.EncryptDecrypt(expectedAEAD, aead); err != nil { + t.Errorf("aeadtestutil.EncryptDecrypt(expectedAEAD, aead) = %v; want nil", err) } } @@ -139,9 +152,19 @@ func TestKeyManagerNewKeyData(t *testing.T) { if err != nil { t.Errorf("registry.PrimitiveFromKeyData(kd) err = %v, want nil", err) } - _, ok := p.(*subtle.XChaCha20Poly1305) + aead, ok := p.(tink.AEAD) if !ok { - t.Error("registry.PrimitiveFromKeyData(kd) did not return a XChaCha20Poly1305 primitive") + t.Fatalf("registry.PrimitiveFromKeyData(kd) = %T, want tink.AEAD", p) + } + expectedAEAD, err := subtle.NewXChaCha20Poly1305(key.GetKeyValue()) + if err != nil { + t.Fatalf("subtle.NewXChaCha20Poly1305(%v) err = %v, want nil", key.GetKeyValue(), err) + } + if err := aeadtestutil.EncryptDecrypt(aead, expectedAEAD); err != nil { + t.Errorf("aeadtestutil.EncryptDecrypt(aead, expectedAEAD) = %v; want nil", err) + } + if err := aeadtestutil.EncryptDecrypt(expectedAEAD, aead); err != nil { + t.Errorf("aeadtestutil.EncryptDecrypt(expectedAEAD, aead) = %v; want nil", err) } } @@ -301,38 +324,18 @@ func TestKeyManagerDeriveKeyFailsWithInsufficientRandomness(t *testing.T) { } } -func validateXChaCha20Poly1305Primitive(p any, key *xpb.XChaCha20Poly1305Key) error { - cipher := p.(*subtle.XChaCha20Poly1305) - - // Try to encrypt and decrypt. - pt := random.GetRandomBytes(32) - aad := random.GetRandomBytes(32) - ct, err := cipher.Encrypt(pt, aad) - if err != nil { - return fmt.Errorf("encryption failed") - } - decrypted, err := cipher.Decrypt(ct, aad) - if err != nil { - return fmt.Errorf("decryption failed") - } - if !bytes.Equal(decrypted, pt) { - return fmt.Errorf("decryption failed") - } - return nil -} - func validateXChaCha20Poly1305Key(key *xpb.XChaCha20Poly1305Key) error { - if key.Version != testutil.XChaCha20Poly1305KeyVersion { + if key.GetVersion() != testutil.XChaCha20Poly1305KeyVersion { return fmt.Errorf("incorrect key version: keyVersion != %d", testutil.XChaCha20Poly1305KeyVersion) } - if uint32(len(key.KeyValue)) != chacha20poly1305.KeySize { + if uint32(len(key.GetKeyValue())) != chacha20poly1305.KeySize { return fmt.Errorf("incorrect key size: keySize != %d", chacha20poly1305.KeySize) } // Try to encrypt and decrypt. - p, err := subtle.NewXChaCha20Poly1305(key.KeyValue) + p, err := subtle.NewXChaCha20Poly1305(key.GetKeyValue()) if err != nil { - return fmt.Errorf("invalid key: %v", key.KeyValue) + return fmt.Errorf("invalid key: %v", key.GetKeyValue()) } - return validateXChaCha20Poly1305Primitive(p, key) + return aeadtestutil.EncryptDecrypt(p, p) }