1
2
3
4
5
6
7
8 package kyber512
9
10 import (
11 "bytes"
12 "crypto/subtle"
13 "io"
14
15 cryptoRand "crypto/rand"
16 "github.com/cloudflare/circl/internal/sha3"
17 "github.com/cloudflare/circl/kem"
18 cpapke "github.com/cloudflare/circl/pke/kyber/kyber512"
19 )
20
21 const (
22
23 KeySeedSize = cpapke.KeySeedSize + 32
24
25
26 EncapsulationSeedSize = 32
27
28
29 SharedKeySize = 32
30
31
32 CiphertextSize = cpapke.CiphertextSize
33
34
35 PublicKeySize = cpapke.PublicKeySize
36
37
38 PrivateKeySize = cpapke.PrivateKeySize + cpapke.PublicKeySize + 64
39 )
40
41
42 type PublicKey struct {
43 pk *cpapke.PublicKey
44
45 hpk [32]byte
46 }
47
48
49 type PrivateKey struct {
50 sk *cpapke.PrivateKey
51 pk *cpapke.PublicKey
52 hpk [32]byte
53 z [32]byte
54 }
55
56
57
58
59
60 func NewKeyFromSeed(seed []byte) (*PublicKey, *PrivateKey) {
61 var sk PrivateKey
62 var pk PublicKey
63
64 if len(seed) != KeySeedSize {
65 panic("seed must be of length KeySeedSize")
66 }
67
68 pk.pk, sk.sk = cpapke.NewKeyFromSeed(seed[:cpapke.KeySeedSize])
69 sk.pk = pk.pk
70 copy(sk.z[:], seed[cpapke.KeySeedSize:])
71
72
73 var ppk [cpapke.PublicKeySize]byte
74 sk.pk.Pack(ppk[:])
75 h := sha3.New256()
76 h.Write(ppk[:])
77 h.Read(sk.hpk[:])
78 copy(pk.hpk[:], sk.hpk[:])
79
80 return &pk, &sk
81 }
82
83
84
85 func GenerateKeyPair(rand io.Reader) (*PublicKey, *PrivateKey, error) {
86 var seed [KeySeedSize]byte
87 if rand == nil {
88 rand = cryptoRand.Reader
89 }
90 _, err := io.ReadFull(rand, seed[:])
91 if err != nil {
92 return nil, nil, err
93 }
94 pk, sk := NewKeyFromSeed(seed[:])
95 return pk, sk, nil
96 }
97
98
99
100
101
102
103
104
105
106 func (pk *PublicKey) EncapsulateTo(ct, ss []byte, seed []byte) {
107 if seed == nil {
108 seed = make([]byte, EncapsulationSeedSize)
109 if _, err := cryptoRand.Read(seed[:]); err != nil {
110 panic(err)
111 }
112 } else {
113 if len(seed) != EncapsulationSeedSize {
114 panic("seed must be of length EncapsulationSeedSize")
115 }
116 }
117
118 if len(ct) != CiphertextSize {
119 panic("ct must be of length CiphertextSize")
120 }
121
122 if len(ss) != SharedKeySize {
123 panic("ss must be of length SharedKeySize")
124 }
125
126
127 var m [32]byte
128 h := sha3.New256()
129 h.Write(seed[:])
130 h.Read(m[:])
131
132
133 var kr [64]byte
134 g := sha3.New512()
135 g.Write(m[:])
136 g.Write(pk.hpk[:])
137 g.Read(kr[:])
138
139
140 pk.pk.EncryptTo(ct, m[:], kr[32:])
141
142
143 h.Reset()
144 h.Write(ct[:CiphertextSize])
145 h.Read(kr[32:])
146
147
148 kdf := sha3.NewShake256()
149 kdf.Write(kr[:])
150 kdf.Read(ss[:SharedKeySize])
151 }
152
153
154
155
156
157
158 func (sk *PrivateKey) DecapsulateTo(ss, ct []byte) {
159 if len(ct) != CiphertextSize {
160 panic("ct must be of length CiphertextSize")
161 }
162
163 if len(ss) != SharedKeySize {
164 panic("ss must be of length SharedKeySize")
165 }
166
167
168 var m2 [32]byte
169 sk.sk.DecryptTo(m2[:], ct)
170
171
172 var kr2 [64]byte
173 g := sha3.New512()
174 g.Write(m2[:])
175 g.Write(sk.hpk[:])
176 g.Read(kr2[:])
177
178
179 var ct2 [CiphertextSize]byte
180 sk.pk.EncryptTo(ct2[:], m2[:], kr2[32:])
181
182
183 h := sha3.New256()
184 h.Write(ct[:CiphertextSize])
185 h.Read(kr2[32:])
186
187
188 subtle.ConstantTimeCopy(
189 1-subtle.ConstantTimeCompare(ct, ct2[:]),
190 kr2[:32],
191 sk.z[:],
192 )
193
194
195 kdf := sha3.NewShake256()
196 kdf.Write(kr2[:])
197 kdf.Read(ss[:SharedKeySize])
198 }
199
200
201
202
203 func (sk *PrivateKey) Pack(buf []byte) {
204 if len(buf) != PrivateKeySize {
205 panic("buf must be of length PrivateKeySize")
206 }
207
208 sk.sk.Pack(buf[:cpapke.PrivateKeySize])
209 buf = buf[cpapke.PrivateKeySize:]
210 sk.pk.Pack(buf[:cpapke.PublicKeySize])
211 buf = buf[cpapke.PublicKeySize:]
212 copy(buf, sk.hpk[:])
213 buf = buf[32:]
214 copy(buf, sk.z[:])
215 }
216
217
218
219
220 func (sk *PrivateKey) Unpack(buf []byte) {
221 if len(buf) != PrivateKeySize {
222 panic("buf must be of length PrivateKeySize")
223 }
224
225 sk.sk = new(cpapke.PrivateKey)
226 sk.sk.Unpack(buf[:cpapke.PrivateKeySize])
227 buf = buf[cpapke.PrivateKeySize:]
228 sk.pk = new(cpapke.PublicKey)
229 sk.pk.Unpack(buf[:cpapke.PublicKeySize])
230 buf = buf[cpapke.PublicKeySize:]
231 copy(sk.hpk[:], buf[:32])
232 copy(sk.z[:], buf[32:])
233 }
234
235
236
237
238 func (pk *PublicKey) Pack(buf []byte) {
239 if len(buf) != PublicKeySize {
240 panic("buf must be of length PublicKeySize")
241 }
242
243 pk.pk.Pack(buf)
244 }
245
246
247
248
249 func (pk *PublicKey) Unpack(buf []byte) {
250 if len(buf) != PublicKeySize {
251 panic("buf must be of length PublicKeySize")
252 }
253
254 pk.pk = new(cpapke.PublicKey)
255 pk.pk.Unpack(buf)
256
257
258 h := sha3.New256()
259 h.Write(buf)
260 h.Read(pk.hpk[:])
261 }
262
263
264
265 type scheme struct{}
266
267 var sch kem.Scheme = &scheme{}
268
269
270 func Scheme() kem.Scheme { return sch }
271
272 func (*scheme) Name() string { return "Kyber512" }
273 func (*scheme) PublicKeySize() int { return PublicKeySize }
274 func (*scheme) PrivateKeySize() int { return PrivateKeySize }
275 func (*scheme) SeedSize() int { return KeySeedSize }
276 func (*scheme) SharedKeySize() int { return SharedKeySize }
277 func (*scheme) CiphertextSize() int { return CiphertextSize }
278 func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize }
279
280 func (sk *PrivateKey) Scheme() kem.Scheme { return sch }
281 func (pk *PublicKey) Scheme() kem.Scheme { return sch }
282
283 func (sk *PrivateKey) MarshalBinary() ([]byte, error) {
284 var ret [PrivateKeySize]byte
285 sk.Pack(ret[:])
286 return ret[:], nil
287 }
288
289 func (sk *PrivateKey) Equal(other kem.PrivateKey) bool {
290 oth, ok := other.(*PrivateKey)
291 if !ok {
292 return false
293 }
294 if sk.pk == nil && oth.pk == nil {
295 return true
296 }
297 if sk.pk == nil || oth.pk == nil {
298 return false
299 }
300 if !bytes.Equal(sk.hpk[:], oth.hpk[:]) ||
301 subtle.ConstantTimeCompare(sk.z[:], oth.z[:]) != 1 {
302 return false
303 }
304 return sk.sk.Equal(oth.sk)
305 }
306
307 func (pk *PublicKey) Equal(other kem.PublicKey) bool {
308 oth, ok := other.(*PublicKey)
309 if !ok {
310 return false
311 }
312 if pk.pk == nil && oth.pk == nil {
313 return true
314 }
315 if pk.pk == nil || oth.pk == nil {
316 return false
317 }
318 return bytes.Equal(pk.hpk[:], oth.hpk[:])
319 }
320
321 func (sk *PrivateKey) Public() kem.PublicKey {
322 pk := new(PublicKey)
323 pk.pk = sk.pk
324 copy(pk.hpk[:], sk.hpk[:])
325 return pk
326 }
327
328 func (pk *PublicKey) MarshalBinary() ([]byte, error) {
329 var ret [PublicKeySize]byte
330 pk.Pack(ret[:])
331 return ret[:], nil
332 }
333
334 func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) {
335 return GenerateKeyPair(cryptoRand.Reader)
336 }
337
338 func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) {
339 if len(seed) != KeySeedSize {
340 panic(kem.ErrSeedSize)
341 }
342 return NewKeyFromSeed(seed[:])
343 }
344
345 func (*scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) {
346 ct = make([]byte, CiphertextSize)
347 ss = make([]byte, SharedKeySize)
348
349 pub, ok := pk.(*PublicKey)
350 if !ok {
351 return nil, nil, kem.ErrTypeMismatch
352 }
353 pub.EncapsulateTo(ct, ss, nil)
354 return
355 }
356
357 func (*scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) (
358 ct, ss []byte, err error) {
359 if len(seed) != EncapsulationSeedSize {
360 return nil, nil, kem.ErrSeedSize
361 }
362
363 ct = make([]byte, CiphertextSize)
364 ss = make([]byte, SharedKeySize)
365
366 pub, ok := pk.(*PublicKey)
367 if !ok {
368 return nil, nil, kem.ErrTypeMismatch
369 }
370 pub.EncapsulateTo(ct, ss, seed)
371 return
372 }
373
374 func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) {
375 if len(ct) != CiphertextSize {
376 return nil, kem.ErrCiphertextSize
377 }
378
379 priv, ok := sk.(*PrivateKey)
380 if !ok {
381 return nil, kem.ErrTypeMismatch
382 }
383 ss := make([]byte, SharedKeySize)
384 priv.DecapsulateTo(ss, ct)
385 return ss, nil
386 }
387
388 func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) {
389 if len(buf) != PublicKeySize {
390 return nil, kem.ErrPubKeySize
391 }
392 var ret PublicKey
393 ret.Unpack(buf)
394 return &ret, nil
395 }
396
397 func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) {
398 if len(buf) != PrivateKeySize {
399 return nil, kem.ErrPrivKeySize
400 }
401 var ret PrivateKey
402 ret.Unpack(buf)
403 return &ret, nil
404 }
405
View as plain text