예제 #1
0
        /**
         * @return <c>true</c> if the keyDigest is compatible with the specified saltData and saltHash
         */
        public bool Validate(byte[] saltData, byte[] saltHash)
        {
            Check16Bytes(saltData, "saltData");
            Check16Bytes(saltHash, "saltHash");

            // validation uses the RC4 for block zero
            RC4 rc4 = CreateRC4(0);

            byte[] saltDataPrime = new byte[saltData.Length];
            Array.Copy(saltData, saltDataPrime, saltData.Length);
            rc4.Encrypt(saltDataPrime);

            byte[] saltHashPrime = new byte[saltHash.Length];
            Array.Copy(saltHash, saltHashPrime, saltHash.Length);
            rc4.Encrypt(saltHashPrime);

            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                byte[] finalSaltResult = md5.ComputeHash(saltDataPrime);

                //if (false)
                //{ // set true to see a valid saltHash value
                //    byte[] saltHashThatWouldWork = xor(saltHash, xor(saltHashPrime, finalSaltResult));
                //    Console.WriteLine(HexDump.ToHex(saltHashThatWouldWork));
                //}

                return(Arrays.Equals(saltHashPrime, finalSaltResult));
            }
        }
예제 #2
0
        public void Xor(byte[] buf, int pOffSet, int pLen)
        {
            int nLeftInBlock;

            nLeftInBlock = _nextRC4BlockStart - _streamPos;
            if (pLen <= nLeftInBlock)
            {
                // simple case - this read does not cross key blocks
                _rc4.Encrypt(buf, pOffSet, pLen);
                _streamPos += pLen;
                return;
            }

            int offset = pOffSet;
            int len    = pLen;

            // start by using the rest of the current block
            if (len > nLeftInBlock)
            {
                if (nLeftInBlock > 0)
                {
                    _rc4.Encrypt(buf, offset, nLeftInBlock);
                    _streamPos += nLeftInBlock;
                    offset     += nLeftInBlock;
                    len        -= nLeftInBlock;
                }
                RekeyForNextBlock();
            }
            // all full blocks following
            while (len > RC4_REKEYING_INTERVAL)
            {
                _rc4.Encrypt(buf, offset, RC4_REKEYING_INTERVAL);
                _streamPos += RC4_REKEYING_INTERVAL;
                offset     += RC4_REKEYING_INTERVAL;
                len        -= RC4_REKEYING_INTERVAL;
                RekeyForNextBlock();
            }
            // finish with incomplete block
            _rc4.Encrypt(buf, offset, len);
            _streamPos += len;
        }