| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- // Package math provides some utility functions for big integers.
- package math
- import "math/big"
- // SignedDigit obtains the signed-digit recoding of n and returns a list L of
- // digits such that n = sum( L[i]*2^(i*(w-1)) ), and each L[i] is an odd number
- // in the set {±1, ±3, ..., ±2^(w-1)-1}. The third parameter ensures that the
- // output has ceil(l/(w-1)) digits.
- //
- // Restrictions:
- // - n is odd and n > 0.
- // - 1 < w < 32.
- // - l >= bit length of n.
- //
- // References:
- // - Alg.6 in "Exponent Recoding and Regular Exponentiation Algorithms"
- // by Joye-Tunstall. http://doi.org/10.1007/978-3-642-02384-2_21
- // - Alg.6 in "Selecting Elliptic Curves for Cryptography: An Efficiency and
- // Security Analysis" by Bos et al. http://doi.org/10.1007/s13389-015-0097-y
- func SignedDigit(n *big.Int, w, l uint) []int32 {
- if n.Sign() <= 0 || n.Bit(0) == 0 {
- panic("n must be non-zero, odd, and positive")
- }
- if w <= 1 || w >= 32 {
- panic("Verify that 1 < w < 32")
- }
- if uint(n.BitLen()) > l {
- panic("n is too big to fit in l digits")
- }
- lenN := (l + (w - 1) - 1) / (w - 1) // ceil(l/(w-1))
- L := make([]int32, lenN+1)
- var k, v big.Int
- k.Set(n)
- var i uint
- for i = 0; i < lenN; i++ {
- words := k.Bits()
- value := int32(words[0] & ((1 << w) - 1))
- value -= int32(1) << (w - 1)
- L[i] = value
- v.SetInt64(int64(value))
- k.Sub(&k, &v)
- k.Rsh(&k, w-1)
- }
- L[i] = int32(k.Int64())
- return L
- }
- // OmegaNAF obtains the window-w Non-Adjacent Form of a positive number n and
- // 1 < w < 32. The returned slice L holds n = sum( L[i]*2^i ).
- //
- // Reference:
- // - Alg.9 "Efficient arithmetic on Koblitz curves" by Solinas.
- // http://doi.org/10.1023/A:1008306223194
- func OmegaNAF(n *big.Int, w uint) (L []int32) {
- if n.Sign() < 0 {
- panic("n must be positive")
- }
- if w <= 1 || w >= 32 {
- panic("Verify that 1 < w < 32")
- }
- L = make([]int32, n.BitLen()+1)
- var k, v big.Int
- k.Set(n)
- i := 0
- for ; k.Sign() > 0; i++ {
- value := int32(0)
- if k.Bit(0) == 1 {
- words := k.Bits()
- value = int32(words[0] & ((1 << w) - 1))
- if value >= (int32(1) << (w - 1)) {
- value -= int32(1) << w
- }
- v.SetInt64(int64(value))
- k.Sub(&k, &v)
- }
- L[i] = value
- k.Rsh(&k, 1)
- }
- return L[:i]
- }
|