xref: /aosp_15_r20/external/tink/go/testutil/hybrid/private_key.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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