/** * Reads a basis from an input stream and constructs a new basis. * @param is an input stream * @param params NtruSign parameters * @param include_h whether to read the polynomial <code>h</code> (<code>true</code>) or only <code>f</code> and <code>f'</code> (<code>false</code>) * @throws IOException */ public Basis(MemoryStream ins, int N, int q, bool sparse, TernaryPolynomialType polyType, BasisType basisType, double keyNormBoundSq, bool include_h) { this.N = N; this.q = q; this.polyType = polyType; this.basisType = basisType; this.keyNormBoundSq = keyNormBoundSq; if (polyType == TernaryPolynomialType.PRODUCT) f = ProductFormPolynomial.FromBinary(ins, N); else { IntegerPolynomial fInt = IntegerPolynomial.FromBinary3Tight(ins, N); if (sparse) f = new SparseTernaryPolynomial(fInt); else f = new DenseTernaryPolynomial(fInt); } if (basisType == BasisType.STANDARD) { IntegerPolynomial fPrimeInt = IntegerPolynomial.FromBinary(ins, N, q); for (int i = 0; i < fPrimeInt.Coeffs.Length; i++) fPrimeInt.Coeffs[i] -= q / 2; fPrime = fPrimeInt; } else if (polyType == TernaryPolynomialType.PRODUCT) fPrime = ProductFormPolynomial.FromBinary(ins, N); else fPrime = IntegerPolynomial.FromBinary3Tight(ins, N); if (include_h) h = IntegerPolynomial.FromBinary(ins, N, q); }
/** * Constructs a new basis from polynomials <code>f, f', h</code>. * @param f * @param fPrime * @param h * @param params NtruSign parameters */ public Basis(IPolynomial f, IPolynomial fPrime, IntegerPolynomial h, int q, TernaryPolynomialType polyType, BasisType basisType, double keyNormBoundSq) { this.f = f; this.fPrime = fPrime; this.h = h; this.N = h.Coeffs.Length; this.q = q; this.polyType = polyType; this.basisType = basisType; this.keyNormBoundSq = keyNormBoundSq; }
public bool EqualTo(IPolynomial t) { return(Equals(t)); }
/** * Constructs a new private key from a polynomial * * @param h the public polynomial for the key. * @param t the polynomial which determines the key: if <code>fastFp=true</code>, <code>f=1+3t</code>; otherwise, <code>f=t</code> * @param fp the inverse of <code>f</code> * @param params the NtruEncrypt parameters to use */ public NTRUEncryptionPrivateKeyParameters(IntegerPolynomial h, IPolynomial t, IntegerPolynomial fp, NTRUEncryptionParameters parameters) : base(true, parameters) { this.h = h; this.t = t; this.fp = fp; }
/// <summary> /// Reads a Private Key from a Stream /// </summary> /// /// <param name="KeyStream">An input stream containing an encoded key</param> /// /// <exception cref="CryptoAsymmetricException">Thrown if the key could not be loaded</exception> public NTRUPrivateKey(MemoryStream KeyStream) { BinaryReader dataStream = new BinaryReader(KeyStream); try { // ins.Position = 0; wrong here, ins pos is wrong _N = IntUtils.ReadShort(KeyStream); _Q = IntUtils.ReadShort(KeyStream); byte flags = dataStream.ReadByte(); _sparse = (flags & 1) != 0; _fastFp = (flags & 2) != 0; _polyType = (flags & 4) == 0 ? TernaryPolynomialType.SIMPLE : TernaryPolynomialType.PRODUCT; if (PolyType == TernaryPolynomialType.PRODUCT) { _T = ProductFormPolynomial.FromBinary(KeyStream, N); } else { IntegerPolynomial fInt = IntegerPolynomial.FromBinary3Tight(KeyStream, N); if (_sparse) _T = new SparseTernaryPolynomial(fInt); else _T = new DenseTernaryPolynomial(fInt); } } catch (Exception ex) { throw new CryptoAsymmetricException("NTRUPrivateKey:Ctor", "The Private key could not be loaded!", ex); } Initialize(); }
/// <summary> /// Decrypts an integer polynomial /// </summary> /// /// <param name="E">Encrypted polynomial</param> /// <param name="PrivT">A polynomial such that if <c>fastFp=true</c>, <c>f=1+3*priv_t</c>; otherwise, <c>f=priv_t</c></param> /// <param name="PrivFp">Fp</param> /// /// <returns>Derypted polynomial</returns> private IntegerPolynomial Decrypt(IntegerPolynomial E, IPolynomial PrivT, IntegerPolynomial PrivFp) { int q = _encParams.Q; IntegerPolynomial a; if (_encParams.FastFp) { a = PrivT.Multiply(E, q); a.Multiply(3); a.Add(E); } else { a = PrivT.Multiply(E, q); } a.Center0(q); a.Mod3(); IntegerPolynomial c = _encParams.FastFp ? a : new DenseTernaryPolynomial(a).Multiply(PrivFp, 3); c.Center0(3); return c; }
public FGBasis(IPolynomial f, IPolynomial fPrime, IntegerPolynomial h, IntegerPolynomial F, IntegerPolynomial G, int q, TernaryPolynomialType polyType, BasisType basisType, double keyNormBoundSq) : base(f, fPrime, h, q, polyType, basisType, keyNormBoundSq) { ; this.F = F; this.G = G; this.q = q; this.keyNormBoundSq = keyNormBoundSq; }
private byte[] getEncoded(IPolynomial p) { if (p.GetType().IsAssignableFrom(typeof(ProductFormPolynomial))) return ((ProductFormPolynomial)p).toBinary(); else return p.ToIntegerPolynomial().ToBinary3Tight(); }
public static Tuple <BigInteger, BigInteger> AlgebraicSquareRoot(IPolynomial f, BigInteger m, int degree, IPolynomial dd, BigInteger p) { IPolynomial startPolynomial = Polynomial.Modulus(dd, p); IPolynomial startInversePolynomial = Polynomial.ModularInverse(startPolynomial, p); IPolynomial resultPoly1 = FiniteFieldArithmetic.SquareRoot(startPolynomial, f, p, degree, m); IPolynomial resultPoly2 = Polynomial.ModularInverse(resultPoly1, p); BigInteger result1 = resultPoly1.Evaluate(m).Mod(p); BigInteger result2 = resultPoly2.Evaluate(m).Mod(p); IPolynomial resultSquared1 = Polynomial.ModMod(Polynomial.Square(resultPoly1), f, p); IPolynomial resultSquared2 = Polynomial.ModMod(Polynomial.Square(resultPoly2), f, p); bool bothResultsAgree = (resultSquared1.CompareTo(resultSquared2) == 0); if (bothResultsAgree) { bool resultSquaredEqualsInput1 = (startPolynomial.CompareTo(resultSquared1) == 0); bool resultSquaredEqualsInput2 = (startInversePolynomial.CompareTo(resultSquared1) == 0); if (resultSquaredEqualsInput1) { return(new Tuple <BigInteger, BigInteger>(result1, result2)); } else if (resultSquaredEqualsInput2) { return(new Tuple <BigInteger, BigInteger>(result2, result1)); } } return(new Tuple <BigInteger, BigInteger>(BigInteger.Zero, BigInteger.Zero)); }
public Tuple <BigInteger, BigInteger> CalculateAlgebraicSide(CancellationToken cancelToken) { bool solutionFound = false; RootsOfS.AddRange(RelationsSet.Select(rel => new Tuple <BigInteger, BigInteger>(rel.A, rel.B))); PolynomialRing = new List <IPolynomial>(); foreach (Relation rel in RelationsSet) { // poly(x) = A + (B * x) IPolynomial newPoly = new Polynomial( new Term[] { new Term(rel.B, 1), new Term(rel.A, 0) } ); PolynomialRing.Add(newPoly); } if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1)); } BigInteger m = polyBase; IPolynomial f = (Polynomial)monicPoly.Clone(); int degree = f.Degree; IPolynomial fd = Polynomial.GetDerivativePolynomial(f); IPolynomial d3 = Polynomial.Product(PolynomialRing); IPolynomial derivativeSquared = Polynomial.Square(fd); IPolynomial d2 = Polynomial.Multiply(d3, derivativeSquared); IPolynomial dd = Polynomial.Mod(d2, f); // Set the result to S S = dd; SRingSquare = dd; TotalS = d2; algebraicNormCollection = RelationsSet.Select(rel => rel.AlgebraicNorm); AlgebraicProduct = d2.Evaluate(m); AlgebraicSquare = dd.Evaluate(m); AlgebraicProductModF = dd.Evaluate(m).Mod(N); AlgebraicSquareResidue = AlgebraicSquare.Mod(N); IsAlgebraicIrreducible = IsPrimitive(algebraicNormCollection); // Irreducible check IsAlgebraicSquare = AlgebraicSquareResidue.IsSquare(); List <BigInteger> primes = new List <BigInteger>(); List <Tuple <BigInteger, BigInteger> > resultTuples = new List <Tuple <BigInteger, BigInteger> >(); BigInteger primeProduct = 1; BigInteger lastP = N / N.ToString().Length; //((N * 3) + 1).NthRoot(3); //gnfs.QFB.Select(fp => fp.P).Max(); while (!solutionFound) { if (primes.Count > 0 && resultTuples.Count > 0) { primes.Remove(primes.First()); resultTuples.Remove(resultTuples.First()); } do { if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1)); } lastP = PrimeFactory.GetNextPrime(lastP + 1); Tuple <BigInteger, BigInteger> lastResult = AlgebraicSquareRoot(f, m, degree, dd, lastP); if (lastResult.Item1 != 0) { primes.Add(lastP); resultTuples.Add(lastResult); } }while (primes.Count < degree); if (primes.Count > degree) { primes.Remove(primes.First()); resultTuples.Remove(resultTuples.First()); } primeProduct = (resultTuples.Select(tup => BigInteger.Min(tup.Item1, tup.Item2)).Product()); if (primeProduct < N) { continue; } AlgebraicPrimes = primes; if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1));; } IEnumerable <IEnumerable <BigInteger> > permutations = Combinatorics.CartesianProduct(resultTuples.Select(tup => new List <BigInteger>() { tup.Item1, tup.Item2 })); BigInteger rationalSquareRoot = RationalSquareRootResidue; BigInteger algebraicSquareRoot = 1; foreach (List <BigInteger> X in permutations) { if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1));; } algebraicSquareRoot = FiniteFieldArithmetic.ChineseRemainder(N, X, primes); BigInteger min = BigInteger.Min(rationalSquareRoot, algebraicSquareRoot); BigInteger max = BigInteger.Max(rationalSquareRoot, algebraicSquareRoot); BigInteger A = max + min; BigInteger B = max - min; BigInteger U = GCD.FindGCD(N, A); BigInteger V = GCD.FindGCD(N, B); if (U > 1 && U != N) { BigInteger rem = 1; BigInteger other = BigInteger.DivRem(N, U, out rem); if (rem == 0) { solutionFound = true; V = other; AlgebraicResults = X; AlgebraicSquareRootResidue = algebraicSquareRoot; return(new Tuple <BigInteger, BigInteger>(U, V)); } } if (V > 1 && V != N) { BigInteger rem = 1; BigInteger other = BigInteger.DivRem(N, V, out rem); if (rem == 0) { solutionFound = true; U = other; AlgebraicResults = X; AlgebraicSquareRootResidue = algebraicSquareRoot; return(new Tuple <BigInteger, BigInteger>(U, V)); } } } if (!solutionFound) { gnfs.LogFunction($"No solution found amongst the algebraic square roots {{ {string.Join(", ", resultTuples.Select(tup => $"({ tup.Item1}, { tup.Item2})"))} }} mod primes {{ {string.Join(", ", primes.Select(p => p.ToString()))} }}"); } } return(new Tuple <BigInteger, BigInteger>(1, 1)); }
public static GNFS FindSquares(CancellationToken cancelToken, GNFS gnfs) { if (cancelToken.IsCancellationRequested) { return(gnfs); } Logging.LogMessage(); Logging.LogMessage($"# of solution sets: {gnfs.CurrentRelationsProgress.FreeRelations.Count}"); Logging.LogMessage(); BigInteger polyBase = gnfs.PolynomialBase; List <List <Relation> > freeRelations = gnfs.CurrentRelationsProgress.FreeRelations; // Below randomly selects a solution set to try and find a square root of the polynomial in. // Each time this step is stopped and restarted, it will try a different solution set. // Previous used sets are tracked with the List<int> triedFreeRelationIndices if (triedFreeRelationIndices.Count == freeRelations.Count) // If we have exhausted our solution sets, alert the user. Number wont factor for some reason. { Logging.LogMessage("ERROR: ALL RELATION SETS HAVE BEEN TRIED...?"); Logging.LogMessage($"If the number of solution sets ({freeRelations.Count}) is low, you may need to sieve some more and then re-run the matrix solving step."); Logging.LogMessage("If there are many solution sets, and you have tried them all without finding non-trivial factors, then something is wrong..."); Logging.LogMessage(); return(gnfs); } int freeRelationIndex = 0; do { freeRelationIndex = StaticRandom.Next(0, freeRelations.Count); }while (triedFreeRelationIndices.Contains(freeRelationIndex)); triedFreeRelationIndices.Add(freeRelationIndex); // Add current selection to our list List <Relation> selectedRelationSet = freeRelations[freeRelationIndex]; // Get the solution set SquareFinder squareRootFinder = new SquareFinder(gnfs, selectedRelationSet); // If you want to solve for a new solution set, create a new instance Logging.LogMessage($"Selected solution set # {freeRelationIndex + 1}"); Logging.LogMessage(); Logging.LogMessage($"Selected set (a,b) pairs (count: {selectedRelationSet.Count}): {string.Join(" ", selectedRelationSet.Select(rel => $"({rel.A},{rel.B})"))}"); Logging.LogMessage(); Logging.LogMessage(); Logging.LogMessage(); Logging.LogMessage($"ƒ'(m) = {squareRootFinder.PolynomialDerivative}"); Logging.LogMessage($"ƒ'(m)^2 = {squareRootFinder.PolynomialDerivativeSquared}"); Logging.LogMessage(); Logging.LogMessage("Calculating Rational Square Root."); Logging.LogMessage("Please wait..."); squareRootFinder.CalculateRationalSide(); Logging.LogMessage("Completed."); Logging.LogMessage(); Logging.LogMessage($"γ² = {squareRootFinder.RationalProduct} IsSquare? {squareRootFinder.RationalProduct.IsSquare()}"); Logging.LogMessage($"(γ · ƒ'(m))^2 = {squareRootFinder.RationalSquare} IsSquare? {squareRootFinder.RationalSquare.IsSquare()}"); Logging.LogMessage(); Logging.LogMessage(); Logging.LogMessage("Calculating Algebraic Square Root."); Logging.LogMessage("Please wait..."); Tuple <BigInteger, BigInteger> foundFactors = squareRootFinder.CalculateAlgebraicSide(cancelToken); BigInteger P = foundFactors.Item1; BigInteger Q = foundFactors.Item2; if (cancelToken.IsCancellationRequested && P == 1 && Q == 1) { Logging.LogMessage("Square root search aborted!"); return(gnfs); } Logging.LogMessage("Completed."); Logging.LogMessage(); Logging.LogMessage(); if (P != 1 || Q != 1) { Logging.LogMessage("NON-TRIVIAL FACTORS FOUND!"); Logging.LogMessage(); } IPolynomial S = squareRootFinder.S; IPolynomial SRingSquare = squareRootFinder.SRingSquare; BigInteger prodS = SRingSquare.Evaluate(polyBase); IPolynomial reducedS = Polynomial.Field.Modulus(S, gnfs.N); BigInteger totalProdS = squareRootFinder.TotalS.Evaluate(polyBase) * squareRootFinder.PolynomialDerivative; BigInteger totalProdModN = totalProdS % gnfs.N; BigInteger prodSmodN = prodS % gnfs.N; List <BigInteger> algebraicNumberFieldSquareRoots = squareRootFinder.AlgebraicResults; BigInteger rationalSquareRoot = squareRootFinder.RationalSquareRootResidue; BigInteger algebraicSquareRoot = squareRootFinder.AlgebraicSquareRootResidue; Logging.LogMessage($"∏ Sᵢ ="); Logging.LogMessage($"{squareRootFinder.TotalS}"); Logging.LogMessage(); Logging.LogMessage($"∏ Sᵢ (mod ƒ) ="); Logging.LogMessage($"{reducedS}"); Logging.LogMessage(); Logging.LogMessage("Polynomial ring:"); Logging.LogMessage($"({string.Join(") * (", squareRootFinder.PolynomialRing.Select(ply => ply.ToString()))})"); Logging.LogMessage(); Logging.LogMessage("Primes:"); Logging.LogMessage($"{string.Join(" * ", squareRootFinder.AlgebraicPrimes)}"); // .RelationsSet.Select(rel => rel.B).Distinct().OrderBy(relB => relB)) Logging.LogMessage(); Logging.LogMessage(); Logging.LogMessage($"X² / ƒ(m) = {squareRootFinder.AlgebraicProductModF} IsSquare? {squareRootFinder.AlgebraicProductModF.IsSquare()}"); Logging.LogMessage(); Logging.LogMessage($""); Logging.LogMessage($"AlgebraicPrimes: {squareRootFinder.AlgebraicPrimes.FormatString(false)}"); Logging.LogMessage($"AlgebraicResults: {squareRootFinder.AlgebraicResults.FormatString(false)}"); Logging.LogMessage($""); Logging.LogMessage($"*****************************"); Logging.LogMessage($""); Logging.LogMessage($"AlgebraicSquareRootResidue: {squareRootFinder.AlgebraicSquareRootResidue}"); Logging.LogMessage($""); Logging.LogMessage($"AlgebraicNumberFieldSquareRoots: {algebraicNumberFieldSquareRoots.FormatString(false)}"); Logging.LogMessage($""); Logging.LogMessage($" RationalSquareRoot : {rationalSquareRoot}"); Logging.LogMessage($" AlgebraicSquareRoot: {algebraicSquareRoot} "); Logging.LogMessage($""); Logging.LogMessage($"*****************************"); Logging.LogMessage($"S (x) = {prodSmodN} IsSquare? {prodSmodN.IsSquare()}"); Logging.LogMessage(); Logging.LogMessage("Roots of S(x):"); Logging.LogMessage($"{{{string.Join(", ", squareRootFinder.RootsOfS.Select(tup => (tup.Item2 > 1) ? $"{tup.Item1}/{tup.Item2}" : $"{tup.Item1}"))}}}");
/** * Tests if the basis is valid. * @param h the polynomial h (either from the public key or from this basis) * @return <code>true</code> if the basis is valid, <code>false</code> otherwise */ public bool isValid(IntegerPolynomial h) { if (f.ToIntegerPolynomial().Coeffs.Length != N) { return(false); } if (fPrime.ToIntegerPolynomial().Coeffs.Length != N) { return(false); } if (h.Coeffs.Length != N || !h.IsReduced(q)) { return(false); } // determine F, G, g from f, fPrime, h using the eqn. fG-Fg=q IPolynomial FPoly = basisType == BasisType.STANDARD ? fPrime : f.Multiply(h, q); IntegerPolynomial F = FPoly.ToIntegerPolynomial(); IntegerPolynomial fq = f.ToIntegerPolynomial().InvertFq(q); IPolynomial g; if (basisType == BasisType.STANDARD) { g = f.Multiply(h, q); } else { g = fPrime; } IntegerPolynomial G = g.Multiply(F); G.Coeffs[0] -= q; G = G.Multiply(fq, q); G.ModCenter(q); // check norms of F and G if (!new FGBasis(f, fPrime, h, F, G, q, polyType, basisType, keyNormBoundSq).isNormOk()) { return(false); } // check norms of f and g int factor = N / 24; if (f.ToIntegerPolynomial().CenteredNormSq(q) * factor >= F.CenteredNormSq(q)) { return(false); } if (g.ToIntegerPolynomial().CenteredNormSq(q) * factor >= G.CenteredNormSq(q)) { return(false); } // check ternarity if (polyType == TernaryPolynomialType.SIMPLE) { if (!f.ToIntegerPolynomial().IsTernary()) { return(false); } if (!g.ToIntegerPolynomial().IsTernary()) { return(false); } } else { if (!(f.GetType().IsAssignableFrom(typeof(ProductFormPolynomial)))) { return(false); } if (!(g.GetType().IsAssignableFrom(typeof(ProductFormPolynomial)))) { return(false); } } return(true); }
public static List <FactorPair> FindPolynomialRootsInRange(CancellationToken cancelToken, IPolynomial polynomial, IEnumerable <BigInteger> primes, BigInteger rangeFrom, BigInteger rangeTo, int totalFactorPairs) { List <FactorPair> result = new List <FactorPair>(); BigInteger r = rangeFrom; while (r < rangeTo && result.Count < totalFactorPairs) { if (cancelToken.IsCancellationRequested) { break; } IEnumerable <BigInteger> modList = primes.Where(p => p > r); List <BigInteger> roots = Polynomial.GetRootsMod(polynomial, r, modList); if (roots.Any()) { result.AddRange(roots.Select(p => new FactorPair(p, r))); } r++; } return(result.OrderBy(tup => tup.P).ToList()); }
public Extrapolation(IPolynomial curve, double confidence) { Curve = curve; Confidence = confidence; }
private void GenerateFQ(IRandom Rng, out IPolynomial T, out IntegerPolynomial Fq, out IntegerPolynomial Fp) { var N = this.m_ntruParams.N; var q = this.m_ntruParams.Q; var df = this.m_ntruParams.DF; var df1 = this.m_ntruParams.DF1; var df2 = this.m_ntruParams.DF2; var df3 = this.m_ntruParams.DF3; var fastFp = this.m_ntruParams.FastFp; var sparse = this.m_ntruParams.Sparse; var polyType = this.m_ntruParams.PolyType; Fp = null; // choose a random f that is invertible mod 3 and q while (true) { IntegerPolynomial f; // choose random t, calculate f and fp if (fastFp) { // if fastFp=true, f is always invertible mod 3 if (polyType == TernaryPolynomialType.SIMPLE) { T = PolynomialGenerator.GenerateRandomTernary(N, df, df, sparse, Rng); } else { T = ProductFormPolynomial.GenerateRandom(N, df1, df2, df3, df3, Rng); } f = T.ToIntegerPolynomial(); f.Multiply(3); f.Coeffs[0] += 1; } else { if (polyType == TernaryPolynomialType.SIMPLE) { T = PolynomialGenerator.GenerateRandomTernary(N, df, df - 1, sparse, Rng); } else { T = ProductFormPolynomial.GenerateRandom(N, df1, df2, df3, df3 - 1, Rng); } f = T.ToIntegerPolynomial(); Fp = f.InvertF3(); if (Fp == null) { continue; } } Fq = f.InvertFq(q); if (Fq != null) { break; } } }
public GenericPolynomialExtensionField(IFiniteField subfield, IPolynomial polynomial) { this.subfield = subfield; this.minimalPolynomial = polynomial; }
public CrcCalc8(IPolynomial polynomial) { poly = polynomial; table = GenerateTable(poly); }
public IPolynomial Add(IPolynomial t) { return(AsPolynomial().Add(t)); }
public bool EqualTo(IPolynomial t) { return(AsPolynomial().EqualTo(t)); }
internal GenericPolynomialExtensionField(IFiniteField subfield, IPolynomial polynomial) { this.subfield = subfield; minimalPolynomial = polynomial; }
/// <summary> /// Decrypts a message /// </summary> /// /// <param name="Input">The message to decrypt</param> /// /// <returns>The decrypted message</returns> /// /// <exception cref="CryptoAsymmetricException">If not initialized, the specified hash algorithm is invalid, the encrypted data is invalid, or <c>MaxLenBytes</c> is greater than 255</exception> public byte[] Decrypt(byte[] Input) { if (!m_isInitialized) { throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", "The cipher has not been initialized!", new InvalidOperationException()); } IPolynomial priv_t = ((NTRUPrivateKey)m_keyPair.PrivateKey).T; IntegerPolynomial priv_fp = ((NTRUPrivateKey)m_keyPair.PrivateKey).FP; IntegerPolynomial pub = ((NTRUPublicKey)m_keyPair.PublicKey).H; int N = m_encParams.N; int q = m_encParams.Q; int db = m_encParams.Db; int maxMsgLenBytes = m_encParams.MessageMax; int dm0 = m_encParams.Dm0; int maxM1 = m_encParams.MaxM1; int minCallsMask = m_encParams.MinMGFHashCalls; bool hashSeed = m_encParams.HashSeed; int bLen = db / 8; IntegerPolynomial e = IntegerPolynomial.FromBinary(Input, N, q); IntegerPolynomial ci = Decrypt(e, priv_t, priv_fp); if (ci.Count(-1) < dm0) { throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", "Less than dm0 coefficients equal -1", new InvalidDataException()); } if (ci.Count(0) < dm0) { throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", "Less than dm0 coefficients equal 0", new InvalidDataException()); } if (ci.Count(1) < dm0) { throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", "Less than dm0 coefficients equal 1", new InvalidDataException()); } //if (maxMsgLenBytes > 255) // throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", "maxMsgLenBytes values bigger than 255 are not supported", new ArgumentOutOfRangeException()); IntegerPolynomial cR = e; cR.Subtract(ci); cR.ModPositive(q); byte[] coR4 = cR.ToBinary4(); IntegerPolynomial mask = MGF(coR4, N, minCallsMask, hashSeed); IntegerPolynomial cMTrin = ci; cMTrin.Subtract(mask); cMTrin.Mod3(); byte[] cb, p0, cm; using (BinaryReader reader = new BinaryReader(new MemoryStream(cMTrin.ToBinary3Sves(maxM1 > 0)))) { cb = new byte[bLen]; reader.Read(cb, 0, cb.Length); // llen=1, so read one byte int cl = reader.ReadByte() & 0xFF; if (cl > maxMsgLenBytes) { throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", string.Format("Message too long: {0} > {1}!", cl, maxMsgLenBytes), new InvalidDataException()); } cm = new byte[cl]; reader.Read(cm, 0, cm.Length); p0 = new byte[reader.BaseStream.Length - reader.BaseStream.Position]; reader.Read(p0, 0, p0.Length); } if (!Compare.IsEqual(p0, new byte[p0.Length])) { throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", "The message is not followed by zeroes!", new InvalidDataException()); } byte[] sData = GetSeed(cm, pub, cb); IPolynomial cr = GenerateBlindingPoly(sData); IntegerPolynomial cRPrime = cr.Multiply(pub); cRPrime.ModPositive(q); if (!cRPrime.Equals(cR)) { throw new CryptoAsymmetricException("NTRUEncrypt:Decrypt", "Invalid message encoding!", new InvalidDataException()); } return(cm); }
internal GenericPolynomialExtensionField(IFiniteField subfield, IPolynomial polynomial) { this.subfield = subfield; this.minimalPolynomial = polynomial; }
/// <summary> /// Encrypts a message /// </summary> /// /// <param name="Input">The message to encrypt</param> /// /// <returns>The encrypted message</returns> /// /// <exception cref="CryptoAsymmetricException">If not initialized, the specified hash algorithm is invalid, the encrypted data is invalid, or <c>maxLenBytes</c> is greater than 255</exception> public byte[] Encrypt(byte[] Input) { if (!m_isInitialized) { throw new CryptoAsymmetricException("NTRUEncrypt:Encrypt", "The cipher has not been initialized!", new InvalidOperationException()); } IntegerPolynomial pub = ((NTRUPublicKey)m_keyPair.PublicKey).H; int N = m_encParams.N; int q = m_encParams.Q; int maxLenBytes = m_encParams.MessageMax; int db = m_encParams.Db; int m_bufferLenBits = m_encParams.m_bufferLenBits; int dm0 = m_encParams.Dm0; int maxM1 = m_encParams.MaxM1; int minCallsMask = m_encParams.MinMGFHashCalls; bool hashSeed = m_encParams.HashSeed; int msgLen = Input.Length; //if (maxLenBytes > 255) // throw new CryptoAsymmetricException("len values bigger than 255 are not supported"); if (msgLen > maxLenBytes) { throw new CryptoAsymmetricException("NTRUEncrypt:Encrypt", string.Format("Message too long: {0} > {1}!", msgLen, maxLenBytes), new InvalidDataException()); } while (true) { // M = b|octL|m|p0 byte[] b = new byte[db / 8]; // forward padding m_rndEngine.GetBytes(b); byte[] p0 = new byte[maxLenBytes + 1 - msgLen]; byte[] msgTmp; using (BinaryWriter writer = new BinaryWriter(new MemoryStream((m_bufferLenBits + 7) / 8))) { writer.Write(b); writer.Write((byte)msgLen); writer.Write(Input); writer.Write(p0); msgTmp = ((MemoryStream)writer.BaseStream).ToArray(); } // don't use the constant coeff if maxM1 is set; see below IntegerPolynomial mTrin = IntegerPolynomial.FromBinary3Sves(msgTmp, N, maxM1 > 0); byte[] sData = GetSeed(Input, pub, b); IPolynomial r = GenerateBlindingPoly(sData); IntegerPolynomial R = r.Multiply(pub, q); byte[] oR4 = R.ToBinary4(); IntegerPolynomial mask = MGF(oR4, N, minCallsMask, hashSeed); mTrin.Add(mask); // If df and dr are close to N/3, and the absolute value of mTrin.sumCoeffs() is // large enough, the message becomes vulnerable to a meet-in-the-middle attack. // To prevent this, we set the constant coefficient to zero but first check to ensure // sumCoeffs() is small enough to keep the likelihood of a decryption failure low. if (maxM1 > 0) { if (mTrin.SumCoeffs() > maxM1) { continue; } mTrin.Coeffs[0] = 0; } mTrin.Mod3(); if (mTrin.Count(-1) < dm0) { continue; } if (mTrin.Count(0) < dm0) { continue; } if (mTrin.Count(1) < dm0) { continue; } R.Add(mTrin, q); R.EnsurePositive(q); return(R.ToBinary(q)); } }
/// <summary> /// Constructs a new private key from a polynomial /// </summary> /// /// <param name="T">The polynomial which determines the key: if <c>FastFp=true</c>, <c>f=1+3T</c>; otherwise, <c>f=T</c></param> /// <param name="FP">Fp the inverse of <c>f</c></param> /// <param name="N">The number of polynomial coefficients</param> /// <param name="Q">The big q modulus</param> /// <param name="Sparse">Sparse whether the polynomial <c>T</c> is sparsely or densely populated</param> /// <param name="FastFp">FastFp whether <c>FP=1</c></param> /// <param name="PolyType">PolyType type of the polynomial <c>T</c></param> internal NTRUPrivateKey(IPolynomial T, IntegerPolynomial FP, int N, int Q, bool Sparse, bool FastFp, TernaryPolynomialType PolyType) { _T = T; _FP = FP; _N = N; _Q = Q; _sparse = Sparse; _fastFp = FastFp; _polyType = PolyType; }
public IPolynomial Add(IPolynomial t) { return(AsPolynomial() + t.AsPolynomial()); }
private void GenerateFQ(IRandom Rng, out IPolynomial t, out IntegerPolynomial fq, out IntegerPolynomial fp) { int N = _ntruParams.N; int q = _ntruParams.Q; int df = _ntruParams.DF; int df1 = _ntruParams.DF1; int df2 = _ntruParams.DF2; int df3 = _ntruParams.DF3; bool fastFp = _ntruParams.FastFp; bool sparse = _ntruParams.Sparse; TernaryPolynomialType polyType = _ntruParams.PolyType; fp = null; // choose a random f that is invertible mod 3 and q while (true) { IntegerPolynomial f; // choose random t, calculate f and fp if (fastFp) { // if fastFp=true, f is always invertible mod 3 if (polyType == TernaryPolynomialType.SIMPLE) t = PolynomialGenerator.GenerateRandomTernary(N, df, df, sparse, Rng); else t = ProductFormPolynomial.GenerateRandom(N, df1, df2, df3, df3, Rng); f = t.ToIntegerPolynomial(); f.Multiply(3); f.Coeffs[0] += 1; } else { if (polyType == TernaryPolynomialType.SIMPLE) t = PolynomialGenerator.GenerateRandomTernary(N, df, df - 1, sparse, Rng); else t = ProductFormPolynomial.GenerateRandom(N, df1, df2, df3, df3 - 1, Rng); f = t.ToIntegerPolynomial(); fp = f.InvertF3(); if (fp == null) continue; } fq = f.InvertFq(q); if (fq != null) break; } }
public static LEMatrix DifferentiationMatrix(this IPolynomial p) => Polynomial.DifferentiationMatrix(p.Degree);