wnaf.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // Package math provides some utility functions for big integers.
  2. package math
  3. import "math/big"
  4. // SignedDigit obtains the signed-digit recoding of n and returns a list L of
  5. // digits such that n = sum( L[i]*2^(i*(w-1)) ), and each L[i] is an odd number
  6. // in the set {±1, ±3, ..., ±2^(w-1)-1}. The third parameter ensures that the
  7. // output has ceil(l/(w-1)) digits.
  8. //
  9. // Restrictions:
  10. // - n is odd and n > 0.
  11. // - 1 < w < 32.
  12. // - l >= bit length of n.
  13. //
  14. // References:
  15. // - Alg.6 in "Exponent Recoding and Regular Exponentiation Algorithms"
  16. // by Joye-Tunstall. http://doi.org/10.1007/978-3-642-02384-2_21
  17. // - Alg.6 in "Selecting Elliptic Curves for Cryptography: An Efficiency and
  18. // Security Analysis" by Bos et al. http://doi.org/10.1007/s13389-015-0097-y
  19. func SignedDigit(n *big.Int, w, l uint) []int32 {
  20. if n.Sign() <= 0 || n.Bit(0) == 0 {
  21. panic("n must be non-zero, odd, and positive")
  22. }
  23. if w <= 1 || w >= 32 {
  24. panic("Verify that 1 < w < 32")
  25. }
  26. if uint(n.BitLen()) > l {
  27. panic("n is too big to fit in l digits")
  28. }
  29. lenN := (l + (w - 1) - 1) / (w - 1) // ceil(l/(w-1))
  30. L := make([]int32, lenN+1)
  31. var k, v big.Int
  32. k.Set(n)
  33. var i uint
  34. for i = 0; i < lenN; i++ {
  35. words := k.Bits()
  36. value := int32(words[0] & ((1 << w) - 1))
  37. value -= int32(1) << (w - 1)
  38. L[i] = value
  39. v.SetInt64(int64(value))
  40. k.Sub(&k, &v)
  41. k.Rsh(&k, w-1)
  42. }
  43. L[i] = int32(k.Int64())
  44. return L
  45. }
  46. // OmegaNAF obtains the window-w Non-Adjacent Form of a positive number n and
  47. // 1 < w < 32. The returned slice L holds n = sum( L[i]*2^i ).
  48. //
  49. // Reference:
  50. // - Alg.9 "Efficient arithmetic on Koblitz curves" by Solinas.
  51. // http://doi.org/10.1023/A:1008306223194
  52. func OmegaNAF(n *big.Int, w uint) (L []int32) {
  53. if n.Sign() < 0 {
  54. panic("n must be positive")
  55. }
  56. if w <= 1 || w >= 32 {
  57. panic("Verify that 1 < w < 32")
  58. }
  59. L = make([]int32, n.BitLen()+1)
  60. var k, v big.Int
  61. k.Set(n)
  62. i := 0
  63. for ; k.Sign() > 0; i++ {
  64. value := int32(0)
  65. if k.Bit(0) == 1 {
  66. words := k.Bits()
  67. value = int32(words[0] & ((1 << w) - 1))
  68. if value >= (int32(1) << (w - 1)) {
  69. value -= int32(1) << w
  70. }
  71. v.SetInt64(int64(value))
  72. k.Sub(&k, &v)
  73. }
  74. L[i] = value
  75. k.Rsh(&k, 1)
  76. }
  77. return L[:i]
  78. }