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 17// Package hybrid provides HybridEncrypt/Decrypt primitive-specific test 18// utilities. 19package hybrid 20 21import ( 22 "errors" 23 "fmt" 24 25 "google.golang.org/protobuf/proto" 26 "github.com/google/tink/go/keyset" 27 "github.com/google/tink/go/testkeyset" 28 hpkepb "github.com/google/tink/go/proto/hpke_go_proto" 29 tinkpb "github.com/google/tink/go/proto/tink_go_proto" 30) 31 32const ( 33 // HPKE key lengths from 34 // https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1. 35 hpkeX25519HKDFSHA256PrivKeyLen = 32 36 hpkeX25519HKDFSHA256PubKeyLen = 32 37 38 hpkePrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.HpkePrivateKey" 39) 40 41// KeysetHandleFromSerializedPrivateKey returns a keyset handle containing a 42// primary key that has the specified privKeyBytes and pubKeyBytes and matches 43// template. 44// 45// Supported templates include: 46// - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template, 47// which requires privKeyBytes and pubKeyBytes to be the KEM-encoding of the 48// private and public key, respectively, i.e. SerializePrivateKey and 49// SerializePublicKey in 50// https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1.1. 51func KeysetHandleFromSerializedPrivateKey(privKeyBytes, pubKeyBytes []byte, template *tinkpb.KeyTemplate) (*keyset.Handle, error) { 52 params, err := hpkeParamsFromTemplate(template) 53 if err != nil { 54 return nil, fmt.Errorf("failed to verify key template: %v", err) 55 } 56 if len(privKeyBytes) != hpkeX25519HKDFSHA256PrivKeyLen { 57 return nil, fmt.Errorf("privKeyBytes length is %d but should be %d", len(privKeyBytes), hpkeX25519HKDFSHA256PrivKeyLen) 58 } 59 if len(pubKeyBytes) != hpkeX25519HKDFSHA256PubKeyLen { 60 return nil, fmt.Errorf("pubKeyBytes length is %d but should be %d", len(pubKeyBytes), hpkeX25519HKDFSHA256PubKeyLen) 61 } 62 63 privKey := &hpkepb.HpkePrivateKey{ 64 Version: 0, 65 PrivateKey: privKeyBytes, 66 PublicKey: &hpkepb.HpkePublicKey{ 67 Version: 0, 68 Params: params, 69 PublicKey: pubKeyBytes, 70 }, 71 } 72 serializedPrivKey, err := proto.Marshal(privKey) 73 if err != nil { 74 return nil, fmt.Errorf("failed to marshal HpkePrivateKey %v: %v", privKey, err) 75 } 76 ks := &tinkpb.Keyset{ 77 PrimaryKeyId: 1, 78 Key: []*tinkpb.Keyset_Key{ 79 { 80 KeyData: &tinkpb.KeyData{ 81 TypeUrl: hpkePrivateKeyTypeURL, 82 Value: serializedPrivKey, 83 KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE, 84 }, 85 Status: tinkpb.KeyStatusType_ENABLED, 86 KeyId: 1, 87 OutputPrefixType: tinkpb.OutputPrefixType_RAW, 88 }, 89 }, 90 } 91 return testkeyset.NewHandle(ks) 92} 93 94// hpkeParamsFromTemplate returns HPKE params after verifying that template is 95// supported. 96// 97// Supported templates include: 98// - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template. 99func hpkeParamsFromTemplate(template *tinkpb.KeyTemplate) (*hpkepb.HpkeParams, error) { 100 if template.GetTypeUrl() != hpkePrivateKeyTypeURL { 101 return nil, fmt.Errorf("not key type URL %s", hpkePrivateKeyTypeURL) 102 } 103 if template.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW { 104 return nil, errors.New("not raw output prefix type") 105 } 106 keyFormat := &hpkepb.HpkeKeyFormat{} 107 if err := proto.Unmarshal(template.GetValue(), keyFormat); err != nil { 108 return nil, fmt.Errorf("failed to unmarshal HpkeKeyFormat(%v): %v", template.GetValue(), err) 109 } 110 111 params := keyFormat.GetParams() 112 if kem := params.GetKem(); kem != hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256 { 113 return nil, fmt.Errorf("HPKE KEM %s not supported", kem) 114 } 115 if kdf := params.GetKdf(); kdf != hpkepb.HpkeKdf_HKDF_SHA256 { 116 return nil, fmt.Errorf("HPKE KDF %s not supported", kdf) 117 } 118 if aead := params.GetAead(); aead != hpkepb.HpkeAead_CHACHA20_POLY1305 { 119 return nil, fmt.Errorf("HPKE AEAD %s not supported", aead) 120 } 121 122 return params, nil 123} 124