Beispiel #1
0
        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);
                }
            }
        }
Beispiel #3
0
        /// <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));
            }
        }
Beispiel #4
0
        /// <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);
                }
            }
        }
Beispiel #5
0
        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!");
                        }
                    }
                }
            }
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <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;
        }
        /// <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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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));
        }
Beispiel #14
0
        /// <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++;
                }
            }
        }
Beispiel #15
0
        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
        }