kyber.go raw

   1  // Code generated from pkg.templ.go. DO NOT EDIT.
   2  
   3  // Package kyber768 implements the IND-CCA2 secure key encapsulation mechanism
   4  // Kyber768.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 kyber768
   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/kyber768"
  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 Kyber768.CCAKEM public key
  42  type PublicKey struct {
  43  	pk *cpapke.PublicKey
  44  
  45  	hpk [32]byte // H(pk)
  46  }
  47  
  48  // Type of a Kyber768.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 "Kyber768" }
 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  }
 406