1// Copyright 2022 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17package hybrid_test 18 19import ( 20 "bytes" 21 "testing" 22 23 "google.golang.org/protobuf/proto" 24 "github.com/google/tink/go/hybrid" 25 "github.com/google/tink/go/keyset" 26 "github.com/google/tink/go/subtle/random" 27 "github.com/google/tink/go/testkeyset" 28 testutilhybrid "github.com/google/tink/go/testutil/hybrid" 29 hpkepb "github.com/google/tink/go/proto/hpke_go_proto" 30 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 31) 32 33func TestKeysetHandleFromSerializedPrivateKey(t *testing.T) { 34 // Obtain private and public key handles via key template. 35 keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() 36 privHandle, err := keyset.NewHandle(keyTemplate) 37 if err != nil { 38 t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) 39 } 40 pubHandle, err := privHandle.Public() 41 if err != nil { 42 t.Fatalf("Public() err = %v, want nil", err) 43 } 44 45 // Get private, public key bytes and construct a private key handle. 46 privKeyBytes, pubKeyBytes := privPubKeyBytes(t, privHandle) 47 gotprivHandle, err := testutilhybrid.KeysetHandleFromSerializedPrivateKey(privKeyBytes, pubKeyBytes, keyTemplate) 48 if err != nil { 49 t.Errorf("KeysetHandleFromSerializedPrivateKey(%v, %v, %v) err = %v, want nil", privKeyBytes, pubKeyBytes, keyTemplate, err) 50 } 51 52 plaintext := random.GetRandomBytes(200) 53 ctxInfo := random.GetRandomBytes(100) 54 55 // Encrypt with original public key handle. 56 enc, err := hybrid.NewHybridEncrypt(pubHandle) 57 if err != nil { 58 t.Fatalf("NewHybridEncrypt(%v) err = %v, want nil", pubHandle, err) 59 } 60 ciphertext, err := enc.Encrypt(plaintext, ctxInfo) 61 if err != nil { 62 t.Fatalf("Encrypt(%x, %x) err = %v, want nil", plaintext, ctxInfo, err) 63 } 64 65 // Decrypt with private key handle constructed from key bytes. 66 dec, err := hybrid.NewHybridDecrypt(gotprivHandle) 67 if err != nil { 68 t.Fatalf("NewHybridDecrypt(%v) err = %v, want nil", gotprivHandle, err) 69 } 70 gotPlaintext, err := dec.Decrypt(ciphertext, ctxInfo) 71 if err != nil { 72 t.Fatalf("Decrypt(%x, %x) err = %v, want nil", ciphertext, ctxInfo, err) 73 } 74 if !bytes.Equal(gotPlaintext, plaintext) { 75 t.Errorf("Decrypt(%x, %x) = %x, want %x", ciphertext, ctxInfo, gotPlaintext, plaintext) 76 } 77} 78 79func TestKeysetHandleFromSerializedPrivateKeyInvalidTemplateFails(t *testing.T) { 80 keyTemplate := hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template() 81 privHandle, err := keyset.NewHandle(keyTemplate) 82 if err != nil { 83 t.Fatalf("NewHandle(%v) err = %v, want nil", keyTemplate, err) 84 } 85 privKeyBytes, pubKeyBytes := privPubKeyBytes(t, privHandle) 86 87 tests := []struct { 88 name string 89 template *tinkpb.KeyTemplate 90 }{ 91 {"AES_128_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Key_Template()}, 92 {"AES_128_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_Raw_Key_Template()}, 93 {"AES_256_GCM", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Key_Template()}, 94 {"AES_256_GCM_Raw", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_Raw_Key_Template()}, 95 {"CHACHA20_POLY1305", hybrid.DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Key_Template()}, 96 {"invalid type URL", &tinkpb.KeyTemplate{ 97 TypeUrl: "type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey", 98 Value: keyTemplate.GetValue(), 99 OutputPrefixType: tinkpb.OutputPrefixType_RAW, 100 }}, 101 } 102 for _, test := range tests { 103 t.Run(test.name, func(t *testing.T) { 104 if _, err := testutilhybrid.KeysetHandleFromSerializedPrivateKey(privKeyBytes, pubKeyBytes, test.template); err == nil { 105 t.Errorf("KeysetHandleFromSerializedPrivateKey(%v, %v, %v) err = nil, want error", privKeyBytes, pubKeyBytes, test.template) 106 } 107 }) 108 } 109} 110 111func privPubKeyBytes(t *testing.T, handle *keyset.Handle) ([]byte, []byte) { 112 t.Helper() 113 114 ks := testkeyset.KeysetMaterial(handle) 115 if len(ks.GetKey()) != 1 { 116 t.Fatalf("got len(ks.GetKey()) = %d, want 1", len(ks.GetKey())) 117 } 118 119 serializedPrivKey := ks.GetKey()[0].GetKeyData().GetValue() 120 privKey := &hpkepb.HpkePrivateKey{} 121 if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil { 122 t.Fatalf("Unmarshal(%v) = err %v, want nil", serializedPrivKey, err) 123 } 124 125 return privKey.GetPrivateKey(), privKey.GetPublicKey().GetPublicKey() 126} 127