You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

207 lines
6.2 KiB

  1. package sidh
  2. import (
  3. "errors"
  4. . "github.com/cloudflare/p751sidh/p751toolbox"
  5. "io"
  6. )
  7. // I keep it bool in order to be able to apply logical NOT
  8. type KeyVariant uint
  9. type PrimeFieldId uint
  10. // Id's correspond to bitlength of the prime field characteristic
  11. // Currently FP_751 is the only one supported by this implementation
  12. const (
  13. FP_503 PrimeFieldId = iota
  14. FP_751
  15. FP_964
  16. maxPrimeFieldId
  17. )
  18. const (
  19. // First 2 bits identify SIDH variant third bit indicates
  20. // wether key is a SIKE variant (set) or SIDH (not set)
  21. // 001 - SIDH: corresponds to 2-torsion group
  22. KeyVariant_SIDH_A KeyVariant = 1 << 0
  23. // 010 - SIDH: corresponds to 3-torsion group
  24. KeyVariant_SIDH_B = 1 << 1
  25. // 110 - SIKE
  26. KeyVariant_SIKE = 1<<2 | KeyVariant_SIDH_B
  27. )
  28. // Base type for public and private key. Used mainly to carry domain
  29. // parameters.
  30. type key struct {
  31. // Domain parameters of the algorithm to be used with a key
  32. params *SidhParams
  33. // Flag indicates wether corresponds to 2-, 3-torsion group or SIKE
  34. keyVariant KeyVariant
  35. }
  36. // Defines operations on public key
  37. type PublicKey struct {
  38. key
  39. affine_xP ExtensionFieldElement
  40. affine_xQ ExtensionFieldElement
  41. affine_xQmP ExtensionFieldElement
  42. }
  43. // Defines operations on private key
  44. type PrivateKey struct {
  45. key
  46. // Secret key
  47. Scalar []byte
  48. // Used only by KEM
  49. S []byte
  50. }
  51. // Accessor to the domain parameters
  52. func (key *key) Params() *SidhParams {
  53. return key.params
  54. }
  55. // Accessor to key variant
  56. func (key *key) Variant() KeyVariant {
  57. return key.keyVariant
  58. }
  59. // NewPrivateKey initializes private key.
  60. // Usage of this function guarantees that the object is correctly initialized.
  61. func NewPrivateKey(id PrimeFieldId, v KeyVariant) *PrivateKey {
  62. prv := &PrivateKey{key: key{params: Params(id), keyVariant: v}}
  63. prv.Scalar = make([]byte, prv.params.SecretKeySize)
  64. if v == KeyVariant_SIKE {
  65. prv.S = make([]byte, prv.params.MsgLen)
  66. }
  67. return prv
  68. }
  69. // NewPublicKey initializes public key.
  70. // Usage of this function guarantees that the object is correctly initialized.
  71. func NewPublicKey(id PrimeFieldId, v KeyVariant) *PublicKey {
  72. return &PublicKey{key: key{params: Params(id), keyVariant: v}}
  73. }
  74. // Import clears content of the public key currently stored in the structure
  75. // and imports key stored in the byte string. Returns error in case byte string
  76. // size is wrong. Doesn't perform any validation.
  77. func (pub *PublicKey) Import(input []byte) error {
  78. if len(input) != pub.Size() {
  79. return errors.New("sidh: input to short")
  80. }
  81. pub.affine_xP.FromBytes(input[0:pub.params.SharedSecretSize])
  82. pub.affine_xQ.FromBytes(input[pub.params.SharedSecretSize : 2*pub.params.SharedSecretSize])
  83. pub.affine_xQmP.FromBytes(input[2*pub.params.SharedSecretSize : 3*pub.params.SharedSecretSize])
  84. return nil
  85. }
  86. // Exports currently stored key. In case structure hasn't been filled with key data
  87. // returned byte string is filled with zeros.
  88. func (pub *PublicKey) Export() []byte {
  89. output := make([]byte, pub.params.PublicKeySize)
  90. pub.affine_xP.ToBytes(output[0:pub.params.SharedSecretSize])
  91. pub.affine_xQ.ToBytes(output[pub.params.SharedSecretSize : 2*pub.params.SharedSecretSize])
  92. pub.affine_xQmP.ToBytes(output[2*pub.params.SharedSecretSize : 3*pub.params.SharedSecretSize])
  93. return output
  94. }
  95. // Size returns size of the public key in bytes
  96. func (pub *PublicKey) Size() int {
  97. return pub.params.PublicKeySize
  98. }
  99. // Exports currently stored key. In case structure hasn't been filled with key data
  100. // returned byte string is filled with zeros.
  101. func (prv *PrivateKey) Export() []byte {
  102. ret := make([]byte, len(prv.Scalar)+len(prv.S))
  103. copy(ret, prv.S)
  104. copy(ret[len(prv.S):], prv.Scalar)
  105. return ret
  106. }
  107. // Size returns size of the private key in bytes
  108. func (prv *PrivateKey) Size() int {
  109. tmp := prv.params.SecretKeySize
  110. if prv.Variant() == KeyVariant_SIKE {
  111. tmp += int(prv.params.MsgLen)
  112. }
  113. return tmp
  114. }
  115. // Import clears content of the private key currently stored in the structure
  116. // and imports key from octet string. In case of SIKE, the random value 'S'
  117. // must be prepended to the value of actual private key (see SIKE spec for details).
  118. // Function doesn't import public key value to PrivateKey object.
  119. func (prv *PrivateKey) Import(input []byte) error {
  120. if len(input) != prv.Size() {
  121. return errors.New("sidh: input to short")
  122. }
  123. if len(prv.Scalar) != prv.params.SecretKeySize {
  124. return errors.New("sidh: object wrongly initialized")
  125. }
  126. copy(prv.S, input[:len(prv.S)])
  127. copy(prv.Scalar, input[len(prv.S):])
  128. return nil
  129. }
  130. // Generates random private key for SIDH or SIKE. Returns error
  131. // in case user provided RNG or memory initialization fails.
  132. func (prv *PrivateKey) Generate(rand io.Reader) error {
  133. var err error
  134. if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
  135. err = prv.generatePrivateKeyA(rand)
  136. } else {
  137. err = prv.generatePrivateKeyB(rand)
  138. }
  139. if prv.keyVariant == KeyVariant_SIKE && err == nil {
  140. _, err = io.ReadFull(rand, prv.S)
  141. }
  142. return err
  143. }
  144. // Generates public key corresponding to prv. KeyVariant of generated public key
  145. // is same as PrivateKey. Fails only if prv was wrongly initialized.
  146. // Constant time for properly initialzied PrivateKey
  147. func GeneratePublicKey(prv *PrivateKey) (*PublicKey, error) {
  148. if prv == nil {
  149. return nil, errors.New("sidh: invalid arguments")
  150. }
  151. if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
  152. return publicKeyGenA(prv), nil
  153. } else {
  154. return publicKeyGenB(prv), nil
  155. }
  156. }
  157. // Computes a shared secret which is a j-invariant. Function requires that pub has
  158. // different KeyVariant than prv. Length of returned output is 2*ceil(log_2 P)/8),
  159. // where P is a prime defining finite field.
  160. //
  161. // It's important to notice that each keypair must not be used more than once
  162. // to calculate shared secret.
  163. //
  164. // Function may return error. This happens only in case provided input is invalid.
  165. // Constant time for properly initialized private and public key.
  166. func DeriveSecret(prv *PrivateKey, pub *PublicKey) ([]byte, error) {
  167. if (pub == nil) || (prv == nil) {
  168. return nil, errors.New("sidh: invalid arguments")
  169. }
  170. if (pub.keyVariant == prv.keyVariant) || (pub.params.Id != prv.params.Id) {
  171. return nil, errors.New("sidh: public and private are incompatbile")
  172. }
  173. if (prv.keyVariant & KeyVariant_SIDH_A) == KeyVariant_SIDH_A {
  174. return deriveSecretA(prv, pub), nil
  175. } else {
  176. return deriveSecretB(prv, pub), nil
  177. }
  178. }