package csidh import ( "fmt" "math/big" mrand "math/rand" ) var ( // Number of interations numIter = 10 // Modulus modulus, _ = new(big.Int).SetString(fp2S(p), 16) // Zero in fp zeroFp512 = fp{} // One in fp oneFp512 = fp{1, 0, 0, 0, 0, 0, 0, 0} // file with KAT vectors katFile = "testdata/csidh_testvectors.dat" ) // Converts dst to Montgomery if "toMont==true" or from Montgomery domain otherwise. func toMont(dst *big.Int, toMont bool) { var bigP, bigR big.Int intSetU64(&bigP, p[:]) bigR.SetUint64(1) bigR.Lsh(&bigR, 512) if !toMont { bigR.ModInverse(&bigR, &bigP) } dst.Mul(dst, &bigR) dst.Mod(dst, &bigP) } func fp2S(v fp) string { var str string for i := 0; i < 8; i++ { str = fmt.Sprintf("%016x", v[i]) + str } return str } // zeroize fp. func zero(v *fp) { for i := range *v { v[i] = 0 } } // returns random value in a range (0,p). func randomFp() fp { var u fp for i := 0; i < 8; i++ { u[i] = mrand.Uint64() } return u } // return x==y for fp. func eqFp(l, r *fp) bool { for idx := range l { if l[idx] != r[idx] { return false } } return true } // return x==y for point. func ceqpoint(l, r *point) bool { return eqFp(&l.x, &r.x) && eqFp(&l.z, &r.z) } // Converts src to big.Int. Function assumes that src is a slice of uint64 // values encoded in little-endian byte order. func intSetU64(dst *big.Int, src []uint64) { var tmp big.Int dst.SetUint64(0) for i := range src { tmp.SetUint64(src[i]) tmp.Lsh(&tmp, uint(i*64)) dst.Add(dst, &tmp) } } // Converts src to an array of uint64 values encoded in little-endian // byte order. func intGetU64(src *big.Int) []uint64 { var tmp, mod big.Int dst := make([]uint64, (src.BitLen()/64)+1) u64 := uint64(0) u64-- mod.SetUint64(u64) for i := 0; i < (src.BitLen()/64)+1; i++ { tmp.Set(src) tmp.Rsh(&tmp, uint(i)*64) tmp.And(&tmp, &mod) dst[i] = tmp.Uint64() } return dst } // Returns projective coordinate X of normalized EC 'point' (point.x / point.z). func toNormX(point *point) big.Int { var bigP, bigDnt, bigDor big.Int intSetU64(&bigP, p[:]) intSetU64(&bigDnt, point.x[:]) intSetU64(&bigDor, point.z[:]) bigDor.ModInverse(&bigDor, &bigP) bigDnt.Mul(&bigDnt, &bigDor) bigDnt.Mod(&bigDnt, &bigP) return bigDnt } // Converts string to fp element in Montgomery domain of cSIDH-512. func toFp(num string) fp { var tmp big.Int var ok bool var ret fp _, ok = tmp.SetString(num, 0) if !ok { panic("Can't parse a number") } toMont(&tmp, true) copy(ret[:], intGetU64(&tmp)) return ret }