/// <summary> /// Returns a number /// </summary> /// /// <returns>The next pseudo-random index</returns> public int NextIndex() { while (true) { if (_remLen < _C) { BitString M = _bitBuffer.GetTrailing(_remLen); int tmpLen = _C - _remLen; int cThreshold = _callCounter + (tmpLen + _hashLen - 1) / _hashLen; while (_callCounter < cThreshold) { byte[] data = new byte[_Z.Length + 4]; Buffer.BlockCopy(_Z, 0, data, 0, _Z.Length); Buffer.BlockCopy(IntUtils.IntToBytes(_callCounter), 0, data, _Z.Length, 4); byte[] H = _digestEngine.ComputeHash(data); M.AppendBits(H); _callCounter++; _remLen += 8 * _hashLen; } _bitBuffer = M; } // assume c less than 32 int i = _bitBuffer.Pop(_C); _remLen -= _C; if (i < (1 << _C) - ((1 << _C) % _N)) { return(i % _N); } } }
/// <summary> /// Returns a number /// </summary> /// /// <returns>The next pseudo-random index</returns> public int NextIndex() { while (true) { if (m_remLen < m_C) { BitString M = m_bitBuffer.GetTrailing(m_remLen); int tmpLen = m_C - m_remLen; int cThreshold = m_callCounter + (tmpLen + m_hashLen - 1) / m_hashLen; while (m_callCounter < cThreshold) { byte[] data = new byte[m_Z.Length + 4]; Buffer.BlockCopy(m_Z, 0, data, 0, m_Z.Length); Buffer.BlockCopy(IntUtils.IntToBytes(m_callCounter), 0, data, m_Z.Length, 4); byte[] H = m_digestEngine.ComputeHash(data); M.AppendBits(H); m_callCounter++; m_remLen += 8 * m_hashLen; } m_bitBuffer = M; } // assume c less than 32 int i = m_bitBuffer.Pop(m_C); m_remLen -= m_C; if (i < (1 << m_C) - ((1 << m_C) % m_N)) { return(i % m_N); } } }
/// <summary> /// Fill an array with pseudo random bytes /// </summary> /// /// <param name="Output">The destination array</param> public void GetBytes(byte[] Output) { int offset = 0; int X; int len = sizeof(int); while (offset < Output.Length) { X = Next(); if (Output.Length - offset < len) { len = Output.Length - offset; } Buffer.BlockCopy(IntUtils.IntToBytes(X), 0, Output, offset, len); offset += len; } }
/// <summary> /// Constructs a new index generator /// </summary> /// /// <param name="Seed">A seed of arbitrary length to initialize the index generator</param> /// <param name="EncParam">NtruEncrypt parameters</param> public IndexGenerator(byte[] Seed, NTRUParameters EncParam) { _N = EncParam.N; _C = EncParam.CBits; int minCallsR = EncParam.MinIGFHashCalls; _digestEngine = GetDigest(EncParam.Digest); _hashLen = _digestEngine.DigestSize; _Z = Seed; _callCounter = 0; _bitBuffer = new BitString(); while (_callCounter < minCallsR) { byte[] data = new byte[_Z.Length + 4]; Buffer.BlockCopy(_Z, 0, data, 0, _Z.Length); Buffer.BlockCopy(IntUtils.IntToBytes(_callCounter), 0, data, _Z.Length, 4); byte[] H = _digestEngine.ComputeHash(data); _bitBuffer.AppendBits(H); _callCounter++; } _remLen = minCallsR * 8 * _hashLen; }
/// <summary> /// An implementation of MGF-TP-1 from P1363.1 section 8.4.1.1. /// </summary> /// /// <param name="Seed">The seed value</param> /// <param name="N">N paramater</param> /// <param name="MinCallsMask">Minimum Calls Mask</param> /// <param name="HashSeed">Whether to hash the seed</param> /// /// <returns></returns> private IntegerPolynomial MGF(byte[] Seed, int N, int MinCallsMask, bool HashSeed) { int hashLen = _dgtEngine.DigestSize; using (MemoryStream writer = new MemoryStream(MinCallsMask * hashLen)) { byte[] Z = HashSeed ? _dgtEngine.ComputeHash(Seed) : Seed; int counter = 0; while (counter < MinCallsMask) { byte[] data = new byte[Z.Length + 4]; Buffer.BlockCopy(Z, 0, data, 0, Z.Length); Buffer.BlockCopy(IntUtils.IntToBytes(counter), 0, data, Z.Length, 4); byte[] hash = _dgtEngine.ComputeHash(data); writer.Write(hash, 0, hash.Length); counter++; } IntegerPolynomial i = new IntegerPolynomial(N); while (true) { int cur = 0; byte[] buffer = writer.ToArray(); for (int j = 0; j < buffer.Length; j++) { int O = (int)buffer[j] & 0xFF; if (O >= 243) // 243 = 3^5 { continue; } for (int terIdx = 0; terIdx < 4; terIdx++) { int rem3 = O % 3; i.Coeffs[cur] = rem3 == 2 ? -1 : rem3; // reduce to [-1..1] cur++; if (cur == N) { return(i); } O = (O - rem3) / 3; } i.Coeffs[cur] = O == 2 ? -1 : O; // reduce to [-1..1] cur++; if (cur == N) { return(i); } } if (cur >= N) { return(i); } // reset the memory writer.SetLength(0); writer.SetLength(hashLen); // get the hash byte[] hash = _dgtEngine.ComputeHash(ArrayUtils.Concat(Z, IntUtils.IntToBytes(counter))); writer.Write(hash, 0, hash.Length); counter++; } } }