Advertisement
Guest User

C# implementation of WordPress PHPass

a guest
Jan 24th, 2015
623
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.92 KB | None | 0 0
  1.     public 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.             if (!genSalt.StartsWith("$P$")) return output;
  62.             //   $count_log2 = strpos($itoa64, $setting[3]);
  63.             int count_log2 = itoa64.IndexOf(genSalt[3]);
  64.             if (count_log2 < 7 || count_log2 > 30) return output;
  65.  
  66.             int count = 1 << count_log2;
  67.             byte[] salt = ASCIIEncoding.ASCII.GetBytes(genSalt.Substring(4, 8));
  68.  
  69.             if (salt.Length != 8) return output;
  70.  
  71.             byte[] hash = md5.ComputeHash(Combine(salt, password));
  72.  
  73.             do
  74.             {
  75.                 hash = md5.ComputeHash(Combine(hash, password));
  76.             } while (count-- > 1);
  77.  
  78.             output = genSalt.Substring(0, 12);
  79.             output += hashEncode64(hash, 16, itoa64);
  80.  
  81.             return output;
  82.         }
  83.  
  84.         /// <summary>
  85.         /// Private function to concat byte arrays.
  86.         /// </summary>
  87.         /// <param name="b1">Source array.</param>
  88.         /// <param name="b2">Array to add to the source array.</param>
  89.         /// <returns>Combined byte array.</returns>
  90.         private byte[] Combine(byte[] b1, byte[] b2)
  91.         {
  92.             byte[] retVal = new byte[b1.Length + b2.Length];
  93.             Array.Copy(b1, 0, retVal, 0, b1.Length);
  94.             Array.Copy(b2, 0, retVal, b1.Length, b2.Length);
  95.             return retVal;
  96.         }
  97.  
  98.         /// <summary>
  99.         /// Encode the hash.
  100.         /// </summary>
  101.         /// <param name="input">The hash to encode.</param>
  102.         /// <param name="count">[This parameter needs documentation].</param>
  103.         /// <param name="itoa64">The itoa64 string.</param>
  104.         /// <returns>Encoded hash.</returns>
  105.         private string hashEncode64(byte[] input, int count, string itoa64)
  106.         {
  107.             string output = "";
  108.             int i = 0; int value = 0;
  109.  
  110.             do
  111.             {
  112.                 value = input[i++];
  113.                 output += itoa64[value & 0x3f];
  114.  
  115.                 if (i < count) value |= input[i] << 8;
  116.                 output += itoa64[(value >> 6) & 0x3f];
  117.                 if (i++ >= count)
  118.                     break;
  119.  
  120.                 if (i < count) value |= input[i] << 16;
  121.                 output += itoa64[(value >> 12) & 0x3f];
  122.                 if (i++ >= count)
  123.                     break;
  124.  
  125.                 output += itoa64[(value >> 18) & 0x3f];
  126.  
  127.             } while (i < count);
  128.  
  129.             return output;
  130.         }
  131.  
  132.         /// <summary>
  133.         /// Generate salt for hash generation.
  134.         /// </summary>
  135.         /// <param name="input">Any random information.</param>
  136.         /// <param name="itoa64">The itoa64 string.</param>
  137.         /// <returns>Generated salt string</returns>
  138.         private string hashGensaltPrivate(byte[] input, string itoa64)
  139.         {
  140.             //int iteration_count_log2 = 6;
  141.             int iteration_count_log2 = 8;
  142.  
  143.             //string output = "$H$";
  144.             string output = "$P$";
  145.             output += itoa64[Math.Min(iteration_count_log2 + 5, 30)];
  146.             output += hashEncode64(input, 6, itoa64);
  147.  
  148.             return output;
  149.         }
  150.  
  151.         /// <summary>
  152.         /// Returns a hexadecimal string representation for the encrypted MD5 parameter.
  153.         /// </summary>
  154.         /// <param name="password">String to be encrypted.</param>
  155.         /// <returns>String</returns>
  156.         private string sMD5(string password) { return sMD5(password, false); }
  157.  
  158.         /// <summary>
  159.         /// Returns a hexadecimal string representation for the encrypted MD5 parameter.
  160.         /// </summary>
  161.         /// <param name="password">String to be encrypted.</param>
  162.         /// <param name="raw">Whether or not to produce a raw string.</param>
  163.         /// <returns>String</returns>
  164.         private string sMD5(string password, bool raw)
  165.         {
  166.             MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
  167.             if (raw) return Encoding.ASCII.GetString(md5.ComputeHash(Encoding.ASCII.GetBytes(password)));
  168.             else return BitConverter.ToString(md5.ComputeHash(Encoding.ASCII.GetBytes(password))).Replace("-", "");
  169.         }
  170.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement