/// <summary>
        /// Generates a proper hash for old style 4.1.0 passwords.  This would be used
        /// if a 4.1.0 server contained old 16 byte hashes.
        /// </summary>
        /// <param name="password">The password to hash</param>
        /// <param name="seedBytes">Seed bytes received from the server</param>
        /// <returns>Byte array containing the password hash</returns>
        public static byte[] GetOld410Password(string password, byte[] seedBytes)
        {
            long[] passwordHash = Hash(password);
            string passHex = String.Format(CultureInfo.InvariantCulture,
                                           "{0,8:X}{1,8:X}", passwordHash[0], passwordHash[1]);

            int[] salt = getSaltFromPassword(passHex);

            // compute binary password
            byte[] binaryPassword = new byte[20];
            int offset = 0;
            for (int i = 0; i < 2; i++)
            {
                int val = salt[i];

                for (int t = 3; t >= 0; t--)
                {
                    binaryPassword[t + offset] = (byte) (val%256);
                    val >>= 8; /* Scroll 8 bits to get next part*/
                }

                offset += 4;
            }

            //SHA1 sha = new SHA1CryptoServiceProvider();
            SHA1Hash sha = new SHA1Hash();
            byte[] temp = new byte[8];
            Buffer.BlockCopy(binaryPassword, 0, temp, 0, 8);
            byte[] binaryHash = sha.ComputeHash(temp);

            byte[] scrambledBuff = new byte[20];
            XorScramble(seedBytes, 4, scrambledBuff, 0, binaryHash, 20);

            string scrambleString = Encoding.Default.GetString(scrambledBuff, 0, scrambledBuff.Length).Substring(0, 8);

            long[] hashPass = Hash(password);
            long[] hashMessage = Hash(scrambleString);

            long max = 0x3FFFFFFFL;
            byte[] to = new byte[20];
            int msgPos = 0;
            int msgLength = scrambleString.Length;
            int toPos = 0;
            long seed1 = (hashPass[0] ^ hashMessage[0])%max;
            long seed2 = (hashPass[1] ^ hashMessage[1])%max;

            while (msgPos++ < msgLength)
                to[toPos++] = (byte) (Math.Floor(rand(ref seed1, ref seed2, max)*31) + 64);

            /* Make it harder to break */
            byte extra = (byte) (Math.Floor(rand(ref seed1, ref seed2, max)*31));

            for (int i = 0; i < 8; i++)
                to[i] ^= extra;

            return to;
        }
        /// <summary>
        /// Generate a scrambled password for 4.1.0 using new passwords
        /// </summary>
        /// <param name="password">The password to scramble</param>
        /// <param name="seedBytes">The seedbytes used to scramble</param>
        /// <returns>Array of bytes containing the scrambled password</returns>
        public static byte[] Get410Password(string password, byte[] seedBytes)
        {
            SHA1Hash sha = new SHA1Hash();
            //SHA1 sha = new SHA1CryptoServiceProvider();

            // clean it and then digest it
            password = password.Replace(" ", "").Replace("\t", "");
            byte[] passBytes = Encoding.Default.GetBytes(password);
            byte[] firstPass = sha.ComputeHash(passBytes);

            byte[] input = new byte[24];
            Array.Copy(seedBytes, 0, input, 0, 4);
            Array.Copy(firstPass, 0, input, 4, 20);
            byte[] secondPass = sha.ComputeHash(input);

            byte[] scrambledBuff = new byte[20];
            XorScramble(seedBytes, 4, scrambledBuff, 0, secondPass, 20);

            byte[] finalBuff = new byte[20];
            XorScramble(scrambledBuff, 0, finalBuff, 0, firstPass, 20);

            return finalBuff;
        }
        /// <summary>
        /// Returns a byte array containing the proper encryption of the 
        /// given password/seed according to the new 4.1.1 authentication scheme.
        /// </summary>
        /// <param name="password"></param>
        /// <param name="seed"></param>
        /// <returns></returns>
        public static byte[] Get411Password(string password, string seed)
        {
            // if we have no password, then we just return 1 zero byte
            if (password.Length == 0) return new byte[1];

            //SHA1 sha = new SHA1CryptoServiceProvider();
            SHA1Hash sha = new SHA1Hash();

            byte[] firstHash = sha.ComputeHash(Encoding.Default.GetBytes(password));
            byte[] secondHash = sha.ComputeHash(firstHash);
            byte[] seedBytes = Encoding.Default.GetBytes(seed);

            byte[] input = new byte[seedBytes.Length + secondHash.Length];
            Array.Copy(seedBytes, 0, input, 0, seedBytes.Length);
            Array.Copy(secondHash, 0, input, seedBytes.Length, secondHash.Length);
            byte[] thirdHash = sha.ComputeHash(input);

            byte[] finalHash = new byte[thirdHash.Length + 1];
            finalHash[0] = 0x14;
            Array.Copy(thirdHash, 0, finalHash, 1, thirdHash.Length);

            for (int i = 1; i < finalHash.Length; i++)
                finalHash[i] = (byte) (finalHash[i] ^ firstHash[i - 1]);
            return finalHash;
        }
Beispiel #4
0
        /// <summary>
        /// Returns a byte array containing the proper encryption of the 
        /// given password/seed according to the new 4.1.1 authentication scheme.
        /// </summary>
        /// <param name="password"></param>
        /// <param name="seed"></param>
        /// <returns></returns>
        public static byte[] Get411Password(string password, string seed)
        {
            // if we have no password, then we just return 2 zero bytes
              if (password.Length == 0) return new byte[1];

              var sha = new SHA1Hash();

              byte[] firstHash = sha.ComputeHash(Encoding.UTF8.GetBytes(password));
              byte[] secondHash = sha.ComputeHash(firstHash);
              byte[] seedBytes = Encoding.UTF8.GetBytes(seed);

              byte[] input = new byte[seedBytes.Length + secondHash.Length];
              Array.Copy(seedBytes, 0, input, 0, seedBytes.Length);
              Array.Copy(secondHash, 0, input, seedBytes.Length, secondHash.Length);
              byte[] thirdHash = sha.ComputeHash(input);

              byte[] finalHash = new byte[thirdHash.Length + 1];
              finalHash[0] = 0x14;
              Array.Copy(thirdHash, 0, finalHash, 1, thirdHash.Length);

              for (int i = 1; i < finalHash.Length; i++)
            finalHash[i] = (byte)(finalHash[i] ^ firstHash[i - 1]);
              return finalHash;
              //byte[] buffer = new byte[finalHash.Length - 1];
              //Array.Copy(finalHash, 1, buffer, 0, finalHash.Length - 1);
              //return buffer;
        }