private bool ResumeSession(Stream stream, byte[] additionalChallenge) { stream.Write((byte)16); byte[] aChallenge = SaltGenerator.Create(16); stream.Write(aChallenge); stream.Write((short)m_resumeTicket.Length); stream.Write(m_resumeTicket); stream.Flush(); if (stream.ReadBoolean()) { SetHashMethod((HashMethod)stream.ReadNextByte()); byte[] bChallenge = stream.ReadBytes(stream.ReadNextByte()); byte[] clientProof = m_hash.ComputeHash(aChallenge, bChallenge, m_sessionSecret, additionalChallenge); stream.Write(clientProof); stream.Flush(); if (stream.ReadBoolean()) { byte[] serverProof = m_hash.ComputeHash(bChallenge, aChallenge, m_sessionSecret, additionalChallenge); byte[] serverProofCheck = stream.ReadBytes(m_hash.GetDigestSize()); return(serverProof.SecureEquals(serverProofCheck)); } } m_sessionSecret = null; m_resumeTicket = null; return(Authenticate(stream, additionalChallenge)); }
/// <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); } } }
/// <remarks> /// Create keying material using a two stage generator /// </remarks> private byte[] GetBlock() { // generate seed; 2x input block size per NIST sp800-90b. // since the generator has already been initialized, so long as the sum extraction length is less // than the generators maximum output length, using unique seed material on each key is worth the computational expense. byte[] seed = m_seedEngine.GetBytes((m_hashEngine.BlockSize * 2) - m_ctrLength); // rotate the counter at 32 bit intervals Rotate(m_ctrVector); // prepend the counter to the seed seed = ArrayUtils.Concat(m_ctrVector, seed); // special case for sha-2 if (m_dgtType == Digests.SHA256 || m_dgtType == Digests.SHA512) { // hmac key size is digest hash size: rfc 2104 byte[] key = m_seedEngine.GetBytes(m_hashEngine.DigestSize); // set hmac to *not* dispose of underlying digest using (HMAC mac = new HMAC(m_hashEngine, key, false)) return(mac.ComputeMac(seed)); } else { // other implemented digests do not require hmac return(m_hashEngine.ComputeHash(seed)); } }
/// <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); } } }
private void DigestTest(Digests DigestType, string Path, bool Parallel = false) { int hashSize = DigestFromName.GetDigestSize(DigestType); using (StreamReader r = new StreamReader(Path)) { string line; while ((line = r.ReadLine()) != null) { if (line.Contains(DMK_INP)) { byte[] input = new byte[0]; byte[] expect = new byte[hashSize]; byte[] key = new byte[0]; byte[] hash = new byte[hashSize]; int sze = DMK_INP.Length; if (line.Length - sze > 0) { input = HexConverter.Decode(line.Substring(sze, line.Length - sze)); } line = r.ReadLine(); sze = DMK_KEY.Length; if (line.Length - sze > 0) { key = HexConverter.Decode(line.Substring(sze, line.Length - sze)); } line = r.ReadLine(); sze = DMK_HSH.Length; if (line.Length - sze > 0) { expect = HexConverter.Decode(line.Substring(sze, line.Length - sze)); } IDigest dgt = DigestFromName.GetInstance(DigestType, Parallel); if (dgt.Enumeral == Digests.Blake2B512) { ((Blake2B512)dgt).LoadMacKey(new MacParams(key)); } else { ((Blake2S256)dgt).LoadMacKey(new MacParams(key)); } hash = dgt.ComputeHash(input); //16,235 if (Evaluate.AreEqual(hash, expect) == false) { throw new Exception("Blake2: Expected hash is not equal!"); } } } } }
/// <summary> /// Get a pseudo random 32bit integer /// </summary> /// /// <returns>Random int</returns> public int Next() { int value = 0; for (int i = 0; i < 32; i += 8) { if (m_position >= m_rndData.Length) { m_rndData = m_digest.ComputeHash(m_rndData); m_position = 0; } value = (value << 8) | (m_rndData[m_position] & 0xFF); m_position++; } return(value); }
/// <remarks> /// Create keying material using a two stage generator /// </remarks> private byte[] GetBlock() { // generate seed; 2x input block per NIST sp800-90b byte[] seed = _seedEngine.GetBytes((_hashEngine.BlockSize * 2)); if (_hashEngine.GetType().Equals(typeof(SHA512)) || _hashEngine.GetType().Equals(typeof(SHA256))) { // hmac key size is digest hash size: rfc 2104 byte[] key = _seedEngine.GetBytes(_hashEngine.DigestSize); // set hmac to *not* dispose of underlying digest using (HMAC mac = new HMAC(_hashEngine, key, false)) return(mac.ComputeMac(seed)); } else { // other implemented digests do not require hmac return(_hashEngine.ComputeHash(seed)); } }
/// <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; }
private bool StandardAuthentication(IDigest hash, Stream stream, byte[] additionalChallenge) { // Authenticate (If mode = 1) // C <= S // byte PasswordHashMethod // byte SaltLength // byte[] Salt // int Iterations // byte SrpHashMethod // int Bit Strength // byte[] Public B (Size equal to SRP Length) // C => S // byte[] Public A (Size equal to SRP Length) // byte[] Client Proof: H(Public A | Public B | SessionKey) // C <= S // Bool Success (if false, done) // byte[] Server Proof: H(Public B | Public A | SessionKey) int srpNumberLength = ((int)m_user.SrpStrength) >> 3; stream.WriteByte((byte)PasswordHashMethod); stream.WriteByte((byte)m_user.Salt.Length); stream.Write(m_user.Salt); stream.Write(m_user.Iterations); stream.WriteByte((byte)SrpHashMethod); stream.Write((int)m_user.SrpStrength); stream.Flush(); //since computing B takes a long time. Go ahead and flush var param = SrpConstants.Lookup(m_user.SrpStrength); Srp6Server server = new Srp6Server(param, m_user.VerificationInteger); BigInteger pubB = server.GenerateServerCredentials(); byte[] pubBBytes = pubB.ToPaddedArray(srpNumberLength); stream.Write(pubBBytes); stream.Flush(); //Read from client: A byte[] pubABytes = stream.ReadBytes(srpNumberLength); BigInteger pubA = new BigInteger(1, pubABytes); //Calculate Session Key BigInteger S = server.CalculateSecret(hash, pubA); byte[] SBytes = S.ToPaddedArray(srpNumberLength); byte[] clientProofCheck = hash.ComputeHash(pubABytes, pubBBytes, SBytes, additionalChallenge); byte[] serverProof = hash.ComputeHash(pubBBytes, pubABytes, SBytes, additionalChallenge); byte[] clientProof = stream.ReadBytes(hash.GetDigestSize()); if (clientProof.SecureEquals(clientProofCheck)) { stream.Write(true); stream.Write(serverProof); stream.Flush(); byte[] K = hash.ComputeHash(pubABytes, SBytes, pubBBytes).Combine(hash.ComputeHash(pubBBytes, SBytes, pubABytes)); byte[] ticket = CreateSessionData(K, m_user); SessionSecret = K; stream.Write((short)ticket.Length); stream.Write(ticket); stream.Flush(); return true; } stream.Write(false); stream.Flush(); return false; }
private bool ResumeTicket(IDigest hash, Stream stream, byte[] additionalChallenge) { // Successful Resume Session (If mode = 1) // C => S // byte ChallengeLength // byte[] A = Challenge // int16 TicketLength // byte[] Ticket // C <= S // bool IsSuccess = true // byte HashMethod // byte ChallengeLength // byte[] B = Challenge // C => S // byte[] M1 = H(A | B | SessionKey) // Bool Success (if false, done) // C <= S // byte[] M2 = H(B | A | SessionKey) // Failed Resume Session // C => S // byte ChallengeLength // byte[] A = Challenge // int16 TicketLength // byte[] Ticket // C <= S // bool IsSuccess = false // Goto Authenticate Code byte[] a = stream.ReadBytes(stream.ReadNextByte()); int ticketLength = stream.ReadInt16(); if (ticketLength < 0 || ticketLength > 10000) return false; byte[] ticket = stream.ReadBytes(ticketLength); if (TryLoadTicket(ticket, m_user, out SessionSecret)) { stream.Write(true); stream.WriteByte((byte)SrpHashMethod); byte[] b = SaltGenerator.Create(16); stream.WriteByte(16); stream.Write(b); stream.Flush(); byte[] clientProofCheck = hash.ComputeHash(a, b, SessionSecret, additionalChallenge); byte[] serverProof = hash.ComputeHash(b, a, SessionSecret, additionalChallenge); byte[] clientProof = stream.ReadBytes(hash.GetDigestSize()); if (clientProof.SecureEquals(clientProofCheck)) { stream.Write(true); stream.Write(serverProof); stream.Flush(); return true; } stream.Write(false); return false; } stream.Write(false); return StandardAuthentication(hash, stream, additionalChallenge); }
private bool StandardAuthentication(IDigest hash, Stream stream, byte[] additionalChallenge) { // Authenticate (If mode = 1) // C <= S // byte PasswordHashMethod // byte SaltLength // byte[] Salt // int Iterations // byte SrpHashMethod // int Bit Strength // byte[] Public B (Size equal to SRP Length) // C => S // byte[] Public A (Size equal to SRP Length) // byte[] Client Proof: H(Public A | Public B | SessionKey) // C <= S // Bool Success (if false, done) // byte[] Server Proof: H(Public B | Public A | SessionKey) int srpNumberLength = ((int)m_user.SrpStrength) >> 3; stream.WriteByte((byte)PasswordHashMethod); stream.WriteByte((byte)m_user.Salt.Length); stream.Write(m_user.Salt); stream.Write(m_user.Iterations); stream.WriteByte((byte)SrpHashMethod); stream.Write((int)m_user.SrpStrength); stream.Flush(); //since computing B takes a long time. Go ahead and flush var param = SrpConstants.Lookup(m_user.SrpStrength); Srp6Server server = new Srp6Server(param, m_user.VerificationInteger); BigInteger pubB = server.GenerateServerCredentials(); byte[] pubBBytes = pubB.ToPaddedArray(srpNumberLength); stream.Write(pubBBytes); stream.Flush(); //Read from client: A byte[] pubABytes = stream.ReadBytes(srpNumberLength); BigInteger pubA = new BigInteger(1, pubABytes); //Calculate Session Key BigInteger S = server.CalculateSecret(hash, pubA); byte[] SBytes = S.ToPaddedArray(srpNumberLength); byte[] clientProofCheck = hash.ComputeHash(pubABytes, pubBBytes, SBytes, additionalChallenge); byte[] serverProof = hash.ComputeHash(pubBBytes, pubABytes, SBytes, additionalChallenge); byte[] clientProof = stream.ReadBytes(hash.GetDigestSize()); if (clientProof.SecureEquals(clientProofCheck)) { stream.Write(true); stream.Write(serverProof); stream.Flush(); byte[] K = hash.ComputeHash(pubABytes, SBytes, pubBBytes).Combine(hash.ComputeHash(pubBBytes, SBytes, pubABytes)); byte[] ticket = CreateSessionData(K, m_user); SessionSecret = K; stream.Write((short)ticket.Length); stream.Write(ticket); stream.Flush(); return(true); } stream.Write(false); stream.Flush(); return(false); }
private bool ResumeTicket(IDigest hash, Stream stream, byte[] additionalChallenge) { // Successful Resume Session (If mode = 1) // C => S // byte ChallengeLength // byte[] A = Challenge // int16 TicketLength // byte[] Ticket // C <= S // bool IsSuccess = true // byte HashMethod // byte ChallengeLength // byte[] B = Challenge // C => S // byte[] M1 = H(A | B | SessionKey) // Bool Success (if false, done) // C <= S // byte[] M2 = H(B | A | SessionKey) // Failed Resume Session // C => S // byte ChallengeLength // byte[] A = Challenge // int16 TicketLength // byte[] Ticket // C <= S // bool IsSuccess = false // Goto Authenticate Code byte[] a = stream.ReadBytes(stream.ReadNextByte()); int ticketLength = stream.ReadInt16(); if (ticketLength < 0 || ticketLength > 10000) { return(false); } byte[] ticket = stream.ReadBytes(ticketLength); if (TryLoadTicket(ticket, m_user, out SessionSecret)) { stream.Write(true); stream.WriteByte((byte)SrpHashMethod); byte[] b = SaltGenerator.Create(16); stream.WriteByte(16); stream.Write(b); stream.Flush(); byte[] clientProofCheck = hash.ComputeHash(a, b, SessionSecret, additionalChallenge); byte[] serverProof = hash.ComputeHash(b, a, SessionSecret, additionalChallenge); byte[] clientProof = stream.ReadBytes(hash.GetDigestSize()); if (clientProof.SecureEquals(clientProofCheck)) { stream.Write(true); stream.Write(serverProof); stream.Flush(); return(true); } stream.Write(false); return(false); } stream.Write(false); return(StandardAuthentication(hash, stream, additionalChallenge)); }
/// <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++; } } }
private bool TryResumeSession(ref Stream secureStream, Stream stream2, byte[] certSignatures) { #if SQLCLR return(false); #else if (m_resumeTicket != null && m_sessionSecret != null) { //Resume Session: // C => S // byte ResumeSession // byte TicketLength // byte[] Ticket // byte ClientChallengeLength // byte[] ClientChallenge byte[] clientChallenge = SaltGenerator.Create(16); stream2.WriteByte((byte)AuthenticationMode.ResumeSession); stream2.WriteByte((byte)m_resumeTicket.Length); stream2.Write(m_resumeTicket); stream2.WriteByte((byte)clientChallenge.Length); stream2.Write(clientChallenge); stream2.Flush(); // S <= C // byte HashMethod // byte ServerChallengeLength // byte[] ServerChallenge HashMethod hashMethod = (HashMethod)stream2.ReadNextByte(); IDigest hash = Scram.CreateDigest(hashMethod); byte[] serverChallenge = stream2.ReadBytes(stream2.ReadNextByte()); // C => S // byte ClientResponseLength // byte[] ClientChallenge byte[] clientResponse = hash.ComputeHash(serverChallenge, clientChallenge, m_sessionSecret, certSignatures); byte[] serverResponse = hash.ComputeHash(clientChallenge, serverChallenge, m_sessionSecret, certSignatures); stream2.WriteByte((byte)clientResponse.Length); stream2.Write(clientResponse); stream2.Flush(); // S => C // bool IsSuccessful // byte ServerResponseLength // byte[] ServerResponse if (stream2.ReadBoolean()) { byte[] serverResponseCheck = stream2.ReadBytes(stream2.ReadNextByte()); // C => S // bool IsSuccessful if (serverResponse.SecureEquals(serverResponseCheck)) { stream2.Write(true); stream2.Flush(); secureStream = stream2; return(true); } stream2.Write(false); stream2.Flush(); } m_resumeTicket = null; m_sessionSecret = null; } return(false); #endif }