From 784e870f9b525bf107ba3b4511708ec400a1a549 Mon Sep 17 00:00:00 2001 From: Moreno Ambrosin Date: Tue, 26 Nov 2024 05:25:42 -0800 Subject: [PATCH] Register proto serialization for AES-GCM-SIV to the global registry PiperOrigin-RevId: 700308124 Change-Id: Ic50dd63e357116a1f5c8f68b34fc1916a6d0c04a --- aead/aead.go | 1 + aead/aesgcmsiv/aesgcmsiv.go | 36 ++++++++ aead/aesgcmsiv/aesgcmsiv_test.go | 141 +++++++++++++++++++++++++++++++ aead/aesgcmsiv/key.go | 3 - 4 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 aead/aesgcmsiv/aesgcmsiv.go create mode 100644 aead/aesgcmsiv/aesgcmsiv_test.go diff --git a/aead/aead.go b/aead/aead.go index b2670cc..cb898b8 100644 --- a/aead/aead.go +++ b/aead/aead.go @@ -22,6 +22,7 @@ import ( _ "github.com/tink-crypto/tink-go/v2/aead/aesctrhmac" // To register the AES-CTR-HMAC key manager. _ "github.com/tink-crypto/tink-go/v2/aead/aesgcm" // To register the AES-GCM key manager, parser and serializer. + _ "github.com/tink-crypto/tink-go/v2/aead/aesgcmsiv" // To register the AES-GCM-SIV key parser and serializer. _ "github.com/tink-crypto/tink-go/v2/aead/chacha20poly1305" // To register the ChaCha20Poly1305 key manager, parser and serializer. _ "github.com/tink-crypto/tink-go/v2/aead/xchacha20poly1305" // To register the XChaCha20Poly1305 key manager. "github.com/tink-crypto/tink-go/v2/core/registry" diff --git a/aead/aesgcmsiv/aesgcmsiv.go b/aead/aesgcmsiv/aesgcmsiv.go new file mode 100644 index 0000000..8796a88 --- /dev/null +++ b/aead/aesgcmsiv/aesgcmsiv.go @@ -0,0 +1,36 @@ +// Copyright 2024 Google LLC +// +// 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 aesgcmsiv provides an implementation of AES-GCM-SIV. +// +// See https://www.rfc-editor.org/rfc/rfc8452.html for more information. +package aesgcmsiv + +import ( + "fmt" + + "github.com/tink-crypto/tink-go/v2/internal/protoserialization" +) + +func init() { + if err := protoserialization.RegisterKeySerializer[*Key](&keySerializer{}); err != nil { + panic(fmt.Sprintf("aesgcmsiv.init() failed: %v", err)) + } + if err := protoserialization.RegisterKeyParser(typeURL, &keyParser{}); err != nil { + panic(fmt.Sprintf("aesgcmsiv.init() failed: %v", err)) + } + if err := protoserialization.RegisterParametersSerializer[*Parameters](¶metersSerializer{}); err != nil { + panic(fmt.Sprintf("aesgcmsiv.init() failed: %v", err)) + } +} diff --git a/aead/aesgcmsiv/aesgcmsiv_test.go b/aead/aesgcmsiv/aesgcmsiv_test.go new file mode 100644 index 0000000..b642cdf --- /dev/null +++ b/aead/aesgcmsiv/aesgcmsiv_test.go @@ -0,0 +1,141 @@ +// Copyright 2024 Google LLC +// +// 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 aesgcmsiv_test + +import ( + "bytes" + "testing" + + "github.com/tink-crypto/tink-go/v2/aead" + "github.com/tink-crypto/tink-go/v2/aead/aesgcmsiv" + "github.com/tink-crypto/tink-go/v2/keyset" +) + +func TestGetKeyFromHandle(t *testing.T) { + keysetHandle, err := keyset.NewHandle(aead.AES128GCMSIVKeyTemplate()) + if err != nil { + t.Fatalf("keyset.NewHandle(aead.AES128GCMSIVKeyTemplate()) err = %v, want nil", err) + } + entry, err := keysetHandle.Entry(0) + if err != nil { + t.Fatalf("keysetHandle.Entry(0) err = %v, want nil", err) + } + key, ok := entry.Key().(*aesgcmsiv.Key) + if !ok { + t.Fatalf("entry.Key() is not an *Key") + } + keySize := 16 + expectedParameters, err := aesgcmsiv.NewParameters(keySize, aesgcmsiv.VariantTink) + if err != nil { + t.Fatalf("aesgcmsiv.NewParameters(%v, %v) err = %v, want nil", keySize, aesgcmsiv.VariantTink, err) + } + if !key.Parameters().Equals(expectedParameters) { + t.Errorf("key.Parameters().Equals(expectedParameters) = false, want true") + } + if _, hasIDRequirement := key.IDRequirement(); !hasIDRequirement { + t.Errorf("expected ID requirement, got none") + } + keyBytes := key.KeyBytes() + if keyBytes.Len() != keySize { + t.Errorf("keyBytes.Len() = %v, want %v", keyBytes.Len(), keySize) + } +} + +func TestCreateKeysetHandleFromKey(t *testing.T) { + keysetHandle, err := keyset.NewHandle(aead.AES256GCMSIVKeyTemplate()) + if err != nil { + t.Fatalf("keyset.NewHandle(aead.AES256GCMSIVKeyTemplate()) err = %v, want nil", err) + } + aeadPrimitive, err := aead.New(keysetHandle) + if err != nil { + t.Fatalf("aead.New(keysetHandle) err = %v, want nil", err) + } + plaintext := []byte("plaintext") + additionalData := []byte("additionalData") + ciphertext, err := aeadPrimitive.Encrypt(plaintext, additionalData) + if err != nil { + t.Fatalf("aeadPrimitive.Encrypt(%v, %v) err = %v, want nil", plaintext, additionalData, err) + } + + entry, err := keysetHandle.Entry(0) + if err != nil { + t.Fatalf("keysetHandle.Entry(0) err = %v, want nil", err) + } + key, ok := entry.Key().(*aesgcmsiv.Key) + if !ok { + t.Fatalf("entry.Key() is not *aesgcmsiv.Key") + } + + // Create a new keyset handle with the same key. + manager := keyset.NewManager() + keyID, err := manager.AddKey(key) + if err != nil { + t.Fatalf("manager.AddKey(key) err = %v, want nil", err) + } + if err = manager.SetPrimary(keyID); err != nil { + t.Fatalf("manager.SetPrimary(%v) err = %v, want nil", keyID, err) + } + newHandle, err := manager.Handle() + if err != nil { + t.Fatalf("manager.Handle() err = %v, want nil", err) + } + + // Get an AEAD primitive from the new handle and decrypt the ciphertext. + newAEAD, err := aead.New(newHandle) + if err != nil { + t.Fatalf("aead.New(newHandle) err = %v, want nil", err) + } + decrypt, err := newAEAD.Decrypt(ciphertext, additionalData) + if err != nil { + t.Fatalf("decrypt.New(otherAEADPrimitivce, %v, %v) err = %v, want nil", ciphertext, additionalData, err) + } + if !bytes.Equal(decrypt, plaintext) { + t.Errorf("decrypt = %v, want %v", decrypt, plaintext) + } +} + +func TestCreateKeysetHandleFromParameters(t *testing.T) { + params, err := aesgcmsiv.NewParameters(32, aesgcmsiv.VariantTink) + if err != nil { + t.Fatalf("aesgcmsiv.NewParameters(%v, %v) err = %v, want nil", 32, aesgcmsiv.VariantTink, err) + } + manager := keyset.NewManager() + keyID, err := manager.AddNewKeyFromParameters(params) + if err != nil { + t.Fatalf("manager.AddNewKeyFromParameters(%v) err = %v, want nil", params, err) + } + manager.SetPrimary(keyID) + handle, err := manager.Handle() + if err != nil { + t.Fatalf("manager.Handle() err = %v, want nil", err) + } + aeadPrimitive, err := aead.New(handle) + if err != nil { + t.Fatalf("aead.New(handle) err = %v, want nil", err) + } + plaintext := []byte("plaintext") + additionalData := []byte("additionalData") + ciphertext, err := aeadPrimitive.Encrypt(plaintext, additionalData) + if err != nil { + t.Fatalf("aeadPrimitive.Encrypt(%v, %v) err = %v, want nil", plaintext, additionalData, err) + } + decrypted, err := aeadPrimitive.Decrypt(ciphertext, additionalData) + if err != nil { + t.Fatalf("aeadPrimitive.Decrypt(%v, %v) err = %v, want nil", ciphertext, additionalData, err) + } + if !bytes.Equal(decrypted, plaintext) { + t.Errorf("decrypted = %v, want %v", decrypted, plaintext) + } +} diff --git a/aead/aesgcmsiv/key.go b/aead/aesgcmsiv/key.go index 01eb916..6e2a6dc 100644 --- a/aead/aesgcmsiv/key.go +++ b/aead/aesgcmsiv/key.go @@ -12,9 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package aesgcmsiv provides an implementation of AES-GCM-SIV. -// -// See https://www.rfc-editor.org/rfc/rfc8452.html for more information. package aesgcmsiv import (