github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/crypto/wnaf/rl.go (about)

     1  package wnaf
     2  
     3  import (
     4  	"math/big"
     5  )
     6  
     7  // FYI https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#w-ary_non-adjacent_form_(wNAF)_method
     8  //	   https://cs.uwaterloo.ca/~shallit/Papers/bbr.pdf
     9  
    10  var (
    11  	zero = big.NewInt(0)
    12  	one  = big.NewInt(1)
    13  	two  = big.NewInt(2)
    14  )
    15  
    16  // ToWnafRL converts a big int to wnaf form from right to left.
    17  // the returned wnaf "bits" are in little endian.
    18  // each "bit" is in range [-2^(w-1), 2^(w-1))
    19  func ToWnafRL(d *big.Int, w uint8) (wnaf []int64) {
    20  	if d.Cmp(zero) < 0 {
    21  		panic("negative d not supported")
    22  	}
    23  	if w > 64 {
    24  		panic("w > 64 not supported")
    25  	}
    26  
    27  	mod := big.NewInt(0).Exp(two, big.NewInt(int64(w)), nil)
    28  	halfMod := big.NewInt(0).Div(mod, two)
    29  
    30  	for {
    31  		if d.Cmp(zero) <= 0 {
    32  			break
    33  		}
    34  		if big.NewInt(0).Mod(d, two).Uint64() == 1 {
    35  			// mods
    36  			di := big.NewInt(0).Mod(d, mod)
    37  			if di.Cmp(halfMod) >= 0 {
    38  				di.Sub(di, mod)
    39  			}
    40  
    41  			d.Sub(d, di)
    42  			wnaf = append(wnaf, di.Int64())
    43  		} else {
    44  			wnaf = append(wnaf, 0)
    45  		}
    46  
    47  		d.Div(d, two)
    48  	}
    49  
    50  	if len(wnaf) == 0 {
    51  		wnaf = append(wnaf, 0)
    52  	}
    53  
    54  	return
    55  }