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.
 
 
 
 

324 rivejä
9.6 KiB

  1. package sidh
  2. import (
  3. "errors"
  4. "io"
  5. "github.com/henrydcase/nobs/dh/sidh/common"
  6. "github.com/henrydcase/nobs/dh/sidh/internal/p434"
  7. "github.com/henrydcase/nobs/dh/sidh/internal/p503"
  8. "github.com/henrydcase/nobs/dh/sidh/internal/p751"
  9. )
  10. // I keep it bool in order to be able to apply logical NOT.
  11. type KeyVariant uint
  12. // Base type for public and private key. Used mainly to carry domain
  13. // parameters.
  14. type Key struct {
  15. // Domain parameters of the algorithm to be used with a key
  16. Params *common.SidhParams
  17. // Flag indicates wether corresponds to 2-, 3-torsion group or SIKE
  18. KeyVariant KeyVariant
  19. }
  20. // Defines operations on public key
  21. type PublicKey struct {
  22. Key
  23. // x-coordinates of P,Q,P-Q in this exact order
  24. affine3Pt [3]common.Fp2
  25. }
  26. // Defines operations on private key
  27. type PrivateKey struct {
  28. Key
  29. // Secret key
  30. Scalar []byte
  31. // Used only by KEM
  32. S []byte
  33. }
  34. // Id's correspond to bitlength of the prime field characteristic
  35. // Currently Fp751 is the only one supported by this implementation
  36. const (
  37. Fp434 = common.Fp434
  38. Fp503 = common.Fp503
  39. Fp751 = common.Fp751
  40. )
  41. const (
  42. // First 2 bits identify SIDH variant third bit indicates
  43. // wether key is a SIKE variant (set) or SIDH (not set)
  44. // 001 - SIDH: corresponds to 2-torsion group
  45. KeyVariantSidhA KeyVariant = 1 << 0
  46. // 010 - SIDH: corresponds to 3-torsion group
  47. KeyVariantSidhB = 1 << 1
  48. // 110 - SIKE
  49. KeyVariantSike = 1<<2 | KeyVariantSidhB
  50. )
  51. // Accessor to key variant.
  52. func (key *Key) Variant() KeyVariant {
  53. return key.KeyVariant
  54. }
  55. // NewPublicKey initializes public key.
  56. // Usage of this function guarantees that the object is correctly initialized.
  57. func NewPublicKey(id uint8, v KeyVariant) *PublicKey {
  58. return &PublicKey{Key: Key{Params: common.Params(id), KeyVariant: v}}
  59. }
  60. // Import clears content of the public key currently stored in the structure
  61. // and imports key stored in the byte string. Returns error in case byte string
  62. // size is wrong. Doesn't perform any validation.
  63. func (pub *PublicKey) Import(input []byte) error {
  64. if len(input) != pub.Size() {
  65. return errors.New("sidh: input to short")
  66. }
  67. ssSz := pub.Params.SharedSecretSize
  68. common.BytesToFp2(&pub.affine3Pt[0], input[0:ssSz], pub.Params.Bytelen)
  69. common.BytesToFp2(&pub.affine3Pt[1], input[ssSz:2*ssSz], pub.Params.Bytelen)
  70. common.BytesToFp2(&pub.affine3Pt[2], input[2*ssSz:3*ssSz], pub.Params.Bytelen)
  71. switch pub.Params.ID {
  72. case Fp434:
  73. p434.ToMontgomery(&pub.affine3Pt[0], &pub.affine3Pt[0])
  74. p434.ToMontgomery(&pub.affine3Pt[1], &pub.affine3Pt[1])
  75. p434.ToMontgomery(&pub.affine3Pt[2], &pub.affine3Pt[2])
  76. case Fp503:
  77. p503.ToMontgomery(&pub.affine3Pt[0], &pub.affine3Pt[0])
  78. p503.ToMontgomery(&pub.affine3Pt[1], &pub.affine3Pt[1])
  79. p503.ToMontgomery(&pub.affine3Pt[2], &pub.affine3Pt[2])
  80. case Fp751:
  81. p751.ToMontgomery(&pub.affine3Pt[0], &pub.affine3Pt[0])
  82. p751.ToMontgomery(&pub.affine3Pt[1], &pub.affine3Pt[1])
  83. p751.ToMontgomery(&pub.affine3Pt[2], &pub.affine3Pt[2])
  84. default:
  85. panic("Unsupported key")
  86. }
  87. return nil
  88. }
  89. // Exports currently stored key. In case structure hasn't been filled with key data
  90. // returned byte string is filled with zeros.
  91. func (pub *PublicKey) Export(out []byte) {
  92. var feTmp [3]common.Fp2
  93. ssSz := pub.Params.SharedSecretSize
  94. switch pub.Params.ID {
  95. case Fp434:
  96. p434.FromMontgomery(&feTmp[0], &pub.affine3Pt[0])
  97. p434.FromMontgomery(&feTmp[1], &pub.affine3Pt[1])
  98. p434.FromMontgomery(&feTmp[2], &pub.affine3Pt[2])
  99. case Fp503:
  100. p503.FromMontgomery(&feTmp[0], &pub.affine3Pt[0])
  101. p503.FromMontgomery(&feTmp[1], &pub.affine3Pt[1])
  102. p503.FromMontgomery(&feTmp[2], &pub.affine3Pt[2])
  103. case Fp751:
  104. p751.FromMontgomery(&feTmp[0], &pub.affine3Pt[0])
  105. p751.FromMontgomery(&feTmp[1], &pub.affine3Pt[1])
  106. p751.FromMontgomery(&feTmp[2], &pub.affine3Pt[2])
  107. default:
  108. panic("Unsupported key")
  109. }
  110. common.Fp2ToBytes(out[0:ssSz], &feTmp[0], pub.Params.Bytelen)
  111. common.Fp2ToBytes(out[ssSz:2*ssSz], &feTmp[1], pub.Params.Bytelen)
  112. common.Fp2ToBytes(out[2*ssSz:3*ssSz], &feTmp[2], pub.Params.Bytelen)
  113. }
  114. // Size returns size of the public key in bytes.
  115. func (pub *PublicKey) Size() int {
  116. return pub.Params.PublicKeySize
  117. }
  118. // NewPrivateKey initializes private key.
  119. // Usage of this function guarantees that the object is correctly initialized.
  120. func NewPrivateKey(id uint8, v KeyVariant) *PrivateKey {
  121. prv := &PrivateKey{Key: Key{Params: common.Params(id), KeyVariant: v}}
  122. if (v & KeyVariantSidhA) == KeyVariantSidhA {
  123. prv.Scalar = make([]byte, prv.Params.A.SecretByteLen)
  124. } else {
  125. prv.Scalar = make([]byte, prv.Params.B.SecretByteLen)
  126. }
  127. if v == KeyVariantSike {
  128. prv.S = make([]byte, prv.Params.MsgLen)
  129. }
  130. return prv
  131. }
  132. // Exports currently stored key. In case structure hasn't been filled with key data
  133. // returned byte string is filled with zeros.
  134. func (prv *PrivateKey) Export(out []byte) {
  135. copy(out, prv.S)
  136. copy(out[len(prv.S):], prv.Scalar)
  137. }
  138. // Size returns size of the private key in bytes.
  139. func (prv *PrivateKey) Size() int {
  140. tmp := len(prv.Scalar)
  141. if prv.Variant() == KeyVariantSike {
  142. tmp += prv.Params.MsgLen
  143. }
  144. return tmp
  145. }
  146. // Size returns size of the shared secret.
  147. func (prv *PrivateKey) SharedSecretSize() int {
  148. return prv.Params.SharedSecretSize
  149. }
  150. // Import clears content of the private key currently stored in the structure
  151. // and imports key from octet string. In case of SIKE, the random value 'S'
  152. // must be prepended to the value of actual private key (see SIKE spec for details).
  153. // Function doesn't import public key value to PrivateKey object.
  154. func (prv *PrivateKey) Import(input []byte) error {
  155. if len(input) != prv.Size() {
  156. return errors.New("sidh: input to short")
  157. }
  158. copy(prv.S, input[:len(prv.S)])
  159. copy(prv.Scalar, input[len(prv.S):])
  160. return nil
  161. }
  162. // Generates random private key for SIDH or SIKE. Generated value is
  163. // formed as little-endian integer from key-space <2^(e2-1)..2^e2 - 1>
  164. // for KeyVariant_A or <2^(s-1)..2^s - 1>, where s = floor(log_2(3^e3)),
  165. // for KeyVariant_B.
  166. //
  167. // Returns error in case user provided RNG fails.
  168. func (prv *PrivateKey) Generate(rand io.Reader) error {
  169. var dp *common.DomainParams
  170. if (prv.KeyVariant & KeyVariantSidhA) == KeyVariantSidhA {
  171. dp = &prv.Params.A
  172. } else {
  173. dp = &prv.Params.B
  174. }
  175. if prv.KeyVariant == KeyVariantSike {
  176. if _, err := io.ReadFull(rand, prv.S); err != nil {
  177. return err
  178. }
  179. }
  180. // Private key generation takes advantage of the fact that keyspace for secret
  181. // key is (0, 2^x - 1), for some possitivite value of 'x' (see SIKE, 1.3.8).
  182. // It means that all bytes in the secret key, but the last one, can take any
  183. // value between <0x00,0xFF>. Similarly for the last byte, but generation
  184. // needs to chop off some bits, to make sure generated value is an element of
  185. // a key-space.
  186. if _, err := io.ReadFull(rand, prv.Scalar); err != nil {
  187. return err
  188. }
  189. prv.Scalar[len(prv.Scalar)-1] &= (1 << (dp.SecretBitLen % 8)) - 1
  190. // Make sure scalar is SecretBitLen long. SIKE spec says that key
  191. // space starts from 0, but I'm not comfortable with having low
  192. // value scalars used for private keys. It is still secrure as per
  193. // table 5.1 in [SIKE].
  194. prv.Scalar[len(prv.Scalar)-1] |= 1 << ((dp.SecretBitLen % 8) - 1)
  195. return nil
  196. }
  197. // Generates public key.
  198. func (prv *PrivateKey) GeneratePublicKey(pub *PublicKey) {
  199. var isA = (prv.KeyVariant & KeyVariantSidhA) == KeyVariantSidhA
  200. if (pub.KeyVariant != prv.KeyVariant) || (pub.Params.ID != prv.Params.ID) {
  201. panic("sidh: incompatbile public key")
  202. }
  203. switch prv.Params.ID {
  204. case Fp434:
  205. if isA {
  206. p434.PublicKeyGenA(&pub.affine3Pt, prv.Scalar)
  207. } else {
  208. p434.PublicKeyGenB(&pub.affine3Pt, prv.Scalar)
  209. }
  210. case Fp503:
  211. if isA {
  212. p503.PublicKeyGenA(&pub.affine3Pt, prv.Scalar)
  213. } else {
  214. p503.PublicKeyGenB(&pub.affine3Pt, prv.Scalar)
  215. }
  216. case Fp751:
  217. if isA {
  218. p751.PublicKeyGenA(&pub.affine3Pt, prv.Scalar)
  219. } else {
  220. p751.PublicKeyGenB(&pub.affine3Pt, prv.Scalar)
  221. }
  222. default:
  223. panic("Field not supported")
  224. }
  225. }
  226. // Computes a SIDH shared secret. Function requires that pub has different
  227. // KeyVariant than prv. Length of returned output is 2*ceil(log_2 P)/8),
  228. // where P is a prime defining finite field.
  229. //
  230. // Caller must make sure key SIDH key pair is not used more than once.
  231. func (prv *PrivateKey) DeriveSecret(ss []byte, pub *PublicKey) {
  232. var isA = (prv.KeyVariant & KeyVariantSidhA) == KeyVariantSidhA
  233. if (pub.KeyVariant == prv.KeyVariant) || (pub.Params.ID != prv.Params.ID) {
  234. panic("sidh: public and private are incompatbile")
  235. }
  236. switch prv.Params.ID {
  237. case Fp434:
  238. if isA {
  239. p434.DeriveSecretA(ss, prv.Scalar, &pub.affine3Pt)
  240. } else {
  241. p434.DeriveSecretB(ss, prv.Scalar, &pub.affine3Pt)
  242. }
  243. case Fp503:
  244. if isA {
  245. p503.DeriveSecretA(ss, prv.Scalar, &pub.affine3Pt)
  246. } else {
  247. p503.DeriveSecretB(ss, prv.Scalar, &pub.affine3Pt)
  248. }
  249. case Fp751:
  250. if isA {
  251. p751.DeriveSecretA(ss, prv.Scalar, &pub.affine3Pt)
  252. } else {
  253. p751.DeriveSecretB(ss, prv.Scalar, &pub.affine3Pt)
  254. }
  255. default:
  256. panic("Field not supported")
  257. }
  258. }
  259. // Alternative API
  260. // TODO: this looks better than the one above - swap it
  261. func (c *Key) Init(fieldID uint8, v KeyVariant) {
  262. c.Params = common.Params(fieldID)
  263. if c.Params == nil {
  264. panic("Params nil")
  265. }
  266. c.KeyVariant = v
  267. }
  268. func (c *PrivateKey) Init(fieldId uint8, v KeyVariant) {
  269. c.Key.Init(fieldId, v)
  270. if (v & KeyVariantSidhA) == KeyVariantSidhA {
  271. c.Scalar = make([]byte, c.Params.A.SecretByteLen)
  272. } else {
  273. c.Scalar = make([]byte, c.Params.B.SecretByteLen)
  274. }
  275. if v == KeyVariantSike {
  276. c.S = make([]byte, c.Params.MsgLen)
  277. }
  278. }
  279. func GeneratePrivateKey(prv *PrivateKey, rng io.Reader) {
  280. prv.Generate(rng)
  281. }
  282. func GeneratePublicKey(pub *PublicKey, prv *PrivateKey) {
  283. prv.GeneratePublicKey(pub)
  284. }
  285. func DeriveSecret(ss []byte, pub *PublicKey, prv *PrivateKey) {
  286. prv.DeriveSecret(ss, pub)
  287. }