// // Copyright (c) 2019 harmony-one // // SPDX-License-Identifier: MIT // package iqc import ( "bytes" "crypto/sha256" "encoding/binary" "math/big" ) type Pair struct { p int64 q int64 } var m = 8 * 3 * 5 * 7 * 11 * 13 func EntropyFromSeed(seed []byte, byte_count uint32) []byte { buffer := bytes.Buffer{} bufferSize := uint32(0) extra := uint16(0) bytes := make([]byte, len(seed)+2) copy(bytes, seed) for bufferSize <= byte_count { binary.BigEndian.PutUint16(bytes[len(seed):], extra) more_entropy := sha256.Sum256(bytes) buffer.Write(more_entropy[:]) bufferSize += sha256.Size extra += 1 } return buffer.Bytes()[:byte_count] } //Return a discriminant of the given length using the given seed //It is a random prime p between 13 - 2^2K //return -p, where p % 8 == 7 func CreateDiscriminant(seed []byte, length uint32) *big.Int { extra := uint8(length) & 7 byte_count := ((length + 7) >> 3) + 2 entropy := EntropyFromSeed(seed, byte_count) n := new(big.Int) n.SetBytes(entropy[:len(entropy)-2]) n = new(big.Int).Rsh(n, uint(((8 - extra) & 7))) n = new(big.Int).SetBit(n, int(length-1), 1) n = new(big.Int).Sub(n, new(big.Int).Mod(n, big.NewInt(int64(m)))) n = new(big.Int).Add(n, big.NewInt(int64(residues[int(binary.BigEndian.Uint16(entropy[len(entropy)-2:]))%len(residues)]))) negN := new(big.Int).Neg(n) // Find the smallest prime >= n of the form n + m*x for { sieve := make([]bool, (1 << 16)) for _, v := range sieve_info { // q = m^-1 (mod p) // i = -n / m, so that m*i is -n (mod p) //i := ((-n % v.p) * v.q) % v.p i := (new(big.Int).Mod(negN, big.NewInt(v.p)).Int64() * v.q) % v.p for i < int64(len(sieve)) { sieve[i] = true i += v.p } } for i, v := range sieve { t := new(big.Int).Add(n, big.NewInt(int64(m)*int64(i))) if !v && t.ProbablyPrime(1) { return new(big.Int).Neg(t) } } //n += m * (1 << 16) bigM := big.NewInt(int64(m)) n = new(big.Int).Add(n, bigM.Mul(bigM, big.NewInt(int64(1<<16)))) } }