github.com/cloudflare/circl@v1.5.0/dh/csidh/utils_test.go (about)

     1  package csidh
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"math/big"
     8  )
     9  
    10  var (
    11  	// Number of iterations
    12  	numIter = 10
    13  	// Modulus
    14  	modulus, _ = new(big.Int).SetString(fp2S(p), 16)
    15  	// Zero in fp
    16  	zeroFp512 = fp{}
    17  	// One in fp
    18  	oneFp512 = fp{1, 0, 0, 0, 0, 0, 0, 0}
    19  	// file with KAT vectors
    20  	katFile = "testdata/csidh_testvectors.json"
    21  )
    22  
    23  // Converts dst to Montgomery if "toMont==true" or from Montgomery domain otherwise.
    24  func toMont(dst *big.Int, toMont bool) {
    25  	var bigP, bigR big.Int
    26  
    27  	intSetU64(&bigP, p[:])
    28  	bigR.SetUint64(1)
    29  	bigR.Lsh(&bigR, 512)
    30  
    31  	if !toMont {
    32  		bigR.ModInverse(&bigR, &bigP)
    33  	}
    34  	dst.Mul(dst, &bigR)
    35  	dst.Mod(dst, &bigP)
    36  }
    37  
    38  func fp2S(v fp) string {
    39  	var str string
    40  	for i := 0; i < 8; i++ {
    41  		str = fmt.Sprintf("%016x", v[i]) + str
    42  	}
    43  	return str
    44  }
    45  
    46  // zeroize fp.
    47  func zero(v *fp) {
    48  	for i := range *v {
    49  		v[i] = 0
    50  	}
    51  }
    52  
    53  // returns random value in a range (0,p).
    54  func randomFp() (u fp) {
    55  	_ = binary.Read(rand.Reader, binary.LittleEndian, &u)
    56  	return
    57  }
    58  
    59  // return x==y for fp.
    60  func eqFp(l, r *fp) bool {
    61  	for idx := range l {
    62  		if l[idx] != r[idx] {
    63  			return false
    64  		}
    65  	}
    66  	return true
    67  }
    68  
    69  // return x==y for point.
    70  func ceqpoint(l, r *point) bool {
    71  	return eqFp(&l.x, &r.x) && eqFp(&l.z, &r.z)
    72  }
    73  
    74  // Converts src to big.Int. Function assumes that src is a slice of uint64
    75  // values encoded in little-endian byte order.
    76  func intSetU64(dst *big.Int, src []uint64) {
    77  	var tmp big.Int
    78  
    79  	dst.SetUint64(0)
    80  	for i := range src {
    81  		tmp.SetUint64(src[i])
    82  		tmp.Lsh(&tmp, uint(i*64))
    83  		dst.Add(dst, &tmp)
    84  	}
    85  }
    86  
    87  // Converts src to an array of uint64 values encoded in little-endian
    88  // byte order.
    89  func intGetU64(src *big.Int) []uint64 {
    90  	var tmp, mod big.Int
    91  	dst := make([]uint64, (src.BitLen()/64)+1)
    92  
    93  	u64 := uint64(0)
    94  	u64--
    95  	mod.SetUint64(u64)
    96  	for i := 0; i < (src.BitLen()/64)+1; i++ {
    97  		tmp.Set(src)
    98  		tmp.Rsh(&tmp, uint(i)*64)
    99  		tmp.And(&tmp, &mod)
   100  		dst[i] = tmp.Uint64()
   101  	}
   102  	return dst
   103  }
   104  
   105  // Returns projective coordinate X of normalized EC 'point' (point.x / point.z).
   106  func toNormX(point *point) big.Int {
   107  	var bigP, bigDnt, bigDor big.Int
   108  
   109  	intSetU64(&bigP, p[:])
   110  	intSetU64(&bigDnt, point.x[:])
   111  	intSetU64(&bigDor, point.z[:])
   112  
   113  	bigDor.ModInverse(&bigDor, &bigP)
   114  	bigDnt.Mul(&bigDnt, &bigDor)
   115  	bigDnt.Mod(&bigDnt, &bigP)
   116  	return bigDnt
   117  }
   118  
   119  // Converts string to fp element in Montgomery domain of cSIDH-512.
   120  func toFp(num string) fp {
   121  	var tmp big.Int
   122  	var ok bool
   123  	var ret fp
   124  
   125  	_, ok = tmp.SetString(num, 0)
   126  	if !ok {
   127  		panic("Can't parse a number")
   128  	}
   129  	toMont(&tmp, true)
   130  	copy(ret[:], intGetU64(&tmp))
   131  	return ret
   132  }