/// <summary> /// Reads a parameter set from an input stream /// </summary> /// /// <param name="CipherParams">Stream containing a parameter set</param> public NTRUParameters(Stream CipherParams) { try { BinaryReader reader = new BinaryReader(CipherParams); _N = reader.ReadInt32(); _Q = reader.ReadInt32(); _DF = reader.ReadInt32(); _DF1 = reader.ReadInt32(); _DF2 = reader.ReadInt32(); _DF3 = reader.ReadInt32(); _Db = reader.ReadInt32(); _Dm0 = reader.ReadInt32(); _maxM1 = reader.ReadInt32(); _cBits = reader.ReadInt32(); _minIGFHashCalls = reader.ReadInt32(); _minMGFHashCalls = reader.ReadInt32(); _hashSeed = reader.ReadBoolean(); _oId = new byte[3]; reader.Read(_oId, 0, _oId.Length); _sparseMode = reader.ReadBoolean(); _fastFp = reader.ReadBoolean(); _polyType = (TernaryPolynomialType)reader.ReadInt32(); _messageDigest = (Digests)reader.ReadInt32(); _randomEngine = (Prngs)reader.ReadInt32(); Initialize(); } catch (Exception ex) { throw new NTRUException("NTRUParameters:CTor", "The stream could not be read!", ex); } }
/// <summary> /// Builds a parameter set from an encoded input stream /// </summary> /// /// <param name="ParamStream">Stream containing a parameter set</param> /// /// <exception cref="CryptoAsymmetricException">Thrown if the Stream is unreadable</exception> public NTRUParameters(Stream ParamStream) { try { BinaryReader reader = new BinaryReader(ParamStream); _oId = new byte[OID_SIZE]; reader.Read(_oId, 0, _oId.Length); _N = reader.ReadInt32(); _Q = reader.ReadInt32(); _DF = reader.ReadInt32(); _DF1 = reader.ReadInt32(); _DF2 = reader.ReadInt32(); _DF3 = reader.ReadInt32(); _Db = reader.ReadInt32(); _Dm0 = reader.ReadInt32(); _maxM1 = reader.ReadInt32(); _cBits = reader.ReadInt32(); _minIGFHashCalls = reader.ReadInt32(); _minMGFHashCalls = reader.ReadInt32(); _hashSeed = reader.ReadBoolean(); _sparseMode = reader.ReadBoolean(); _fastFp = reader.ReadBoolean(); _polyType = (TernaryPolynomialType)reader.ReadInt32(); _dgtEngineType = (Digests)reader.ReadInt32(); _rndEngineType = (Prngs)reader.ReadInt32(); Initialize(); } catch (Exception ex) { throw new CryptoAsymmetricException("NTRUParameters:CTor", "The stream could not be read!", ex); } }
/** * 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 private key from an input stream * @param is an input stream * @throws NtruException if an {@link IOException} occurs */ public SignaturePrivateKey(MemoryStream ins) { bases = new List <Basis>(); BinaryReader dataStream = new BinaryReader(ins); try { N = dataStream.ReadInt16(); q = dataStream.ReadInt16(); byte flags = dataStream.ReadByte(); sparse = (flags & 1) != 0; polyType = (flags & 4) == 0 ? TernaryPolynomialType.SIMPLE : TernaryPolynomialType.PRODUCT; basisType = ((flags & 8) == 0) ? BasisType.STANDARD : BasisType.TRANSPOSE; keyNormBoundSq = (float)dataStream.ReadInt32(); int numBases = dataStream.ReadByte(); for (int i = 0; i < numBases; i++) { // include a public key h[i] in all bases except for the first one add(new Basis(ins, N, q, sparse, polyType, basisType, keyNormBoundSq, i != 0)); } } catch (IOException e) { throw new NtruException(e.Message); } }
/// <summary> /// Constructs a parameter set that uses product-form private keys (i.e. <c>PolyType=PRODUCT</c>). /// </summary> /// /// <param name="OId">OId - Unique identifier; <c>Family</c>, <c>Set</c>, <c>SubSet</c>, and <c>Designator</c>. The NTRU family must be <c>2</c> corresponding with the <see cref="AsymmetricEngines"/> enumeration.</param> /// <param name="N">N number of polynomial coefficients</param> /// <param name="Q">The big Q Modulus</param> /// <param name="Df1">Number of ones in the private polynomial <c>f1</c></param> /// <param name="Df2">Number of ones in the private polynomial <c>f2</c></param> /// <param name="Df3">Number of ones in the private polynomial <c>f3</c></param> /// <param name="Dm0">Minimum acceptable number of -1's, 0's, and 1's in the polynomial <c>m'</c> in the last encryption step</param> /// <param name="MaxM1">Maximum absolute value of mTrin.sumCoeffs() or zero to disable this check. Values greater than zero cause the constant coefficient of the message to always be zero.</param> /// <param name="Db">Number of random bits to prepend to the message; should be a multiple of 8</param> /// <param name="CBits">The number of bits in candidate for deriving an index in IGF-2</param> /// <param name="MinIGFHashCalls">Minimum number of hash calls for the IGF to make</param> /// <param name="MinMGFHashCalls">Minimum number of calls to generate the masking polynomial</param> /// <param name="HashSeed">Whether to hash the seed in the MGF first (true) or use the seed directly (false)</param> /// <param name="Sparse">Whether to treat ternary polynomials as sparsely populated SparseTernaryPolynomial vs DenseTernaryPolynomial</param> /// <param name="FastFp">Whether <c>F=1+p*F</c> for a ternary <c>F</c> (true) or <c>F</c> is ternary (false)</param> /// <param name="Digest">The Message Digest engine to use; default is SHA512</param> /// <param name="Random">The pseudo random generator engine to use; default is CTRPrng</param> /// /// <exception cref="CryptoAsymmetricException">Thrown if the Oid format is invalid</exception> public NTRUParameters(byte[] OId, int N, int Q, int Df1, int Df2, int Df3, int Dm0, int MaxM1, int Db, int CBits, int MinIGFHashCalls, int MinMGFHashCalls, bool HashSeed, bool Sparse, bool FastFp, Digests Digest = Digests.SHA512, Prngs Random = Prngs.CTRPrng) { if (OId.Length != OID_SIZE) { throw new CryptoAsymmetricException("NTRUParameters:Ctor", string.Format("The OId is invalid, the OId length must be {0} bytes!", OID_SIZE, new ArgumentException())); } if (OId[0] != (byte)AsymmetricEngines.NTRU) { throw new CryptoAsymmetricException("NTRUParameters:Ctor", string.Format("The OId is invalid, first byte must be family designator ({0})!", AsymmetricEngines.NTRU, new ArgumentException())); } Array.Copy(OId, this.OId, Math.Min(OId.Length, OID_SIZE)); _N = N; _Q = Q; _DF1 = Df1; _DF2 = Df2; _DF3 = Df3; _Db = Db; _Dm0 = Dm0; _maxM1 = MaxM1; _cBits = CBits; _minIGFHashCalls = MinIGFHashCalls; _minMGFHashCalls = MinMGFHashCalls; _hashSeed = HashSeed; _sparseMode = Sparse; _fastFp = FastFp; _polyType = TernaryPolynomialType.PRODUCT; _dgtEngineType = Digest; _rndEngineType = Random; Initialize(); }
/** * Constructs a new private key from an input stream * @param is an input stream * @throws NtruException if an {@link IOException} occurs */ public SignaturePrivateKey(MemoryStream ins) { bases = new List<Basis>(); BinaryReader dataStream = new BinaryReader(ins); try { N = dataStream.ReadInt16(); q = dataStream.ReadInt16(); byte flags = dataStream.ReadByte(); sparse = (flags & 1) != 0; polyType = (flags & 4) == 0 ? TernaryPolynomialType.SIMPLE : TernaryPolynomialType.PRODUCT; basisType = ((flags & 8) == 0) ? BasisType.STANDARD : BasisType.TRANSPOSE; keyNormBoundSq = (float)dataStream.ReadInt32(); int numBases = dataStream.ReadByte(); for (int i = 0; i < numBases; i++) // include a public key h[i] in all bases except for the first one add(new Basis(ins, N, q, sparse, polyType, basisType, keyNormBoundSq, i != 0)); } catch (IOException e) { throw new NtruException(e.Message); } }
/// <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) { m_T = T; m_FP = FP; m_N = N; m_Q = Q; m_sparse = Sparse; m_fastFp = FastFp; m_polyType = PolyType; }
/// <summary> /// Read a Private key from a stream /// </summary> /// /// <param name="KeyStream">The stream containing the key</param> /// /// <returns>An initialized NTRUPrivateKey class</returns> /// /// <exception cref="NTRUException">Thrown if the stream can not be read</exception> public static NTRUPrivateKey From(MemoryStream KeyStream) { BinaryReader dataStream = new BinaryReader(KeyStream); try { // ins.Position = 0; wrong here, ins pos is wrong int n = IntUtils.ReadShort(KeyStream); int q = IntUtils.ReadShort(KeyStream); byte flags = dataStream.ReadByte(); bool sparse = (flags & 1) != 0; bool fastFp = (flags & 2) != 0; IPolynomial t; TernaryPolynomialType 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); } } // Initializes fp from t IntegerPolynomial fp; if (fastFp) { fp = new IntegerPolynomial(n); fp.Coeffs[0] = 1; } else { fp = t.ToIntegerPolynomial().InvertF3(); } return(new NTRUPrivateKey(t, fp, n, q, sparse, fastFp, polyType)); } catch (IOException ex) { throw new NTRUException("NTRUPrivateKey:From", ex.Message, ex); } }
/** * 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; }
/** * Constructs a private key that contains no bases */ public SignaturePrivateKey(SignatureParameters param) { N = param.N; q = param.q; sparse = param.sparse; polyType = param.polyType; basisType = param.basisType; keyNormBoundSq = param.keyNormBoundSq; bases = new List <Basis>(); }
/** * Constructs a private key that contains no bases */ public SignaturePrivateKey(SignatureParameters param) { N = param.N; q = param.q; sparse = param.sparse; polyType = param.polyType; basisType = param.basisType; keyNormBoundSq = param.keyNormBoundSq; bases = new List<Basis>(); }
/** * 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 parameter set that uses ternary private keys (i.e. </code>polyType=SIMPLE</code>). * @param N number of polynomial coefficients * @param q modulus * @param d number of -1's in the private polynomials <code>f</code> and <code>g</code> * @param B number of perturbations * @param basisType whether to use the standard or transpose lattice * @param beta balancing factor for the transpose lattice * @param normBound maximum norm for valid signatures * @param keyNormBound maximum norm for the polynomials <code>F</code> and <code>G</code> * @param primeCheck whether <code>2N+1</code> is prime * @param sparse whether to treat ternary polynomials as sparsely populated ({@link SparseTernaryPolynomial} vs {@link DenseTernaryPolynomial}) * @param keyGenAlg <code>RESULTANT</code> produces better bases, <code>FLOAT</code> is slightly faster. <code>RESULTANT</code> follows the EESS standard while <code>FLOAT</code> is described in Hoffstein et al: An Introduction to Mathematical Cryptography. * @param hashAlg a valid identifier for a <code>java.security.MessageDigest</code> instance such as <code>SHA-256</code>. The <code>MessageDigest</code> must support the <code>getDigestLength()</code> method. */ public SignatureParameters(int N, int q, int d, int B, BasisType basisType, float beta, float normBound, float keyNormBound, bool primeCheck, bool sparse, KeyGenAlg keyGenAlg, String hashAlg) { this.N = N; this.q = q; this.d = d; this.B = B; this.basisType = basisType; this.beta = beta; this.normBound = normBound; this.keyNormBound = keyNormBound; this.primeCheck = primeCheck; this.sparse = sparse; this.keyGenAlg = keyGenAlg; this.hashAlg = hashAlg; polyType = TernaryPolynomialType.SIMPLE; init(); }
/// <summary> /// Generates a new encryption key pair /// </summary> /// /// <param name="RngF">The random number generator to use for generating the secret polynomial f</param> /// <param name="RngG">The random number generator to use for generating the secret polynomial g</param> /// /// <returns>A key pair</returns> private IAsymmetricKeyPair GenerateKeyPair(IRandom RngF, IRandom RngG) { int N = _encParams.N; int q = _encParams.Q; bool fastFp = _encParams.FastFp; bool sparse = _encParams.Sparse; TernaryPolynomialType polyType = _encParams.PolyType; IPolynomial t = null; IntegerPolynomial fq = null; IntegerPolynomial fp = null; IntegerPolynomial g = null; if (ParallelUtils.IsParallel && _isParallel) { Action[] gA = new Action[] { new Action(() => g = GenerateG(RngG)), new Action(() => GenerateFQ(RngF, out t, out fq, out fp)) }; Parallel.Invoke(gA); } else { // Choose a random g that is invertible mod q. g = GenerateG(RngG); // choose a random f that is invertible mod 3 and q GenerateFQ(RngF, out t, out fq, out fp); } // if fastFp=true, fp=1 if (fastFp) { fp = new IntegerPolynomial(N); fp.Coeffs[0] = 1; } IntegerPolynomial h = g.Multiply(fq, q); h.Mult3(q); h.EnsurePositive(q); NTRUPrivateKey priv = new NTRUPrivateKey(t, fp, N, q, sparse, fastFp, polyType); NTRUPublicKey pub = new NTRUPublicKey(h, N, q); return(new NTRUKeyPair(pub, priv)); }
/// <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 m_N = IntUtils.ReadShort(KeyStream); m_Q = IntUtils.ReadShort(KeyStream); byte flags = dataStream.ReadByte(); m_sparse = (flags & 1) != 0; m_fastFp = (flags & 2) != 0; m_polyType = (flags & 4) == 0 ? TernaryPolynomialType.SIMPLE : TernaryPolynomialType.PRODUCT; if (PolyType == TernaryPolynomialType.PRODUCT) { m_T = ProductFormPolynomial.FromBinary(KeyStream, N); } else { IntegerPolynomial fInt = IntegerPolynomial.FromBinary3Tight(KeyStream, N); if (m_sparse) { m_T = new SparseTernaryPolynomial(fInt); } else { m_T = new DenseTernaryPolynomial(fInt); } } } catch (Exception ex) { throw new CryptoAsymmetricException("NTRUPrivateKey:Ctor", "The Private key could not be loaded!", ex); } Initialize(); }
/// <summary> /// Constructs a parameter set that uses ternary private keys (i.e. <c>PolyType=SIMPLE</c>) /// </summary> /// /// <param name="N">The ring dimension; the number of polynomial coefficients</param> /// <param name="Q">The big Q Modulus</param> /// <param name="Df">Number of ones in the private polynomial <c>f</c></param> /// <param name="Dm0">Minimum acceptable number of -1's, 0's, and 1's in the polynomial <c>m</c> in the last encryption step</param> /// <param name="MaxM1">Maximum absolute value of mTrin.sumCoeffs() or zero to disable this check. Values greater than zero cause the constant coefficient of the message to always be zero.</param> /// <param name="Db">Number of random bits to prepend to the message; should be a multiple of 8</param> /// <param name="CBits">The number of bits in candidate for deriving an index in IGF-2</param> /// <param name="MinIGFHashCalls">Minimum number of hash calls for the IGF to make</param> /// <param name="MinMGFHashCalls">Minimum number of calls to generate the masking polynomial</param> /// <param name="HashSeed">Whether to hash the seed in the MGF first (true), or use the seed directly (false)</param> /// <param name="OId">Three bytes that uniquely identify the parameter set</param> /// <param name="Sparse">Whether to treat ternary polynomials as sparsely populated; SparseTernaryPolynomial vs DenseTernaryPolynomial</param> /// <param name="FastFp">Whether <c>f=1+p*F</c> for a ternary <c>F</c> (true) or <c>f</c> is ternary (false)</param> /// <param name="Digest">The Message Digest engine to use; default is SHA512</param> /// <param name="Random">The pseudo random generator engine to use; default is CTRPrng</param> public NTRUParameters(int N, int Q, int Df, int Dm0, int MaxM1, int Db, int CBits, int MinIGFHashCalls, int MinMGFHashCalls, bool HashSeed, byte[] OId, bool Sparse, bool FastFp, Digests Digest = Digests.SHA512, Prngs Random = Prngs.CTRPrng) { _N = N; _Q = Q; _DF = Df; _Db = Db; _Dm0 = Dm0; _maxM1 = MaxM1; _cBits = CBits; _minIGFHashCalls = MinIGFHashCalls; _minMGFHashCalls = MinMGFHashCalls; _hashSeed = HashSeed; _sparseMode = Sparse; _fastFp = FastFp; _polyType = TernaryPolynomialType.SIMPLE; _messageDigest = Digest; _randomEngine = Random; this.OId = OId; Initialize(); }
/** * Reads a parameter set from an input stream. * @param is an input stream * @throws IOException */ public SignatureParameters(MemoryStream ins) { BinaryReader dis = new BinaryReader(ins); N = dis.ReadInt32(); q = dis.ReadInt32(); d = dis.ReadInt32(); d1 = dis.ReadInt32(); d2 = dis.ReadInt32(); d3 = dis.ReadInt32(); B = dis.ReadInt32(); basisType = (BasisType)dis.ReadInt32(); beta = dis.ReadSingle(); normBound = dis.ReadSingle(); keyNormBound = dis.ReadSingle(); signFailTolerance = dis.ReadInt32(); primeCheck = dis.ReadBoolean(); sparse = dis.ReadBoolean(); bitsF = dis.ReadInt32(); keyGenAlg = (KeyGenAlg)dis.ReadInt32(); hashAlg = dis.ReadString(); polyType = (TernaryPolynomialType)dis.ReadInt32(); init(); }
/// <summary> /// Constructs a parameter set that uses product-form private keys (i.e. <c>PolyType=PRODUCT</c>). /// </summary> /// /// <param name="OId">OId - Unique identifier; <c>Family</c>, <c>Set</c>, <c>SubSet</c>, and <c>Designator</c>. The NTRU family must be <c>2</c> corresponding with the <see cref="AsymmetricEngines"/> enumeration.</param> /// <param name="N">N number of polynomial coefficients</param> /// <param name="Q">The big Q Modulus</param> /// <param name="Df1">Number of ones in the private polynomial <c>f1</c></param> /// <param name="Df2">Number of ones in the private polynomial <c>f2</c></param> /// <param name="Df3">Number of ones in the private polynomial <c>f3</c></param> /// <param name="Dm0">Minimum acceptable number of -1's, 0's, and 1's in the polynomial <c>m'</c> in the last encryption step</param> /// <param name="MaxM1">Maximum absolute value of mTrin.sumCoeffs() or zero to disable this check. Values greater than zero cause the constant coefficient of the message to always be zero.</param> /// <param name="Db">Number of random bits to prepend to the message; should be a multiple of 8</param> /// <param name="CBits">The number of bits in candidate for deriving an index in IGF-2</param> /// <param name="MinIGFHashCalls">Minimum number of hash calls for the IGF to make</param> /// <param name="MinMGFHashCalls">Minimum number of calls to generate the masking polynomial</param> /// <param name="HashSeed">Whether to hash the seed in the MGF first (true) or use the seed directly (false)</param> /// <param name="Sparse">Whether to treat ternary polynomials as sparsely populated SparseTernaryPolynomial vs DenseTernaryPolynomial</param> /// <param name="FastFp">Whether <c>F=1+p*F</c> for a ternary <c>F</c> (true) or <c>F</c> is ternary (false)</param> /// <param name="Digest">The Message Digest engine to use; default is SHA512</param> /// <param name="Random">The pseudo random generator engine to use; default is CTRPrng</param> /// /// <exception cref="CryptoAsymmetricException">Thrown if the Oid format is invalid</exception> public NTRUParameters(byte[] OId, int N, int Q, int Df1, int Df2, int Df3, int Dm0, int MaxM1, int Db, int CBits, int MinIGFHashCalls, int MinMGFHashCalls, bool HashSeed, bool Sparse, bool FastFp, Digests Digest = Digests.SHA512, Prngs Random = Prngs.CTRPrng) { if (OId.Length != OID_SIZE) throw new CryptoAsymmetricException("NTRUParameters:Ctor", string.Format("The OId is invalid, the OId length must be {0} bytes!", OID_SIZE, new ArgumentException())); if (OId[0] != (byte)AsymmetricEngines.NTRU) throw new CryptoAsymmetricException("NTRUParameters:Ctor", string.Format("The OId is invalid, first byte must be family designator ({0})!", AsymmetricEngines.NTRU, new ArgumentException())); Array.Copy(OId, this.OId, Math.Min(OId.Length, OID_SIZE)); _N = N; _Q = Q; _DF1 = Df1; _DF2 = Df2; _DF3 = Df3; _Db = Db; _Dm0 = Dm0; _maxM1 = MaxM1; _cBits = CBits; _minIGFHashCalls = MinIGFHashCalls; _minMGFHashCalls = MinMGFHashCalls; _hashSeed = HashSeed; _sparseMode = Sparse; _fastFp = FastFp; _polyType = TernaryPolynomialType.PRODUCT; _dgtEngineType = Digest; _rndEngineType = Random; Initialize(); }
/// <summary> /// Constructs a parameter set that uses product-form private keys (i.e. <c>PolyType=PRODUCT</c>). /// </summary> /// /// <param name="N">N number of polynomial coefficients</param> /// <param name="Q">The big Q Modulus</param> /// <param name="Df1">Number of ones in the private polynomial <c>f1</c></param> /// <param name="Df2">Number of ones in the private polynomial <c>f2</c></param> /// <param name="Df3">Number of ones in the private polynomial <c>f3</c></param> /// <param name="Dm0">Minimum acceptable number of -1's, 0's, and 1's in the polynomial <c>m'</c> in the last encryption step</param> /// <param name="MaxM1">Maximum absolute value of mTrin.sumCoeffs() or zero to disable this check. Values greater than zero cause the constant coefficient of the message to always be zero.</param> /// <param name="Db">Number of random bits to prepend to the message; should be a multiple of 8</param> /// <param name="CBits">The number of bits in candidate for deriving an index in IGF-2</param> /// <param name="MinIGFHashCalls">Minimum number of hash calls for the IGF to make</param> /// <param name="MinMGFHashCalls">Minimum number of calls to generate the masking polynomial</param> /// <param name="HashSeed">Whether to hash the seed in the MGF first (true) or use the seed directly (false)</param> /// <param name="OId">Three bytes that uniquely identify the parameter set</param> /// <param name="Sparse">Whether to treat ternary polynomials as sparsely populated SparseTernaryPolynomial vs DenseTernaryPolynomial</param> /// <param name="FastFp">Whether <c>F=1+p*F</c> for a ternary <c>F</c> (true) or <c>F</c> is ternary (false)</param> /// <param name="Digest">The Message Digest engine to use; default is SHA512</param> /// <param name="Random">The pseudo random generator engine to use; default is CTRPrng</param> public NTRUParameters(int N, int Q, int Df1, int Df2, int Df3, int Dm0, int MaxM1, int Db, int CBits, int MinIGFHashCalls, int MinMGFHashCalls, bool HashSeed, byte[] OId, bool Sparse, bool FastFp, Digests Digest = Digests.SHA512, Prngs Random = Prngs.CTRPrng) { _N = N; _Q = Q; _DF1 = Df1; _DF2 = Df2; _DF3 = Df3; _Db = Db; _Dm0 = Dm0; _maxM1 = MaxM1; _cBits = CBits; _minIGFHashCalls = MinIGFHashCalls; _minMGFHashCalls = MinMGFHashCalls; _hashSeed = HashSeed; _sparseMode = Sparse; _fastFp = FastFp; _polyType = TernaryPolynomialType.PRODUCT; _messageDigest = Digest; _randomEngine = Random; this.OId = OId; Initialize(); }
private void GenerateFQ(IRandom Rng, out IPolynomial t, out IntegerPolynomial fq, out IntegerPolynomial fp) { int N = _encParams.N; int q = _encParams.Q; int df = _encParams.DF; int df1 = _encParams.DF1; int df2 = _encParams.DF2; int df3 = _encParams.DF3; bool fastFp = _encParams.FastFp; bool sparse = _encParams.Sparse; TernaryPolynomialType polyType = _encParams.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; } } }
/// <summary> /// Tests if the key pair is valid. /// <para>See IEEE 1363.1 section 9.2.4.1.</para> /// </summary> /// /// <returns>if the key pair is valid, <c>true</c> otherwise false</returns> public bool IsValid() { int N = ((NTRUPrivateKey)PrivateKey).N; int q = ((NTRUPrivateKey)PrivateKey).Q; TernaryPolynomialType polyType = ((NTRUPrivateKey)PrivateKey).PolyType; if (((NTRUPublicKey)PublicKey).N != N) { return(false); } if (((NTRUPublicKey)PublicKey).Q != q) { return(false); } if (((NTRUPrivateKey)PrivateKey).T.ToIntegerPolynomial().Coeffs.Length != N) { return(false); } IntegerPolynomial h = ((NTRUPublicKey)PublicKey).H.ToIntegerPolynomial(); if (h.Coeffs.Length != N) { return(false); } if (!h.IsReduced(q)) { return(false); } IntegerPolynomial f = ((NTRUPrivateKey)PrivateKey).T.ToIntegerPolynomial(); if (polyType == TernaryPolynomialType.SIMPLE && !f.IsTernary()) { return(false); } // if t is a ProductFormPolynomial, ternarity of f1,f2,f3 doesn't need to be verified if (polyType == TernaryPolynomialType.PRODUCT && !(((NTRUPrivateKey)PrivateKey).T.GetType().Equals(typeof(ProductFormPolynomial)))) { return(false); } if (polyType == TernaryPolynomialType.PRODUCT) { f.Multiply(3); f.Coeffs[0] += 1; f.ModPositive(q); } // the key generator pre-multiplies h by 3, so divide by 9 instead of 3 int inv9 = IntEuclidean.Calculate(9, q).X; // 9^-1 mod q IntegerPolynomial g = f.Multiply(h, q); g.Multiply(inv9); g.ModCenter(q); if (!g.IsTernary()) { return(false); } int dg = N / 3; // see EncryptionParameters.Initialize() if (g.Count(1) != dg) { return(false); } if (g.Count(-1) != dg - 1) { return(false); } return(true); }
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; }
/// <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; }
/// <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(); }