github.com/cloudflare/circl@v1.5.0/kem/kyber/kyber512/kyber.go (about) 1 // Code generated from pkg.templ.go. DO NOT EDIT. 2 3 // Package kyber512 implements the IND-CCA2 secure key encapsulation mechanism 4 // Kyber512.CCAKEM as submitted to round 3 of the NIST PQC competition and 5 // described in 6 // 7 // https://pq-crystals.org/kyber/data/kyber-specification-round3.pdf 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 // Size of seed for NewKeyFromSeed 23 KeySeedSize = cpapke.KeySeedSize + 32 24 25 // Size of seed for EncapsulateTo. 26 EncapsulationSeedSize = 32 27 28 // Size of the established shared key. 29 SharedKeySize = 32 30 31 // Size of the encapsulated shared key. 32 CiphertextSize = cpapke.CiphertextSize 33 34 // Size of a packed public key. 35 PublicKeySize = cpapke.PublicKeySize 36 37 // Size of a packed private key. 38 PrivateKeySize = cpapke.PrivateKeySize + cpapke.PublicKeySize + 64 39 ) 40 41 // Type of a Kyber512.CCAKEM public key 42 type PublicKey struct { 43 pk *cpapke.PublicKey 44 45 hpk [32]byte // H(pk) 46 } 47 48 // Type of a Kyber512.CCAKEM private key 49 type PrivateKey struct { 50 sk *cpapke.PrivateKey 51 pk *cpapke.PublicKey 52 hpk [32]byte // H(pk) 53 z [32]byte 54 } 55 56 // NewKeyFromSeed derives a public/private keypair deterministically 57 // from the given seed. 58 // 59 // Panics if seed is not of length KeySeedSize. 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 // Compute H(pk) 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 // GenerateKeyPair generates public and private keys using entropy from rand. 84 // If rand is nil, crypto/rand.Reader will be used. 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 // EncapsulateTo generates a shared key and ciphertext that contains it 99 // for the public key using randomness from seed and writes the shared key 100 // to ss and ciphertext to ct. 101 // 102 // Panics if ss, ct or seed are not of length SharedKeySize, CiphertextSize 103 // and EncapsulationSeedSize respectively. 104 // 105 // seed may be nil, in which case crypto/rand.Reader is used to generate one. 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 var m [32]byte 127 // m = H(seed), the hash of shame 128 h := sha3.New256() 129 h.Write(seed) 130 h.Read(m[:]) 131 132 // (K', r) = G(m ‖ H(pk)) 133 var kr [64]byte 134 g := sha3.New512() 135 g.Write(m[:]) 136 g.Write(pk.hpk[:]) 137 g.Read(kr[:]) 138 139 // c = Kyber.CPAPKE.Enc(pk, m, r) 140 pk.pk.EncryptTo(ct, m[:], kr[32:]) 141 142 // Compute H(c) and put in second slot of kr, which will be (K', H(c)). 143 h.Reset() 144 h.Write(ct[:CiphertextSize]) 145 h.Read(kr[32:]) 146 147 // K = KDF(K' ‖ H(c)) 148 kdf := sha3.NewShake256() 149 kdf.Write(kr[:]) 150 kdf.Read(ss[:SharedKeySize]) 151 } 152 153 // DecapsulateTo computes the shared key which is encapsulated in ct 154 // for the private key. 155 // 156 // Panics if ct or ss are not of length CiphertextSize and SharedKeySize 157 // respectively. 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 // m' = Kyber.CPAPKE.Dec(sk, ct) 168 var m2 [32]byte 169 sk.sk.DecryptTo(m2[:], ct) 170 171 // (K'', r') = G(m' ‖ H(pk)) 172 var kr2 [64]byte 173 g := sha3.New512() 174 g.Write(m2[:]) 175 g.Write(sk.hpk[:]) 176 g.Read(kr2[:]) 177 178 // c' = Kyber.CPAPKE.Enc(pk, m', r') 179 var ct2 [CiphertextSize]byte 180 sk.pk.EncryptTo(ct2[:], m2[:], kr2[32:]) 181 182 // Compute H(c) and put in second slot of kr2, which will be (K'', H(c)). 183 h := sha3.New256() 184 h.Write(ct[:CiphertextSize]) 185 h.Read(kr2[32:]) 186 187 // Replace K'' by z in the first slot of kr2 if c ≠ c'. 188 subtle.ConstantTimeCopy( 189 1-subtle.ConstantTimeCompare(ct, ct2[:]), 190 kr2[:32], 191 sk.z[:], 192 ) 193 194 // K = KDF(K''/z, H(c)) 195 kdf := sha3.NewShake256() 196 kdf.Write(kr2[:]) 197 kdf.Read(ss) 198 } 199 200 // Packs sk to buf. 201 // 202 // Panics if buf is not of size PrivateKeySize. 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 // Unpacks sk from buf. 218 // 219 // Panics if buf is not of size PrivateKeySize. 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 // Packs pk to buf. 236 // 237 // Panics if buf is not of size PublicKeySize. 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 // Unpacks pk from buf. 247 // 248 // Panics if buf is not of size PublicKeySize. 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 // Compute cached H(pk) 258 h := sha3.New256() 259 h.Write(buf) 260 h.Read(pk.hpk[:]) 261 262 } 263 264 // Boilerplate down below for the KEM scheme API. 265 266 type scheme struct{} 267 268 var sch kem.Scheme = &scheme{} 269 270 // Scheme returns a KEM interface. 271 func Scheme() kem.Scheme { return sch } 272 273 func (*scheme) Name() string { return "Kyber512" } 274 func (*scheme) PublicKeySize() int { return PublicKeySize } 275 func (*scheme) PrivateKeySize() int { return PrivateKeySize } 276 func (*scheme) SeedSize() int { return KeySeedSize } 277 func (*scheme) SharedKeySize() int { return SharedKeySize } 278 func (*scheme) CiphertextSize() int { return CiphertextSize } 279 func (*scheme) EncapsulationSeedSize() int { return EncapsulationSeedSize } 280 281 func (sk *PrivateKey) Scheme() kem.Scheme { return sch } 282 func (pk *PublicKey) Scheme() kem.Scheme { return sch } 283 284 func (sk *PrivateKey) MarshalBinary() ([]byte, error) { 285 var ret [PrivateKeySize]byte 286 sk.Pack(ret[:]) 287 return ret[:], nil 288 } 289 290 func (sk *PrivateKey) Equal(other kem.PrivateKey) bool { 291 oth, ok := other.(*PrivateKey) 292 if !ok { 293 return false 294 } 295 if sk.pk == nil && oth.pk == nil { 296 return true 297 } 298 if sk.pk == nil || oth.pk == nil { 299 return false 300 } 301 if !bytes.Equal(sk.hpk[:], oth.hpk[:]) || 302 subtle.ConstantTimeCompare(sk.z[:], oth.z[:]) != 1 { 303 return false 304 } 305 return sk.sk.Equal(oth.sk) 306 } 307 308 func (pk *PublicKey) Equal(other kem.PublicKey) bool { 309 oth, ok := other.(*PublicKey) 310 if !ok { 311 return false 312 } 313 if pk.pk == nil && oth.pk == nil { 314 return true 315 } 316 if pk.pk == nil || oth.pk == nil { 317 return false 318 } 319 return bytes.Equal(pk.hpk[:], oth.hpk[:]) 320 } 321 322 func (sk *PrivateKey) Public() kem.PublicKey { 323 pk := new(PublicKey) 324 pk.pk = sk.pk 325 copy(pk.hpk[:], sk.hpk[:]) 326 return pk 327 } 328 329 func (pk *PublicKey) MarshalBinary() ([]byte, error) { 330 var ret [PublicKeySize]byte 331 pk.Pack(ret[:]) 332 return ret[:], nil 333 } 334 335 func (*scheme) GenerateKeyPair() (kem.PublicKey, kem.PrivateKey, error) { 336 return GenerateKeyPair(cryptoRand.Reader) 337 } 338 339 func (*scheme) DeriveKeyPair(seed []byte) (kem.PublicKey, kem.PrivateKey) { 340 if len(seed) != KeySeedSize { 341 panic(kem.ErrSeedSize) 342 } 343 return NewKeyFromSeed(seed[:]) 344 } 345 346 func (*scheme) Encapsulate(pk kem.PublicKey) (ct, ss []byte, err error) { 347 ct = make([]byte, CiphertextSize) 348 ss = make([]byte, SharedKeySize) 349 350 pub, ok := pk.(*PublicKey) 351 if !ok { 352 return nil, nil, kem.ErrTypeMismatch 353 } 354 pub.EncapsulateTo(ct, ss, nil) 355 return 356 } 357 358 func (*scheme) EncapsulateDeterministically(pk kem.PublicKey, seed []byte) ( 359 ct, ss []byte, err error) { 360 if len(seed) != EncapsulationSeedSize { 361 return nil, nil, kem.ErrSeedSize 362 } 363 364 ct = make([]byte, CiphertextSize) 365 ss = make([]byte, SharedKeySize) 366 367 pub, ok := pk.(*PublicKey) 368 if !ok { 369 return nil, nil, kem.ErrTypeMismatch 370 } 371 pub.EncapsulateTo(ct, ss, seed) 372 return 373 } 374 375 func (*scheme) Decapsulate(sk kem.PrivateKey, ct []byte) ([]byte, error) { 376 if len(ct) != CiphertextSize { 377 return nil, kem.ErrCiphertextSize 378 } 379 380 priv, ok := sk.(*PrivateKey) 381 if !ok { 382 return nil, kem.ErrTypeMismatch 383 } 384 ss := make([]byte, SharedKeySize) 385 priv.DecapsulateTo(ss, ct) 386 return ss, nil 387 } 388 389 func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (kem.PublicKey, error) { 390 var ret PublicKey 391 if len(buf) != PublicKeySize { 392 return nil, kem.ErrPubKeySize 393 } 394 ret.Unpack(buf) 395 return &ret, nil 396 } 397 398 func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (kem.PrivateKey, error) { 399 if len(buf) != PrivateKeySize { 400 return nil, kem.ErrPrivKeySize 401 } 402 var ret PrivateKey 403 ret.Unpack(buf) 404 return &ret, nil 405 }