curve.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. package tools
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "math/big"
  7. "git.ali33.ru/fcg-xvii/go-tools/json"
  8. )
  9. var (
  10. MinP = big.NewInt(11)
  11. )
  12. // 4a³ + 27b² = 0 - проверка кривой на сингулярность
  13. func NewCurve(a, b *big.Int) (*Curve, error) {
  14. c := &Curve{
  15. a: new(big.Int).Set(a),
  16. b: new(big.Int).Set(b),
  17. }
  18. return c, c.IsSingular()
  19. }
  20. /*
  21. func NewRandom(a, b *big.Int) (*Curve, error) {
  22. c := Curve{
  23. a: new(big.Int).Set(a),
  24. b: new(big.Int).Set(b),
  25. }
  26. if err := c.IsSingular(); err != nil {
  27. return nil, err
  28. }
  29. }
  30. */
  31. type Curve struct {
  32. a *big.Int // константа a
  33. b *big.Int // константа b
  34. p *big.Int // размер конечного поля
  35. g *Point // базовая точка подгруппы
  36. //n *big.Int // порядок подгруппы
  37. //h *big.Int // кофактор подгруппы
  38. }
  39. func (s *Curve) A() (res *big.Int) {
  40. return intCopy(s.a)
  41. }
  42. func (s *Curve) B() (res *big.Int) {
  43. return intCopy(s.b)
  44. }
  45. func (s *Curve) G() (res *Point) {
  46. if s.g != nil {
  47. res = s.g.Copy()
  48. }
  49. return
  50. }
  51. func (s *Curve) P() (res *big.Int) {
  52. if s.p != nil {
  53. res = intCopy(s.p)
  54. }
  55. return
  56. }
  57. // Проверка, установлен ли размер конечного поля
  58. func (s *Curve) IsValidP() (err error) {
  59. if err = s.IsValidConstants(); err == nil {
  60. if s.p == nil {
  61. err = errors.New("размер конечного поля не установлен")
  62. }
  63. }
  64. return
  65. }
  66. func (s *Curve) IsValidG() (err error) {
  67. if err = s.IsValidP(); err == nil {
  68. if s.g == nil {
  69. err = errors.New("базовая точка подгруппы g не определена")
  70. }
  71. }
  72. return
  73. }
  74. // Возвращает строку уравнения кривой
  75. func (s *Curve) FormulaString() string {
  76. return fmt.Sprintf(
  77. "y² = x³ + %sx + %s",
  78. mustBigInt(s.a),
  79. mustBigInt(s.b),
  80. )
  81. }
  82. // Проверка кривой на сингулярность (4a³ + 27b² = 0)
  83. func (s *Curve) IsSingular() (err error) {
  84. if err = s.IsValidConstants(); err != nil {
  85. return
  86. }
  87. l := new(big.Int).Mul(new(big.Int).Exp(s.a, big.NewInt(3), nil), big.NewInt(4))
  88. r := new(big.Int).Mul(new(big.Int).Exp(s.b, big.NewInt(2), nil), big.NewInt(27))
  89. if l.Add(l, r).Cmp(big.NewInt(0)) == 0 {
  90. err = fmt.Errorf("кривая [ %s ] сингулярна и не рекомендуется к использованию", s.FormulaString())
  91. }
  92. return
  93. }
  94. // Проверка констант уравнения на валидность
  95. func (s *Curve) IsValidConstants() error {
  96. if s.a == nil {
  97. return errors.New("константа [ a ] не определена")
  98. }
  99. if s.b == nil {
  100. return errors.New("константа [ b ] не определена")
  101. }
  102. return nil
  103. }
  104. // Установка размера конечного поля
  105. func (s *Curve) SetP(p *big.Int) (err error) {
  106. if s.p != nil {
  107. return errors.New("резмер конечного поля уже определен")
  108. }
  109. if err = s.IsValidConstants(); err != nil {
  110. return
  111. }
  112. if !IsPrime(p) {
  113. err = fmt.Errorf("число [ %s ] не является простым. Размер конечного поля должен быть простым числом", p)
  114. return
  115. }
  116. s.p = p
  117. return
  118. }
  119. func (s *Curve) Point(x, y *big.Int) *Point {
  120. return NewPoint(x, y, s)
  121. }
  122. func (s *Curve) InverseMod(k, p *big.Int) (res *big.Int, err error) {
  123. if err = s.IsValidP(); err != nil {
  124. return
  125. }
  126. if k == nil {
  127. err = errors.New("[ k ] не определено")
  128. return
  129. } else if rk := k.Cmp(intZero); rk == 0 {
  130. err = errors.New("[ k ] == 0. Деление на 0 невозможно")
  131. return
  132. } else if rk < 0 {
  133. // k ** -1 = p - (-k) ** -1 (mod p)
  134. // point - self.inverseMod(-k, point)
  135. var iMod *big.Int
  136. if iMod, err = s.InverseMod(Neg(k), p); err == nil {
  137. res = Sub(p, iMod)
  138. }
  139. } else {
  140. s, olds := big.NewInt(0), big.NewInt(1)
  141. t, oldt := big.NewInt(1), big.NewInt(0)
  142. r, oldr := intCopy(p), intCopy(k)
  143. for r.Cmp(intZero) != 0 {
  144. quot := Div(oldr, r)
  145. oldr, r = r, Sub(oldr, Mul(quot, r))
  146. olds, s = s, Sub(olds, Mul(quot, s))
  147. oldt, t = t, Sub(oldt, Mul(quot, t))
  148. }
  149. // gcd, x, y = old_r, old_s, old_t
  150. res = Mod(olds, p)
  151. }
  152. return
  153. }
  154. func (s *Curve) Points(dx *big.Int) (p1, p2 *Point, err error) {
  155. if err = s.IsValidG(); err != nil {
  156. return
  157. }
  158. return s.points(dx)
  159. }
  160. // Определение координат пары зеркальных точек по x
  161. func (s *Curve) points(dx *big.Int) (p1, p2 *Point, err error) {
  162. dxx := intCopy(dx)
  163. // Инициализируем результирующие точки пустыми
  164. p1, p2 = s.Point(nil, nil), s.Point(nil, nil)
  165. var dy *big.Int
  166. // Операции, обратной делению по модулю, не существует, поэтому
  167. // для определения координаты по y, необходимо, путем перебора с подстановкой y,
  168. // проверить равенство левой части уравнения, разделенного по модулю на p с
  169. // правой частью, так же разделенной по модулю на p
  170. for i := big.NewInt(0); i.Cmp(s.p) < 0; i.Add(i, big.NewInt(1)) {
  171. // i ** 2 % s.p == (dx ** 3 + s.a * dx + self.b) % self.p > 0
  172. l := Mod(Exp64(i, 2), s.p)
  173. r := Mod(
  174. Add(
  175. Exp64(dx, 3),
  176. Add(
  177. Mul(s.a, dx),
  178. s.b,
  179. ),
  180. ),
  181. s.p,
  182. )
  183. if l.Cmp(r) == 0 {
  184. dy = i
  185. break
  186. }
  187. }
  188. if dy == nil {
  189. err = fmt.Errorf("не удалось найти пару зеркальных точек на кривой после x [ %s ]", dxx)
  190. } else {
  191. p1.x, p1.y = dx, dy
  192. p2.x = intCopy(p1.x)
  193. p2.y = Mod(Neg(p1.y), s.p)
  194. }
  195. return
  196. }
  197. func (s *Curve) SearchClosePoints(x *big.Int, ctx context.Context) (p1, p2 *Point, err error) {
  198. if err = s.IsValidG(); err != nil {
  199. return
  200. }
  201. return s.searhClosePoints(x, ctx)
  202. }
  203. func (s *Curve) searhClosePoints(x *big.Int, ctx context.Context) (p1, p2 *Point, err error) {
  204. cx := intCopy(x)
  205. if x.Cmp(s.p) >= 0 {
  206. x = Sub(s.p, big.NewInt(1))
  207. } else if x.Cmp(intZero) < 0 {
  208. x = big.NewInt(0)
  209. }
  210. //kx := Sub64(x, 1)
  211. kx := intCopy(x)
  212. ch := make(chan struct{})
  213. go func() {
  214. defer close(ch)
  215. for {
  216. select {
  217. case <-ctx.Done():
  218. return
  219. default:
  220. //log.Println("xkx", x, kx)
  221. if x.Cmp(s.p) >= 0 && kx.Cmp(intZero) <= 0 {
  222. err = fmt.Errorf("не удалось найти точки, близкие к [ %s ]", cx)
  223. return
  224. } else {
  225. // Поиск вправо
  226. if x.Cmp(s.p) <= 0 {
  227. if p1, p2, err = s.points(x); err == nil {
  228. if p1.IsInCurve() == nil {
  229. return
  230. }
  231. }
  232. x = Add64(x, 1)
  233. }
  234. // Поиск влево
  235. if kx.Cmp(intZero) < 0 {
  236. if p1, p2, err = s.points(kx); err == nil {
  237. if p1.IsInCurve() == nil {
  238. return
  239. }
  240. }
  241. kx = Sub64(kx, 1)
  242. }
  243. }
  244. }
  245. }
  246. }()
  247. select {
  248. case <-ch:
  249. case <-ctx.Done():
  250. err = fmt.Errorf("Поиск точки, близкой к [ %v ] прерван - время вышло", x)
  251. }
  252. return
  253. }
  254. func (s *Curve) SetG(g *Point) (err error) {
  255. if s.g != nil {
  256. err = errors.New("базовая точка подгруппы g уже определена")
  257. return
  258. }
  259. if err = s.IsValidP(); err != nil {
  260. return
  261. }
  262. if err = g.IsInCurve(); err == nil && g.curve == s {
  263. s.g = g
  264. }
  265. return
  266. }
  267. func (s *Curve) SetGRandom(ctx context.Context) (err error) {
  268. if s.g != nil {
  269. err = errors.New("базовая точка подгруппы g уже определена")
  270. return
  271. }
  272. if err = s.IsValidP(); err != nil {
  273. return
  274. }
  275. x := Random(
  276. Div(s.p, big.NewInt(2)),
  277. Sub(s.p, big.NewInt(10)),
  278. )
  279. //log.Println(x)
  280. p1, p2, err := s.searhClosePoints(x, ctx)
  281. if err != nil {
  282. return
  283. }
  284. if err = p1.IsInCurve(); err == nil {
  285. s.g = p1
  286. } else if err = p2.IsInCurve(); err == nil {
  287. s.g = p2
  288. } else {
  289. err = errors.New("не удалось найти точку g, пренадлежащую кривой")
  290. }
  291. return
  292. }
  293. func (s *Curve) Map() json.Map {
  294. res := json.Map{
  295. "a": s.A(),
  296. "b": s.B(),
  297. "p": s.P(),
  298. "g": s.G(),
  299. }
  300. return res
  301. }
  302. /*
  303. // Поиск порядка подгруппы
  304. func (s *Curve) SetN() (err error) {
  305. if s.n != nil {
  306. return errors.New("порядок подгруппы уже определен")
  307. }
  308. if err = s.IsValidP(); err != nil {
  309. return
  310. }
  311. dx, dy := intCopy(s.g.x), Mod(Neg(s.g.y), s.p)
  312. tmpG := s.g.Copy()
  313. s.n = big.NewInt(1)
  314. for {
  315. s.n.Add(s.n, big.NewInt(1))
  316. if tmpG, err = tmpG.Add(s.g); err != nil {
  317. return
  318. }
  319. if tmpG.x.Cmp(dx) == 0 && tmpG.y.Cmp(dy) == 0 {
  320. s.n.Add(s.n, big.NewInt(1))
  321. return
  322. }
  323. }
  324. }
  325. func (s *Curve) KeyPub(priv *big.Int) (pub *Point, err error) {
  326. if err = s.IsValidN(); err != nil {
  327. return
  328. }
  329. pub, err = s.g.Mul(priv)
  330. return
  331. }
  332. func (s *Curve) RandomKeyPair() (priv *big.Int, pub *Point, err error) {
  333. if err = s.IsValidN(); err != nil {
  334. return
  335. }
  336. priv = Random(big.NewInt(1), Sub64(s.n, 1))
  337. pub, err = s.g.Mul(priv)
  338. return
  339. }
  340. // Вычисление общего секрета
  341. func (s *Curve) PointSecret(mPriv *big.Int, fPub *Point) (res *Point, err error) {
  342. if err = s.IsValidN(); err != nil {
  343. return
  344. }
  345. res, err = fPub.Mul(mPriv)
  346. return
  347. }
  348. type ELKeyPriv struct {
  349. d *big.Int
  350. }
  351. type ELKeyPub struct {
  352. e1 *Point
  353. e2 *Point
  354. }
  355. type ELKeyPair struct {
  356. curve *Curve
  357. priv *ELKeyPriv
  358. pub *ELKeyPub
  359. dTable map[byte]*Point
  360. }
  361. func (s *ELKeyPair) setupDataTable() error {
  362. if s.dTable != nil {
  363. return nil
  364. }
  365. s.dTable = make(map[byte]*Point)
  366. dx := big.NewInt(0)
  367. //var points []*Point
  368. //var p *Point
  369. for i := byte(0); i <= 254; i++ {
  370. p, _, err := s.curve.searhClosePoints(dx)
  371. if err != nil {
  372. return err
  373. }
  374. // check already exists - todo
  375. dx = Add64(p.x, 1)
  376. s.dTable[i] = p
  377. log.Println(i, p)
  378. }
  379. return nil
  380. }
  381. type ELMessage struct {
  382. c1 *Point
  383. cd []*Point
  384. }
  385. // c1 = r x e1
  386. // c2 = P + r x e2
  387. func (s *ELKeyPair) EncodeMessage(data []byte) (mes *ELMessage, err error) {
  388. r := Random(big.NewInt(1), Sub64(s.curve.p, 1))
  389. c1, err := s.pub.e1.Mul(r)
  390. if err != nil {
  391. return nil, err
  392. }
  393. mes = &ELMessage{
  394. c1: c1,
  395. cd: make([]*Point, len(data)),
  396. }
  397. for i, d := range data {
  398. p := s.dTable[d]
  399. c2, err := s.pub.e2.Mul(r)
  400. if err != nil {
  401. return nil, err
  402. }
  403. cd, err := p.Add(c2)
  404. if err != nil {
  405. return nil, err
  406. }
  407. mes.cd[i] = cd
  408. }
  409. return mes, nil
  410. }
  411. // p = c2 – (d x c1)
  412. func (s *ELKeyPair) DecodeMessage(mes *ELMessage) ([]byte, error) {
  413. res := make([]byte, len(mes.cd))
  414. part, err := mes.c1.Mul(s.priv.d)
  415. if err != nil {
  416. return nil, err
  417. }
  418. part, _ = part.Neg()
  419. for _, c2 := range mes.cd {
  420. p, err := c2.Add(part)
  421. if err != nil {
  422. return nil, err
  423. }
  424. log.Println(p)
  425. }
  426. return res, nil
  427. }
  428. func (s *Curve) ELKeyPair() (*ELKeyPair, error) {
  429. e1, _, err := s.searhClosePoints(Random(big.NewInt(1), Sub64(s.p, 1)))
  430. if err != nil {
  431. return nil, err
  432. }
  433. d := Random(big.NewInt(1), Sub64(s.n, 1))
  434. e2, err := e1.Mul(d)
  435. if err != nil {
  436. return nil, err
  437. }
  438. res := &ELKeyPair{
  439. curve: s,
  440. priv: &ELKeyPriv{
  441. d: d,
  442. },
  443. pub: &ELKeyPub{
  444. e1: e1,
  445. e2: e2,
  446. },
  447. }
  448. return res, res.setupDataTable()
  449. }
  450. */
  451. /*
  452. func (s *Curve) HEncode(b byte, pub *Point) (cm1, cm2 *Point, err error) {
  453. var p1 *Point
  454. if p1, _, err = s.points(big.NewInt(int64(b))); err != nil {
  455. return
  456. }
  457. c1 = pub.Add()
  458. }
  459. */
  460. /*
  461. // 𝐶𝑚 = (𝑘 × 𝐺, 𝑃𝑚 + 𝑘 × 𝑃𝐵)
  462. func (s *Curve) HellmanEncode(b byte, pub *Point) (cm1, cm2 *Point, err error) {
  463. k := Random(big.NewInt(1), Sub64(s.n, 1))
  464. if cm1, err = s.g.Mul(k); err != nil {
  465. return
  466. }
  467. cm2, err = pub.Mul(Add64(k, int64(b)))
  468. return
  469. }
  470. */
  471. /*
  472. func (s *Curve) HellmanDecode(cm1, cm2 *Point, priv *big.Int) {
  473. }
  474. */