Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 

227 lignes
6.8 KiB

  1. package sidh
  2. import (
  3. "errors"
  4. . "github.com/cloudflare/sidh/internal/isogeny"
  5. "io"
  6. )
  7. // I keep it bool in order to be able to apply logical NOT
  8. type KeyVariant uint
  9. // Id's correspond to bitlength of the prime field characteristic
  10. // Currently FP_751 is the only one supported by this implementation
  11. const (
  12. FP_503 uint8 = iota
  13. FP_751
  14. FP_964
  15. maxPrimeFieldId
  16. )
  17. const (
  18. // First 2 bits identify SIDH variant third bit indicates
  19. // wether key is a SIKE variant (set) or SIDH (not set)
  20. // 001 - SIDH: corresponds to 2-torsion group
  21. KeyVariant_SIDH_A KeyVariant = 1 << 0
  22. // 010 - SIDH: corresponds to 3-torsion group
  23. KeyVariant_SIDH_B = 1 << 1
  24. // 110 - SIKE
  25. KeyVariant_SIKE = 1<<2 | KeyVariant_SIDH_B
  26. )
  27. // Base type for public and private key. Used mainly to carry domain
  28. // parameters.
  29. type key struct {
  30. // Domain parameters of the algorithm to be used with a key
  31. params *SidhParams
  32. // Flag indicates wether corresponds to 2-, 3-torsion group or SIKE
  33. keyVariant KeyVariant
  34. }
  35. // Defines operations on public key
  36. type PublicKey struct {
  37. key
  38. affine_xP Fp2Element
  39. affine_xQ Fp2Element
  40. affine_xQmP Fp2Element
  41. }
  42. // Defines operations on private key
  43. type PrivateKey struct {
  44. key
  45. // Secret key
  46. Scalar []byte
  47. // Used only by KEM
  48. S []byte
  49. }
  50. // Accessor to the domain parameters
  51. func (key *key) Params() *SidhParams {
  52. return key.params
  53. }
  54. // Accessor to key variant
  55. func (key *key) Variant() KeyVariant {
  56. return key.keyVariant
  57. }
  58. // NewPrivateKey initializes private key.
  59. // Usage of this function guarantees that the object is correctly initialized.
  60. func NewPrivateKey(id uint8, v KeyVariant) *PrivateKey {
  61. prv := &PrivateKey{key: key{params: Params(id), keyVariant: v}}
  62. if (v & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
  63. prv.Scalar = make([]byte, prv.params.A.SecretByteLen)
  64. } else {
  65. prv.Scalar = make([]byte, prv.params.B.SecretByteLen)
  66. }
  67. if v == KeyVariant_SIKE {
  68. prv.S = make([]byte, prv.params.MsgLen)
  69. }
  70. return prv
  71. }
  72. // NewPublicKey initializes public key.
  73. // Usage of this function guarantees that the object is correctly initialized.
  74. func NewPublicKey(id uint8, v KeyVariant) *PublicKey {
  75. return &PublicKey{key: key{params: Params(id), keyVariant: v}}
  76. }
  77. // Import clears content of the public key currently stored in the structure
  78. // and imports key stored in the byte string. Returns error in case byte string
  79. // size is wrong. Doesn't perform any validation.
  80. func (pub *PublicKey) Import(input []byte) error {
  81. if len(input) != pub.Size() {
  82. return errors.New("sidh: input to short")
  83. }
  84. op := CurveOperations{Params: pub.params}
  85. ssSz := pub.params.SharedSecretSize
  86. op.Fp2FromBytes(&pub.affine_xP, input[0:ssSz])
  87. op.Fp2FromBytes(&pub.affine_xQ, input[ssSz:2*ssSz])
  88. op.Fp2FromBytes(&pub.affine_xQmP, input[2*ssSz:3*ssSz])
  89. return nil
  90. }
  91. // Exports currently stored key. In case structure hasn't been filled with key data
  92. // returned byte string is filled with zeros.
  93. func (pub *PublicKey) Export() []byte {
  94. output := make([]byte, pub.params.PublicKeySize)
  95. op := CurveOperations{Params: pub.params}
  96. ssSz := pub.params.SharedSecretSize
  97. op.Fp2ToBytes(output[0:ssSz], &pub.affine_xP)
  98. op.Fp2ToBytes(output[ssSz:2*ssSz], &pub.affine_xQ)
  99. op.Fp2ToBytes(output[2*ssSz:3*ssSz], &pub.affine_xQmP)
  100. return output
  101. }
  102. // Size returns size of the public key in bytes
  103. func (pub *PublicKey) Size() int {
  104. return pub.params.PublicKeySize
  105. }
  106. // Exports currently stored key. In case structure hasn't been filled with key data
  107. // returned byte string is filled with zeros.
  108. func (prv *PrivateKey) Export() []byte {
  109. ret := make([]byte, len(prv.Scalar)+len(prv.S))
  110. copy(ret, prv.S)
  111. copy(ret[len(prv.S):], prv.Scalar)
  112. return ret
  113. }
  114. // Size returns size of the private key in bytes
  115. func (prv *PrivateKey) Size() int {
  116. tmp := len(prv.Scalar)
  117. if prv.Variant() == KeyVariant_SIKE {
  118. tmp += int(prv.params.MsgLen)
  119. }
  120. return tmp
  121. }
  122. // Import clears content of the private key currently stored in the structure
  123. // and imports key from octet string. In case of SIKE, the random value 'S'
  124. // must be prepended to the value of actual private key (see SIKE spec for details).
  125. // Function doesn't import public key value to PrivateKey object.
  126. func (prv *PrivateKey) Import(input []byte) error {
  127. if len(input) != prv.Size() {
  128. return errors.New("sidh: input to short")
  129. }
  130. copy(prv.S, input[:len(prv.S)])
  131. copy(prv.Scalar, input[len(prv.S):])
  132. return nil
  133. }
  134. // Generates random private key for SIDH or SIKE. Generated value is
  135. // formed as little-endian integer from key-space <2^(e2-1)..2^e2 - 1>
  136. // for KeyVariant_A or <2^(s-1)..2^s - 1>, where s = floor(log_2(3^e3)),
  137. // for KeyVariant_B.
  138. //
  139. // Returns error in case user provided RNG fails.
  140. func (prv *PrivateKey) Generate(rand io.Reader) error {
  141. var err error
  142. var dp *DomainParams
  143. if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
  144. dp = &prv.params.A
  145. } else {
  146. dp = &prv.params.B
  147. }
  148. if prv.keyVariant == KeyVariant_SIKE && err == nil {
  149. _, err = io.ReadFull(rand, prv.S)
  150. }
  151. // Private key generation takes advantage of the fact that keyspace for secret
  152. // key is (0, 2^x - 1), for some possitivite value of 'x' (see SIKE, 1.3.8).
  153. // It means that all bytes in the secret key, but the last one, can take any
  154. // value between <0x00,0xFF>. Similarily for the last byte, but generation
  155. // needs to chop off some bits, to make sure generated value is an element of
  156. // a key-space.
  157. _, err = io.ReadFull(rand, prv.Scalar)
  158. if err != nil {
  159. return err
  160. }
  161. prv.Scalar[len(prv.Scalar)-1] &= (1 << (dp.SecretBitLen % 8)) - 1
  162. // Make sure scalar is SecretBitLen long. SIKE spec says that key
  163. // space starts from 0, but I'm not confortable with having low
  164. // value scalars used for private keys. It is still secrure as per
  165. // table 5.1 in [SIKE].
  166. prv.Scalar[len(prv.Scalar)-1] |= 1 << ((dp.SecretBitLen % 8) - 1)
  167. return err
  168. }
  169. // Generates public key.
  170. //
  171. // Constant time.
  172. func (prv *PrivateKey) GeneratePublicKey() *PublicKey {
  173. if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
  174. return publicKeyGenA(prv)
  175. }
  176. return publicKeyGenB(prv)
  177. }
  178. // Computes a shared secret which is a j-invariant. Function requires that pub has
  179. // different KeyVariant than prv. Length of returned output is 2*ceil(log_2 P)/8),
  180. // where P is a prime defining finite field.
  181. //
  182. // It's important to notice that each keypair must not be used more than once
  183. // to calculate shared secret.
  184. //
  185. // Function may return error. This happens only in case provided input is invalid.
  186. // Constant time for properly initialized private and public key.
  187. func DeriveSecret(prv *PrivateKey, pub *PublicKey) ([]byte, error) {
  188. if (pub == nil) || (prv == nil) {
  189. return nil, errors.New("sidh: invalid arguments")
  190. }
  191. if (pub.keyVariant == prv.keyVariant) || (pub.params.Id != prv.params.Id) {
  192. return nil, errors.New("sidh: public and private are incompatbile")
  193. }
  194. if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
  195. return deriveSecretA(prv, pub), nil
  196. } else {
  197. return deriveSecretB(prv, pub), nil
  198. }
  199. }