forked from toolshed/abra
		
	
		
			
				
	
	
		
			85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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]
 | 
						|
}
 |