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 }