1 package hpke
2
3
4
5
6
7
8
9
10 import (
11 "crypto/rand"
12
13 "github.com/cloudflare/circl/kem"
14 )
15
16 type hybridKEM struct {
17 kemBase
18 kemA kem.Scheme
19 kemB kem.Scheme
20 }
21
22 func (h hybridKEM) PrivateKeySize() int { return h.kemA.PrivateKeySize() + h.kemB.PrivateKeySize() }
23 func (h hybridKEM) SeedSize() int { return 32 }
24 func (h hybridKEM) CiphertextSize() int { return h.kemA.CiphertextSize() + h.kemB.CiphertextSize() }
25 func (h hybridKEM) PublicKeySize() int { return h.kemA.PublicKeySize() + h.kemB.PublicKeySize() }
26 func (h hybridKEM) EncapsulationSeedSize() int {
27 return h.kemA.EncapsulationSeedSize() + h.kemB.EncapsulationSeedSize()
28 }
29 func (h hybridKEM) SharedKeySize() int { return h.kemA.SharedKeySize() + h.kemB.SharedKeySize() }
30 func (h hybridKEM) Name() string { return h.name }
31
32 func (h hybridKEM) AuthDecapsulate(skR kem.PrivateKey,
33 ct []byte,
34 pkS kem.PublicKey,
35 ) ([]byte, error) {
36 panic("AuthDecapsulate is not supported for this KEM")
37 }
38
39 func (h hybridKEM) AuthEncapsulate(pkr kem.PublicKey, sks kem.PrivateKey) (
40 ct []byte, ss []byte, err error,
41 ) {
42 panic("AuthEncapsulate is not supported for this KEM")
43 }
44
45 func (h hybridKEM) AuthEncapsulateDeterministically(pkr kem.PublicKey, sks kem.PrivateKey, seed []byte) (ct, ss []byte, err error) {
46 panic("AuthEncapsulateDeterministically is not supported for this KEM")
47 }
48
49 func (h hybridKEM) Encapsulate(pkr kem.PublicKey) (
50 ct []byte, ss []byte, err error,
51 ) {
52 panic("Encapsulate is not implemented")
53 }
54
55 func (h hybridKEM) Decapsulate(skr kem.PrivateKey, ct []byte) ([]byte, error) {
56 hybridSk := skr.(*hybridKEMPrivKey)
57 ssA, err := h.kemA.Decapsulate(hybridSk.privA, ct[0:h.kemA.CiphertextSize()])
58 if err != nil {
59 return nil, err
60 }
61 ssB, err := h.kemB.Decapsulate(hybridSk.privB, ct[h.kemA.CiphertextSize():])
62 if err != nil {
63 return nil, err
64 }
65
66 ss := append(ssA, ssB...)
67
68 return ss, nil
69 }
70
71 func (h hybridKEM) EncapsulateDeterministically(
72 pkr kem.PublicKey, seed []byte,
73 ) (ct, ss []byte, err error) {
74 hybridPk := pkr.(*hybridKEMPubKey)
75 encA, ssA, err := h.kemA.EncapsulateDeterministically(hybridPk.pubA, seed[0:h.kemA.EncapsulationSeedSize()])
76 if err != nil {
77 return nil, nil, err
78 }
79 encB, ssB, err := h.kemB.EncapsulateDeterministically(hybridPk.pubB, seed[h.kemA.EncapsulationSeedSize():])
80 if err != nil {
81 return nil, nil, err
82 }
83
84 ct = append(encA, encB...)
85 ss = append(ssA, ssB...)
86
87 return ct, ss, nil
88 }
89
90 type hybridKEMPrivKey struct {
91 scheme kem.Scheme
92 privA kem.PrivateKey
93 privB kem.PrivateKey
94 }
95
96 func (k *hybridKEMPrivKey) Scheme() kem.Scheme {
97 return k.scheme
98 }
99
100 func (k *hybridKEMPrivKey) MarshalBinary() ([]byte, error) {
101 skA, err := k.privA.MarshalBinary()
102 if err != nil {
103 return nil, err
104 }
105 skB, err := k.privB.MarshalBinary()
106 if err != nil {
107 return nil, err
108 }
109 return append(skA, skB...), nil
110 }
111
112 func (k *hybridKEMPrivKey) Equal(sk kem.PrivateKey) bool {
113 k1, ok := sk.(*hybridKEMPrivKey)
114 return ok &&
115 k.privA.Equal(k1.privA) &&
116 k.privB.Equal(k1.privB)
117 }
118
119 func (k *hybridKEMPrivKey) Public() kem.PublicKey {
120 return &hybridKEMPubKey{
121 scheme: k.scheme,
122 pubA: k.privA.Public(),
123 pubB: k.privB.Public(),
124 }
125 }
126
127 type hybridKEMPubKey struct {
128 scheme kem.Scheme
129 pubA kem.PublicKey
130 pubB kem.PublicKey
131 }
132
133 func (k *hybridKEMPubKey) Scheme() kem.Scheme {
134 return k.scheme
135 }
136
137 func (k hybridKEMPubKey) MarshalBinary() ([]byte, error) {
138 pkA, err := k.pubA.MarshalBinary()
139 if err != nil {
140 return nil, err
141 }
142 pkB, err := k.pubB.MarshalBinary()
143 if err != nil {
144 return nil, err
145 }
146 return append(pkA, pkB...), nil
147 }
148
149 func (k *hybridKEMPubKey) Equal(pk kem.PublicKey) bool {
150 k1, ok := pk.(*hybridKEMPubKey)
151 return ok &&
152 k.pubA.Equal(k1.pubA) &&
153 k.pubB.Equal(k1.pubB)
154 }
155
156
157
158
159
160 func (h hybridKEM) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) {
161
162
163 if len(seed) != h.SeedSize() {
164 panic(kem.ErrSeedSize)
165 }
166
167 outputSeedSize := h.kemA.SeedSize() + h.kemB.SeedSize()
168 dkpPrk := h.labeledExtract([]byte(""), []byte("dkp_prk"), seed)
169 bytes := h.labeledExpand(
170 dkpPrk,
171 []byte("sk"),
172 nil,
173 uint16(outputSeedSize),
174 )
175 seedA := bytes[0:h.kemA.SeedSize()]
176 seedB := bytes[h.kemA.SeedSize():]
177 pubA, privA := h.kemA.DeriveKeyPair(seedA)
178 pubB, privB := h.kemB.DeriveKeyPair(seedB)
179
180 privKey := &hybridKEMPrivKey{
181 privA: privA,
182 privB: privB,
183 }
184 pubKey := &hybridKEMPubKey{
185 pubA: pubA,
186 pubB: pubB,
187 }
188
189 return pubKey, privKey
190 }
191
192 func (h hybridKEM) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) {
193 seed := make([]byte, h.SeedSize())
194 _, err := rand.Read(seed)
195 if err != nil {
196 return nil, nil, err
197 }
198 pk, sk := h.DeriveKeyPair(seed)
199 return pk, sk, nil
200 }
201
202 func (h hybridKEM) UnmarshalBinaryPrivateKey(data []byte) (kem.PrivateKey, error) {
203 skA, err := h.kemA.UnmarshalBinaryPrivateKey(data[0:h.kemA.PrivateKeySize()])
204 if err != nil {
205 return nil, err
206 }
207 skB, err := h.kemB.UnmarshalBinaryPrivateKey(data[h.kemA.PrivateKeySize():])
208 if err != nil {
209 return nil, err
210 }
211
212 return &hybridKEMPrivKey{
213 privA: skA,
214 privB: skB,
215 }, nil
216 }
217
218 func (h hybridKEM) UnmarshalBinaryPublicKey(data []byte) (kem.PublicKey, error) {
219 pkA, err := h.kemA.UnmarshalBinaryPublicKey(data[0:h.kemA.PublicKeySize()])
220 if err != nil {
221 return nil, err
222 }
223 pkB, err := h.kemB.UnmarshalBinaryPublicKey(data[h.kemA.PublicKeySize():])
224 if err != nil {
225 return nil, err
226 }
227
228 return &hybridKEMPubKey{
229 pubA: pkA,
230 pubB: pkB,
231 }, nil
232 }
233
View as plain text