您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

218 行
6.1 KiB

  1. // [SIKE] http://www.sike.org/files/SIDH-spec.pdf
  2. // [REF] https://github.com/Microsoft/PQCrypto-SIDH
  3. package sike
  4. import (
  5. "crypto/subtle"
  6. "errors"
  7. "io"
  8. // TODO: Use implementation from xcrypto, once PR below merged
  9. // https://go-review.googlesource.com/c/crypto/+/111281/
  10. . "github.com/cloudflare/sidh/sidh"
  11. cshake "github.com/henrydcase/nobs/hash/sha3"
  12. )
  13. // Constants used for cSHAKE customization
  14. // Those values are different than in [SIKE] - they are encoded on 16bits. This is
  15. // done in order for implementation to be compatible with [REF] and test vectors.
  16. var G = []byte{0x00, 0x00}
  17. var H = []byte{0x01, 0x00}
  18. var F = []byte{0x02, 0x00}
  19. // Generates cShake-256 sum
  20. func cshakeSum(out, in, S []byte) {
  21. h := cshake.NewCShake256(nil, S)
  22. h.Write(in)
  23. h.Read(out)
  24. }
  25. func encrypt(skA *PrivateKey, pkA, pkB *PublicKey, ptext []byte) ([]byte, error) {
  26. var n [40]byte // n can is max 320-bit (see 1.4 of [SIKE])
  27. var ptextLen = len(ptext)
  28. if pkB.Variant() != KeyVariant_SIKE {
  29. return nil, errors.New("wrong key type")
  30. }
  31. j, err := DeriveSecret(skA, pkB)
  32. if err != nil {
  33. return nil, err
  34. }
  35. cshakeSum(n[:ptextLen], j, F)
  36. for i, _ := range ptext {
  37. n[i] ^= ptext[i]
  38. }
  39. ret := make([]byte, pkA.Size()+ptextLen)
  40. copy(ret, pkA.Export())
  41. copy(ret[pkA.Size():], n[:ptextLen])
  42. return ret, nil
  43. }
  44. // -----------------------------------------------------------------------------
  45. // PKE interface
  46. //
  47. // Uses SIKE public key to encrypt plaintext. Requires cryptographically secure PRNG
  48. // Returns ciphertext in case encryption succeeds. Returns error in case PRNG fails
  49. // or wrongly formated input was provided.
  50. func Encrypt(rng io.Reader, pub *PublicKey, ptext []byte) ([]byte, error) {
  51. var params = pub.Params()
  52. var ptextLen = uint(len(ptext))
  53. // c1 must be security level + 64 bits (see [SIKE] 1.4 and 4.3.3)
  54. if ptextLen != (params.KemSize + 8) {
  55. return nil, errors.New("Unsupported message length")
  56. }
  57. skA := NewPrivateKey(params.Id, KeyVariant_SIDH_A)
  58. err := skA.Generate(rng)
  59. if err != nil {
  60. return nil, err
  61. }
  62. pkA := skA.GeneratePublicKey()
  63. return encrypt(skA, pkA, pub, ptext)
  64. }
  65. // Uses SIKE private key to decrypt ciphertext. Returns plaintext in case
  66. // decryption succeeds or error in case unexptected input was provided.
  67. // Constant time
  68. func Decrypt(prv *PrivateKey, ctext []byte) ([]byte, error) {
  69. var params = prv.Params()
  70. var n [40]byte // n can is max 320-bit (see 1.4 of [SIKE])
  71. var c1_len int
  72. var pk_len = params.PublicKeySize
  73. if prv.Variant() != KeyVariant_SIKE {
  74. return nil, errors.New("wrong key type")
  75. }
  76. // ctext is a concatenation of (pubkey_A || c1=ciphertext)
  77. // it must be security level + 64 bits (see [SIKE] 1.4 and 4.3.3)
  78. c1_len = len(ctext) - pk_len
  79. if c1_len != (int(params.KemSize) + 8) {
  80. return nil, errors.New("wrong size of cipher text")
  81. }
  82. c0 := NewPublicKey(params.Id, KeyVariant_SIDH_A)
  83. err := c0.Import(ctext[:pk_len])
  84. if err != nil {
  85. return nil, err
  86. }
  87. j, err := DeriveSecret(prv, c0)
  88. if err != nil {
  89. return nil, err
  90. }
  91. cshakeSum(n[:c1_len], j, F)
  92. for i, _ := range n[:c1_len] {
  93. n[i] ^= ctext[pk_len+i]
  94. }
  95. return n[:c1_len], nil
  96. }
  97. // -----------------------------------------------------------------------------
  98. // KEM interface
  99. //
  100. // Encapsulation receives the public key and generates SIKE ciphertext and shared secret.
  101. // The generated ciphertext is used for authentication.
  102. // The rng must be cryptographically secure PRNG.
  103. // Error is returned in case PRNG fails or wrongly formated input was provided.
  104. func Encapsulate(rng io.Reader, pub *PublicKey) (ctext []byte, secret []byte, err error) {
  105. var params = pub.Params()
  106. // Buffer for random, secret message
  107. var ptext = make([]byte, params.MsgLen)
  108. // r = G(ptext||pub)
  109. var r = make([]byte, params.A.SecretByteLen)
  110. // Resulting shared secret
  111. secret = make([]byte, params.KemSize)
  112. // Generate ephemeral value
  113. _, err = io.ReadFull(rng, ptext)
  114. if err != nil {
  115. return nil, nil, err
  116. }
  117. h := cshake.NewCShake256(nil, G)
  118. h.Write(ptext)
  119. h.Write(pub.Export())
  120. h.Read(r)
  121. // cSHAKE256 implementation is byte oriented. Ensure bitlength is not bigger then to 2^e2-1
  122. r[len(r)-1] &= (1 << (params.A.SecretBitLen % 8)) - 1
  123. // (c0 || c1) = Enc(pkA, ptext; r)
  124. skA := NewPrivateKey(params.Id, KeyVariant_SIDH_A)
  125. err = skA.Import(r)
  126. if err != nil {
  127. return nil, nil, err
  128. }
  129. pkA := skA.GeneratePublicKey()
  130. ctext, err = encrypt(skA, pkA, pub, ptext)
  131. if err != nil {
  132. return nil, nil, err
  133. }
  134. // K = H(ptext||(c0||c1))
  135. h = cshake.NewCShake256(nil, H)
  136. h.Write(ptext)
  137. h.Write(ctext)
  138. h.Read(secret)
  139. return ctext, secret, nil
  140. }
  141. // Decapsulate given the keypair and ciphertext as inputs, Decapsulate outputs a shared
  142. // secret if plaintext verifies correctly, otherwise function outputs random value.
  143. // Decapsulation may fail in case input is wrongly formated.
  144. // Constant time for properly initialized input.
  145. func Decapsulate(prv *PrivateKey, pub *PublicKey, ctext []byte) ([]byte, error) {
  146. var params = pub.Params()
  147. var r = make([]byte, params.A.SecretByteLen)
  148. // Resulting shared secret
  149. var secret = make([]byte, params.KemSize)
  150. var skA = NewPrivateKey(params.Id, KeyVariant_SIDH_A)
  151. m, err := Decrypt(prv, ctext)
  152. if err != nil {
  153. return nil, err
  154. }
  155. // r' = G(m'||pub)
  156. h := cshake.NewCShake256(nil, G)
  157. h.Write(m)
  158. h.Write(pub.Export())
  159. h.Read(r)
  160. // cSHAKE256 implementation is byte oriented: Ensure bitlength is not bigger than 2^e2-1
  161. r[len(r)-1] &= (1 << (params.A.SecretBitLen % 8)) - 1
  162. // Never fails
  163. skA.Import(r)
  164. // Never fails
  165. pkA := skA.GeneratePublicKey()
  166. c0 := pkA.Export()
  167. h = cshake.NewCShake256(nil, H)
  168. if subtle.ConstantTimeCompare(c0, ctext[:len(c0)]) == 1 {
  169. h.Write(m)
  170. } else {
  171. // S is chosen at random when generating a key and unknown to other party. It
  172. // may seem weird, but it's correct. It is important that S is unpredictable
  173. // to other party. Without this check, it is possible to recover a secret, by
  174. // providing series of invalid ciphertexts. It is also important that in case
  175. //
  176. // See more details in "On the security of supersingular isogeny cryptosystems"
  177. // (S. Galbraith, et al., 2016, ePrint #859).
  178. h.Write(prv.S)
  179. }
  180. h.Write(ctext)
  181. h.Read(secret)
  182. return secret, nil
  183. }