xref: /aosp_15_r20/external/tink/go/testutil/hybrid/private_key.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang// Copyright 2022 Google LLC
2*e7b1675dSTing-Kang Chang//
3*e7b1675dSTing-Kang Chang// Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang// you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang// You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang//
7*e7b1675dSTing-Kang Chang//      http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang//
9*e7b1675dSTing-Kang Chang// Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang// distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang// See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang// limitations under the License.
14*e7b1675dSTing-Kang Chang//
15*e7b1675dSTing-Kang Chang////////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Chang// Package hybrid provides HybridEncrypt/Decrypt primitive-specific test
18*e7b1675dSTing-Kang Chang// utilities.
19*e7b1675dSTing-Kang Changpackage hybrid
20*e7b1675dSTing-Kang Chang
21*e7b1675dSTing-Kang Changimport (
22*e7b1675dSTing-Kang Chang	"errors"
23*e7b1675dSTing-Kang Chang	"fmt"
24*e7b1675dSTing-Kang Chang
25*e7b1675dSTing-Kang Chang	"google.golang.org/protobuf/proto"
26*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/keyset"
27*e7b1675dSTing-Kang Chang	"github.com/google/tink/go/testkeyset"
28*e7b1675dSTing-Kang Chang	hpkepb "github.com/google/tink/go/proto/hpke_go_proto"
29*e7b1675dSTing-Kang Chang	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
30*e7b1675dSTing-Kang Chang)
31*e7b1675dSTing-Kang Chang
32*e7b1675dSTing-Kang Changconst (
33*e7b1675dSTing-Kang Chang	// HPKE key lengths from
34*e7b1675dSTing-Kang Chang	// https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1.
35*e7b1675dSTing-Kang Chang	hpkeX25519HKDFSHA256PrivKeyLen = 32
36*e7b1675dSTing-Kang Chang	hpkeX25519HKDFSHA256PubKeyLen  = 32
37*e7b1675dSTing-Kang Chang
38*e7b1675dSTing-Kang Chang	hpkePrivateKeyTypeURL = "type.googleapis.com/google.crypto.tink.HpkePrivateKey"
39*e7b1675dSTing-Kang Chang)
40*e7b1675dSTing-Kang Chang
41*e7b1675dSTing-Kang Chang// KeysetHandleFromSerializedPrivateKey returns a keyset handle containing a
42*e7b1675dSTing-Kang Chang// primary key that has the specified privKeyBytes and pubKeyBytes and matches
43*e7b1675dSTing-Kang Chang// template.
44*e7b1675dSTing-Kang Chang//
45*e7b1675dSTing-Kang Chang// Supported templates include:
46*e7b1675dSTing-Kang Chang//   - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template,
47*e7b1675dSTing-Kang Chang//     which requires privKeyBytes and pubKeyBytes to be the KEM-encoding of the
48*e7b1675dSTing-Kang Chang//     private and public key, respectively, i.e. SerializePrivateKey and
49*e7b1675dSTing-Kang Chang//     SerializePublicKey in
50*e7b1675dSTing-Kang Chang//     https://www.rfc-editor.org/rfc/rfc9180.html#section-7.1.1.
51*e7b1675dSTing-Kang Changfunc KeysetHandleFromSerializedPrivateKey(privKeyBytes, pubKeyBytes []byte, template *tinkpb.KeyTemplate) (*keyset.Handle, error) {
52*e7b1675dSTing-Kang Chang	params, err := hpkeParamsFromTemplate(template)
53*e7b1675dSTing-Kang Chang	if err != nil {
54*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("failed to verify key template: %v", err)
55*e7b1675dSTing-Kang Chang	}
56*e7b1675dSTing-Kang Chang	if len(privKeyBytes) != hpkeX25519HKDFSHA256PrivKeyLen {
57*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("privKeyBytes length is %d but should be %d", len(privKeyBytes), hpkeX25519HKDFSHA256PrivKeyLen)
58*e7b1675dSTing-Kang Chang	}
59*e7b1675dSTing-Kang Chang	if len(pubKeyBytes) != hpkeX25519HKDFSHA256PubKeyLen {
60*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("pubKeyBytes length is %d but should be %d", len(pubKeyBytes), hpkeX25519HKDFSHA256PubKeyLen)
61*e7b1675dSTing-Kang Chang	}
62*e7b1675dSTing-Kang Chang
63*e7b1675dSTing-Kang Chang	privKey := &hpkepb.HpkePrivateKey{
64*e7b1675dSTing-Kang Chang		Version:    0,
65*e7b1675dSTing-Kang Chang		PrivateKey: privKeyBytes,
66*e7b1675dSTing-Kang Chang		PublicKey: &hpkepb.HpkePublicKey{
67*e7b1675dSTing-Kang Chang			Version:   0,
68*e7b1675dSTing-Kang Chang			Params:    params,
69*e7b1675dSTing-Kang Chang			PublicKey: pubKeyBytes,
70*e7b1675dSTing-Kang Chang		},
71*e7b1675dSTing-Kang Chang	}
72*e7b1675dSTing-Kang Chang	serializedPrivKey, err := proto.Marshal(privKey)
73*e7b1675dSTing-Kang Chang	if err != nil {
74*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("failed to marshal HpkePrivateKey %v: %v", privKey, err)
75*e7b1675dSTing-Kang Chang	}
76*e7b1675dSTing-Kang Chang	ks := &tinkpb.Keyset{
77*e7b1675dSTing-Kang Chang		PrimaryKeyId: 1,
78*e7b1675dSTing-Kang Chang		Key: []*tinkpb.Keyset_Key{
79*e7b1675dSTing-Kang Chang			{
80*e7b1675dSTing-Kang Chang				KeyData: &tinkpb.KeyData{
81*e7b1675dSTing-Kang Chang					TypeUrl:         hpkePrivateKeyTypeURL,
82*e7b1675dSTing-Kang Chang					Value:           serializedPrivKey,
83*e7b1675dSTing-Kang Chang					KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PRIVATE,
84*e7b1675dSTing-Kang Chang				},
85*e7b1675dSTing-Kang Chang				Status:           tinkpb.KeyStatusType_ENABLED,
86*e7b1675dSTing-Kang Chang				KeyId:            1,
87*e7b1675dSTing-Kang Chang				OutputPrefixType: tinkpb.OutputPrefixType_RAW,
88*e7b1675dSTing-Kang Chang			},
89*e7b1675dSTing-Kang Chang		},
90*e7b1675dSTing-Kang Chang	}
91*e7b1675dSTing-Kang Chang	return testkeyset.NewHandle(ks)
92*e7b1675dSTing-Kang Chang}
93*e7b1675dSTing-Kang Chang
94*e7b1675dSTing-Kang Chang// hpkeParamsFromTemplate returns HPKE params after verifying that template is
95*e7b1675dSTing-Kang Chang// supported.
96*e7b1675dSTing-Kang Chang//
97*e7b1675dSTing-Kang Chang// Supported templates include:
98*e7b1675dSTing-Kang Chang//   - DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_Raw_Key_Template.
99*e7b1675dSTing-Kang Changfunc hpkeParamsFromTemplate(template *tinkpb.KeyTemplate) (*hpkepb.HpkeParams, error) {
100*e7b1675dSTing-Kang Chang	if template.GetTypeUrl() != hpkePrivateKeyTypeURL {
101*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("not key type URL %s", hpkePrivateKeyTypeURL)
102*e7b1675dSTing-Kang Chang	}
103*e7b1675dSTing-Kang Chang	if template.GetOutputPrefixType() != tinkpb.OutputPrefixType_RAW {
104*e7b1675dSTing-Kang Chang		return nil, errors.New("not raw output prefix type")
105*e7b1675dSTing-Kang Chang	}
106*e7b1675dSTing-Kang Chang	keyFormat := &hpkepb.HpkeKeyFormat{}
107*e7b1675dSTing-Kang Chang	if err := proto.Unmarshal(template.GetValue(), keyFormat); err != nil {
108*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("failed to unmarshal HpkeKeyFormat(%v): %v", template.GetValue(), err)
109*e7b1675dSTing-Kang Chang	}
110*e7b1675dSTing-Kang Chang
111*e7b1675dSTing-Kang Chang	params := keyFormat.GetParams()
112*e7b1675dSTing-Kang Chang	if kem := params.GetKem(); kem != hpkepb.HpkeKem_DHKEM_X25519_HKDF_SHA256 {
113*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("HPKE KEM %s not supported", kem)
114*e7b1675dSTing-Kang Chang	}
115*e7b1675dSTing-Kang Chang	if kdf := params.GetKdf(); kdf != hpkepb.HpkeKdf_HKDF_SHA256 {
116*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("HPKE KDF %s not supported", kdf)
117*e7b1675dSTing-Kang Chang	}
118*e7b1675dSTing-Kang Chang	if aead := params.GetAead(); aead != hpkepb.HpkeAead_CHACHA20_POLY1305 {
119*e7b1675dSTing-Kang Chang		return nil, fmt.Errorf("HPKE AEAD %s not supported", aead)
120*e7b1675dSTing-Kang Chang	}
121*e7b1675dSTing-Kang Chang
122*e7b1675dSTing-Kang Chang	return params, nil
123*e7b1675dSTing-Kang Chang}
124