tools.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package tools
  2. import (
  3. "context"
  4. "errors"
  5. "math/big"
  6. "math/rand"
  7. "time"
  8. )
  9. var (
  10. rnd = rand.New(rand.NewSource(time.Now().UnixNano())) // Генератор случайных чисел
  11. intZero = big.NewInt(0)
  12. intMax, _ = new(big.Int).SetString("9223372036854775807", 10)
  13. )
  14. func intCopy(val *big.Int) (res *big.Int) {
  15. if val != nil {
  16. res = new(big.Int).Set(val)
  17. }
  18. return
  19. }
  20. // Возвращает число или 0 при пустом указателе
  21. func mustBigInt(val *big.Int) (res *big.Int) {
  22. res = val
  23. if res == nil {
  24. res = big.NewInt(0)
  25. }
  26. return res
  27. }
  28. func IsPrime(val *big.Int) bool {
  29. return val.ProbablyPrime(100)
  30. }
  31. func SearchP(min *big.Int, ctx context.Context) (p *big.Int, g *big.Int, err error) {
  32. ch := make(chan struct{})
  33. go func() {
  34. defer func() {
  35. close(ch)
  36. }()
  37. p = intCopy(min)
  38. var check bool
  39. for {
  40. select {
  41. case <-ctx.Done():
  42. err = errors.New("Поиск поля и первообразного корня - время вышло")
  43. return
  44. default:
  45. if g, check = CheckP(p); check {
  46. ch <- struct{}{}
  47. return
  48. }
  49. p = Add64(p, 1)
  50. }
  51. }
  52. }()
  53. <-ch
  54. return
  55. }
  56. func CheckP(val *big.Int) (res *big.Int, check bool) {
  57. if IsPrime(val) {
  58. //log.Println("PRIME", val, Div64(Sub64(val, 1), 2))
  59. res = Div64(Sub64(val, 1), 2)
  60. check = IsPrime(res)
  61. }
  62. return
  63. }
  64. func SearchPrime(val *big.Int) *big.Int {
  65. rVal := new(big.Int).Set(val)
  66. //log.Println(rVal)
  67. for {
  68. if rVal.ProbablyPrime(100) {
  69. break
  70. }
  71. rVal.Add(rVal, big.NewInt(1))
  72. //log.Println(rVal)
  73. }
  74. return rVal
  75. }
  76. func Random(min, max *big.Int) *big.Int {
  77. if min == nil {
  78. min = intZero
  79. }
  80. if max == nil {
  81. max = intMax
  82. }
  83. res := new(big.Int).Rand(rnd, max)
  84. for res.Cmp(min) == -1 {
  85. res = new(big.Int).Rand(rnd, max)
  86. }
  87. return res
  88. }
  89. // Проверка кривой на сингулярность (4a³ + 27b² = 0)
  90. func IsCurveSingular(a, b *big.Int) bool {
  91. l := Mul64(Exp64(a, 3), 4)
  92. r := Mul64(Exp64(b, 2), 27)
  93. return l.Add(l, r).Cmp(intZero) == 0
  94. }
  95. func CurveRandomParams(max *big.Int) (a, b, p *big.Int) {
  96. for {
  97. a, b = Random(intZero, max), Random(intZero, max)
  98. if !IsCurveSingular(a, b) {
  99. break
  100. }
  101. }
  102. p = SearchPrime(Random(intZero, max))
  103. return
  104. }