kex.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. // kex.go - Kyber key exchange.
  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. "errors"
  10. "io"
  11. "golang.org/x/crypto/sha3"
  12. )
  13. var (
  14. // ErrInvalidMessageSize is the error thrown via a panic when a initator
  15. // or responder message is an invalid size.
  16. ErrInvalidMessageSize = errors.New("kyber: invalid message size")
  17. // ErrParameterSetMismatch is the error thrown via a panic when there
  18. // is a mismatch between parameter sets.
  19. ErrParameterSetMismatch = errors.New("kyber: parameter set mismatch")
  20. )
  21. // UAKEInitiatorMessageSize returns the size of the initiator UAKE message
  22. // in bytes.
  23. func (p *ParameterSet) UAKEInitiatorMessageSize() int {
  24. return p.PublicKeySize() + p.CipherTextSize()
  25. }
  26. // UAKEResponderMessageSize returns the size of the responder UAKE message
  27. // in bytes.
  28. func (p *ParameterSet) UAKEResponderMessageSize() int {
  29. return p.CipherTextSize()
  30. }
  31. // UAKEInitiatorState is a initiator UAKE instance. Each instance MUST only
  32. // be used for one key exchange and never reused.
  33. type UAKEInitiatorState struct {
  34. // Message is the UAKE message to send to the responder.
  35. Message []byte
  36. eSk *PrivateKey
  37. tk []byte
  38. }
  39. // Shared generates a shared secret for the given UAKE instance and responder
  40. // message.
  41. //
  42. // On failures, sharedSecret will contain a randomized value. Providing a
  43. // cipher text that is obviously malformed (too large/small) will result in a
  44. // panic.
  45. func (s *UAKEInitiatorState) Shared(recv []byte) (sharedSecret []byte) {
  46. xof := sha3.NewShake256()
  47. var tk []byte
  48. tk = s.eSk.KEMDecrypt(recv)
  49. xof.Write(tk)
  50. xof.Write(s.tk)
  51. sharedSecret = make([]byte, SymSize)
  52. xof.Read(sharedSecret)
  53. return
  54. }
  55. // NewUAKEInitiatorState creates a new initiator UAKE instance.
  56. func (pk *PublicKey) NewUAKEInitiatorState(rng io.Reader) (*UAKEInitiatorState, error) {
  57. s := new(UAKEInitiatorState)
  58. s.Message = make([]byte, 0, pk.p.UAKEInitiatorMessageSize())
  59. var err error
  60. _, s.eSk, err = pk.p.GenerateKeyPair(rng)
  61. if err != nil {
  62. return nil, err
  63. }
  64. s.Message = append(s.Message, s.eSk.PublicKey.Bytes()...)
  65. var ct []byte
  66. ct, s.tk, err = pk.KEMEncrypt(rng)
  67. if err != nil {
  68. return nil, err
  69. }
  70. s.Message = append(s.Message, ct...)
  71. return s, nil
  72. }
  73. // UAKEResponderShared generates a responder message and shared secret given
  74. // a initiator UAKE message.
  75. //
  76. // On failures, sharedSecret will contain a randomized value. Providing a
  77. // cipher text that is obviously malformed (too large/small) will result in a
  78. // panic.
  79. func (sk *PrivateKey) UAKEResponderShared(rng io.Reader, recv []byte) (message, sharedSecret []byte) {
  80. p := sk.PublicKey.p
  81. pkLen := p.PublicKeySize()
  82. // Deserialize the peer's ephemeral public key.
  83. if len(recv) != p.UAKEInitiatorMessageSize() {
  84. panic(ErrInvalidMessageSize)
  85. }
  86. rawPk, ct := recv[:pkLen], recv[pkLen:]
  87. pk, err := p.PublicKeyFromBytes(rawPk)
  88. if err != nil {
  89. panic(err)
  90. }
  91. xof := sha3.NewShake256()
  92. var tk []byte
  93. message, tk, err = pk.KEMEncrypt(rng)
  94. if err != nil {
  95. panic(err)
  96. }
  97. xof.Write(tk)
  98. tk = sk.KEMDecrypt(ct)
  99. xof.Write(tk)
  100. sharedSecret = make([]byte, SymSize)
  101. xof.Read(sharedSecret)
  102. return
  103. }
  104. // AKEInitiatorMessageSize returns the size of the initiator AKE message
  105. // in bytes.
  106. func (p *ParameterSet) AKEInitiatorMessageSize() int {
  107. return p.PublicKeySize() + p.CipherTextSize()
  108. }
  109. // AKEResponderMessageSize returns the size of the responder AKE message
  110. // in bytes.
  111. func (p *ParameterSet) AKEResponderMessageSize() int {
  112. return 2 * p.CipherTextSize()
  113. }
  114. // AKEInitiatorState is a initiator AKE instance. Each instance MUST only be
  115. // used for one key exchange and never reused.
  116. type AKEInitiatorState struct {
  117. // Message is the AKE message to send to the responder.
  118. Message []byte
  119. eSk *PrivateKey
  120. tk []byte
  121. }
  122. // Shared generates a shared secret for the given AKE instance, responder
  123. // message, and long term initiator private key.
  124. //
  125. // On failures sharedSecret will contain a randomized value. Providing a
  126. // malformed responder message, or a private key that uses a different
  127. // ParamterSet than the AKEInitiatorState will result in a panic.
  128. func (s *AKEInitiatorState) Shared(recv []byte, initiatorPrivateKey *PrivateKey) (sharedSecret []byte) {
  129. p := s.eSk.PublicKey.p
  130. if initiatorPrivateKey.PublicKey.p != p {
  131. panic(ErrParameterSetMismatch)
  132. }
  133. if len(recv) != p.AKEResponderMessageSize() {
  134. panic(ErrInvalidMessageSize)
  135. }
  136. ctLen := p.CipherTextSize()
  137. xof := sha3.NewShake256()
  138. var tk []byte
  139. tk = s.eSk.KEMDecrypt(recv[:ctLen])
  140. xof.Write(tk)
  141. tk = initiatorPrivateKey.KEMDecrypt(recv[ctLen:])
  142. xof.Write(tk)
  143. xof.Write(s.tk)
  144. sharedSecret = make([]byte, SymSize)
  145. xof.Read(sharedSecret)
  146. return
  147. }
  148. // NewAKEInitiatorState creates a new initiator AKE instance.
  149. func (pk *PublicKey) NewAKEInitiatorState(rng io.Reader) (*AKEInitiatorState, error) {
  150. s := new(AKEInitiatorState)
  151. // This is identical to the UAKE case, so just reuse the code.
  152. us, err := pk.NewUAKEInitiatorState(rng)
  153. if err != nil {
  154. return nil, err
  155. }
  156. s.Message = us.Message
  157. s.eSk = us.eSk
  158. s.tk = us.tk
  159. return s, nil
  160. }
  161. // AKEResponderShared generates a responder message and shared secret given
  162. // a initiator AKE message and long term initiator public key.
  163. //
  164. // On failures sharedSecret will contain a randomized value. Providing a
  165. // malformed responder message, or a private key that uses a different
  166. // ParamterSet than the AKEInitiatorState will result in a panic.
  167. func (sk *PrivateKey) AKEResponderShared(rng io.Reader, recv []byte, peerPublicKey *PublicKey) (message, sharedSecret []byte) {
  168. p := sk.PublicKey.p
  169. pkLen := p.PublicKeySize()
  170. if peerPublicKey.p != p {
  171. panic(ErrParameterSetMismatch)
  172. }
  173. // Deserialize the peer's ephemeral public key.
  174. if len(recv) != p.AKEInitiatorMessageSize() {
  175. panic(ErrInvalidMessageSize)
  176. }
  177. rawPk, ct := recv[:pkLen], recv[pkLen:]
  178. pk, err := p.PublicKeyFromBytes(rawPk)
  179. if err != nil {
  180. panic(err)
  181. }
  182. message = make([]byte, 0, p.AKEResponderMessageSize())
  183. xof := sha3.NewShake256()
  184. var tk, tmp []byte
  185. tmp, tk, err = pk.KEMEncrypt(rng)
  186. if err != nil {
  187. panic(err)
  188. }
  189. xof.Write(tk)
  190. message = append(message, tmp...)
  191. tmp, tk, err = peerPublicKey.KEMEncrypt(rng)
  192. if err != nil {
  193. panic(err)
  194. }
  195. xof.Write(tk)
  196. message = append(message, tmp...)
  197. tk = sk.KEMDecrypt(ct)
  198. xof.Write(tk)
  199. sharedSecret = make([]byte, SymSize)
  200. xof.Read(sharedSecret)
  201. return
  202. }