Manu404

phpass C# implementation for phpbb

Aug 17th, 2011
832
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class phpBBCryptoServiceProvider
  2.     {
  3.         /// <summary>
  4.         /// The encryption string base.
  5.         /// </summary>
  6.         private string itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  7.  
  8.         /// <summary>
  9.         /// Compares the password string given with the hash retrieved from your database.
  10.         /// </summary>
  11.         /// <param name="password">Plaintext password.</param>
  12.         /// <param name="hash">Hash from a SQL database</param>
  13.         /// <returns>True if the password is correct, False otherwise.</returns>
  14.         public bool phpbbCheckHash(string password, string hash)
  15.         {
  16.             if (hash.Length == 34) return (hashCryptPrivate(ASCIIEncoding.ASCII.GetBytes(password), hash, itoa64) == hash);
  17.             return false;
  18.         }
  19.  
  20.         /// <summary>
  21.         /// This function will return the resulting hash from the password string you specify.
  22.         /// </summary>
  23.         /// <param name="password">String to hash.</param>
  24.         /// <returns>Encrypted hash.</returns>
  25.         /// <remarks>
  26.         /// Although this will return the md5 for an older password, I have not added
  27.         /// support for older passwords, so they will not work with this class unless
  28.         /// I or someone else updates it.
  29.         /// </remarks>
  30.         public string phpbb_hash(string password)
  31.         {
  32.             // Generate a random string from a random number with the length of 6.
  33.             // You could use a static string instead, doesn't matter. E.g.
  34.             // byte[] random = ASCIIEncoding.ASCII.GetBytes("abc123");
  35.             byte[] random = ASCIIEncoding.ASCII.GetBytes(new Random().Next(100000, 999999).ToString());
  36.  
  37.             string hash = hashCryptPrivate(ASCIIEncoding.ASCII.GetBytes(password), hashGensaltPrivate(random, itoa64), itoa64);
  38.  
  39.             if (hash.Length == 34) return hash;
  40.  
  41.             return sMD5(password);
  42.         }
  43.  
  44.         /// <summary>
  45.         /// The workhorse that encrypts your hash.
  46.         /// </summary>
  47.         /// <param name="password">String to be encrypted. Use: ASCIIEncoding.ASCII.GetBytes();</param>
  48.         /// <param name="genSalt">Generated salt.</param>
  49.         /// <param name="itoa64">The itoa64 string.</param>
  50.         /// <returns>The encrypted hash ready to be compared.</returns>
  51.         /// <remarks>
  52.         /// password:  Saves conversion inside the function, lazy coding really.
  53.         /// genSalt:   Returns from hashGensaltPrivate(random, itoa64);
  54.         /// return:    Compare with phpbbCheckHash(password, hash)
  55.         /// </remarks>
  56.         private string hashCryptPrivate(byte[] password, string genSalt, string itoa64)
  57.         {
  58.             string output = "*";
  59.             MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
  60.             if (!genSalt.StartsWith("$H$")) return output;
  61.             //   $count_log2 = strpos($itoa64, $setting[3]);
  62.             int count_log2 = itoa64.IndexOf(genSalt[3]);
  63.             if (count_log2 < 7 || count_log2 > 30) return output;
  64.  
  65.             int count = 1 << count_log2;
  66.             byte[] salt = ASCIIEncoding.ASCII.GetBytes(genSalt.Substring(4, 8));
  67.  
  68.             if (salt.Length != 8) return output;
  69.  
  70.             byte[] hash = md5.ComputeHash(Combine(salt, password));
  71.  
  72.             do
  73.             {
  74.                 hash = md5.ComputeHash(Combine(hash, password));
  75.             } while (count-- > 1);
  76.  
  77.             output = genSalt.Substring(0, 12);
  78.             output += hashEncode64(hash, 16, itoa64);
  79.  
  80.             return output;
  81.         }
  82.  
  83.         /// <summary>
  84.         /// Private function to concat byte arrays.
  85.         /// </summary>
  86.         /// <param name="b1">Source array.</param>
  87.         /// <param name="b2">Array to add to the source array.</param>
  88.         /// <returns>Combined byte array.</returns>
  89.         private byte[] Combine(byte[] b1, byte[] b2)
  90.         {
  91.             byte[] retVal = new byte[b1.Length + b2.Length];
  92.             Array.Copy(b1, 0, retVal, 0, b1.Length);
  93.             Array.Copy(b2, 0, retVal, b1.Length, b2.Length);
  94.             return retVal;
  95.         }
  96.  
  97.         /// <summary>
  98.         /// Encode the hash.
  99.         /// </summary>
  100.         /// <param name="input">The hash to encode.</param>
  101.         /// <param name="count">[This parameter needs documentation].</param>
  102.         /// <param name="itoa64">The itoa64 string.</param>
  103.         /// <returns>Encoded hash.</returns>
  104.         private string hashEncode64(byte[] input, int count, string itoa64)
  105.         {
  106.             string output = "";
  107.             int i = 0; int value = 0;
  108.  
  109.             do
  110.             {
  111.                 value = input[i++];
  112.                 output += itoa64[value & 0x3f];
  113.  
  114.                 if (i < count) value |= input[i] << 8;
  115.                 output += itoa64[(value >> 6) & 0x3f];
  116.                 if (i++ >= count)
  117.                     break;
  118.  
  119.                 if (i < count) value |= input[i] << 16;
  120.                 output += itoa64[(value >> 12) & 0x3f];
  121.                 if (i++ >= count)
  122.                     break;
  123.  
  124.                 output += itoa64[(value >> 18) & 0x3f];
  125.  
  126.             } while (i < count);
  127.  
  128.             return output;
  129.         }
  130.  
  131.         /// <summary>
  132.         /// Generate salt for hash generation.
  133.         /// </summary>
  134.         /// <param name="input">Any random information.</param>
  135.         /// <param name="itoa64">The itoa64 string.</param>
  136.         /// <returns>Generated salt string</returns>
  137.         private string hashGensaltPrivate(byte[] input, string itoa64)
  138.         {
  139.             int iteration_count_log2 = 6;
  140.  
  141.             string output = "$H$";
  142.             output += itoa64[Math.Min(iteration_count_log2 + 5, 30)];
  143.             output += hashEncode64(input, 6, itoa64);
  144.  
  145.             return output;
  146.         }
  147.  
  148.         /// <summary>
  149.         /// Returns a hexadecimal string representation for the encrypted MD5 parameter.
  150.         /// </summary>
  151.         /// <param name="password">String to be encrypted.</param>
  152.         /// <returns>String</returns>
  153.         private string sMD5(string password) { return sMD5(password, false); }
  154.  
  155.         /// <summary>
  156.         /// Returns a hexadecimal string representation for the encrypted MD5 parameter.
  157.         /// </summary>
  158.         /// <param name="password">String to be encrypted.</param>
  159.         /// <param name="raw">Whether or not to produce a raw string.</param>
  160.         /// <returns>String</returns>
  161.         private string sMD5(string password, bool raw)
  162.         {
  163.             MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
  164.             if (raw) return Encoding.ASCII.GetString(md5.ComputeHash(Encoding.ASCII.GetBytes(password)));
  165.             else return BitConverter.ToString(md5.ComputeHash(Encoding.ASCII.GetBytes(password))).Replace("-", "");
  166.         }
  167.     }
RAW Paste Data