kem.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. // kem.go - Kyber key encapsulation mechanism.
  2. //
  3. // To the extent possible under law, Yawning Angel has waived all copyright
  4. // and related or neighboring rights to the software, using the Creative
  5. // Commons "CC0" public domain dedication. See LICENSE or
  6. // <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
  7. package kyber
  8. import (
  9. "bytes"
  10. "crypto/subtle"
  11. "errors"
  12. "io"
  13. "golang.org/x/crypto/sha3"
  14. )
  15. var (
  16. // ErrInvalidKeySize is the error returned when a byte serailized key is
  17. // an invalid size.
  18. ErrInvalidKeySize = errors.New("kyber: invalid key size")
  19. // ErrInvalidCipherTextSize is the error thrown via a panic when a byte
  20. // serialized ciphertext is an invalid size.
  21. ErrInvalidCipherTextSize = errors.New("kyber: invalid ciphertext size")
  22. // ErrInvalidPrivateKey is the error returned when a byte serialized
  23. // private key is malformed.
  24. ErrInvalidPrivateKey = errors.New("kyber: invalid private key")
  25. )
  26. // PrivateKey is a Kyber private key.
  27. type PrivateKey struct {
  28. PublicKey
  29. sk *indcpaSecretKey
  30. z []byte
  31. }
  32. // Bytes returns the byte serialization of a PrivateKey.
  33. func (sk *PrivateKey) Bytes() []byte {
  34. p := sk.PublicKey.p
  35. b := make([]byte, 0, p.secretKeySize)
  36. b = append(b, sk.sk.packed...)
  37. b = append(b, sk.PublicKey.pk.packed...)
  38. b = append(b, sk.PublicKey.pk.h[:]...)
  39. b = append(b, sk.z...)
  40. return b
  41. }
  42. // PrivateKeyFromBytes deserializes a byte serialized PrivateKey.
  43. func (p *ParameterSet) PrivateKeyFromBytes(b []byte) (*PrivateKey, error) {
  44. if len(b) != p.secretKeySize {
  45. return nil, ErrInvalidKeySize
  46. }
  47. sk := new(PrivateKey)
  48. sk.sk = new(indcpaSecretKey)
  49. sk.z = make([]byte, SymSize)
  50. sk.PublicKey.pk = new(indcpaPublicKey)
  51. sk.PublicKey.p = p
  52. // De-serialize the public key first.
  53. off := p.indcpaSecretKeySize
  54. if err := sk.PublicKey.pk.fromBytes(p, b[off:off+p.publicKeySize]); err != nil {
  55. return nil, err
  56. }
  57. off += p.publicKeySize
  58. if !bytes.Equal(sk.PublicKey.pk.h[:], b[off:off+SymSize]) {
  59. return nil, ErrInvalidPrivateKey
  60. }
  61. off += SymSize
  62. copy(sk.z, b[off:])
  63. // Then go back to de-serialize the private key.
  64. if err := sk.sk.fromBytes(p, b[:p.indcpaSecretKeySize]); err != nil {
  65. return nil, err
  66. }
  67. return sk, nil
  68. }
  69. // PublicKey is a Kyber public key.
  70. type PublicKey struct {
  71. pk *indcpaPublicKey
  72. p *ParameterSet
  73. }
  74. // Bytes returns the byte serialization of a PublicKey.
  75. func (pk *PublicKey) Bytes() []byte {
  76. return pk.pk.toBytes()
  77. }
  78. // PublicKeyFromBytes deserializes a byte serialized PublicKey.
  79. func (p *ParameterSet) PublicKeyFromBytes(b []byte) (*PublicKey, error) {
  80. pk := &PublicKey{
  81. pk: new(indcpaPublicKey),
  82. p: p,
  83. }
  84. if err := pk.pk.fromBytes(p, b); err != nil {
  85. return nil, err
  86. }
  87. return pk, nil
  88. }
  89. // GenerateKeyPair generates a private and public key parameterized with the
  90. // given ParameterSet.
  91. func (p *ParameterSet) GenerateKeyPair(rng io.Reader) (*PublicKey, *PrivateKey, error) {
  92. kp := new(PrivateKey)
  93. var err error
  94. if kp.PublicKey.pk, kp.sk, err = p.indcpaKeyPair(rng); err != nil {
  95. return nil, nil, err
  96. }
  97. kp.PublicKey.p = p
  98. kp.z = make([]byte, SymSize)
  99. if _, err := io.ReadFull(rng, kp.z); err != nil {
  100. return nil, nil, err
  101. }
  102. return &kp.PublicKey, kp, nil
  103. }
  104. // KEMEncrypt generates cipher text and shared secret via the CCA-secure Kyber
  105. // key encapsulation mechanism.
  106. func (pk *PublicKey) KEMEncrypt(rng io.Reader) (cipherText []byte, sharedSecret []byte, err error) {
  107. var buf [SymSize]byte
  108. if _, err = io.ReadFull(rng, buf[:]); err != nil {
  109. return nil, nil, err
  110. }
  111. buf = sha3.Sum256(buf[:]) // Don't release system RNG output
  112. hKr := sha3.New512()
  113. hKr.Write(buf[:])
  114. hKr.Write(pk.pk.h[:]) // Multitarget countermeasures for coins + contributory KEM
  115. kr := hKr.Sum(nil)
  116. cipherText = make([]byte, pk.p.cipherTextSize)
  117. pk.p.indcpaEncrypt(cipherText, buf[:], pk.pk, kr[SymSize:]) // coins are in kr[SymSize:]
  118. hc := sha3.Sum256(cipherText)
  119. copy(kr[SymSize:], hc[:]) // overwrite coins in kr with H(c)
  120. hSs := sha3.New256()
  121. hSs.Write(kr)
  122. sharedSecret = hSs.Sum(nil) // hash concatenation of pre-k and H(c) to k
  123. return
  124. }
  125. // KEMDecrypt generates shared secret for given cipher text via the CCA-secure
  126. // Kyber key encapsulation mechanism.
  127. //
  128. // On failures, sharedSecret will contain a randomized value. Providing a
  129. // cipher text that is obviously malformed (too large/small) will result in a
  130. // panic.
  131. func (sk *PrivateKey) KEMDecrypt(cipherText []byte) (sharedSecret []byte) {
  132. var buf [2 * SymSize]byte
  133. p := sk.PublicKey.p
  134. if len(cipherText) != p.CipherTextSize() {
  135. panic(ErrInvalidCipherTextSize)
  136. }
  137. p.indcpaDecrypt(buf[:SymSize], cipherText, sk.sk)
  138. copy(buf[SymSize:], sk.PublicKey.pk.h[:]) // Multitarget countermeasure for coins + contributory KEM
  139. kr := sha3.Sum512(buf[:])
  140. cmp := make([]byte, p.cipherTextSize)
  141. p.indcpaEncrypt(cmp, buf[:SymSize], sk.PublicKey.pk, kr[SymSize:]) // coins are in kr[SymSize:]
  142. hc := sha3.Sum256(cipherText)
  143. copy(kr[SymSize:], hc[:]) // overwrite coins in kr with H(c)
  144. fail := subtle.ConstantTimeSelect(subtle.ConstantTimeCompare(cipherText, cmp), 0, 1)
  145. subtle.ConstantTimeCopy(fail, kr[SymSize:], sk.z) // Overwrite pre-k with z on re-encryption failure
  146. h := sha3.New256()
  147. h.Write(kr[:])
  148. sharedSecret = h.Sum(nil)
  149. return
  150. }