title: Convert C# PBKDF2 using Rfc2898DeriveBytes to PHP
body: <p>Long story short have a membership system built in .NET that we are porting to WordPress and need to replicate the PBKDF2 encryption so users don't need to reset their passwords.</p>
  
  <p>Using a know hashed password I've been able to replicate this in .NET easily, with the following code:</p>
  
  <pre><code>static void Main(string[] args)
  {
    var isValid = CheckPassword("#0zEZcD7uNmv", "5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ");
  }
  
  public static int PBKDF2IterCount = 10000;
  public static int PBKDF2SubkeyLength = 256 / 8; // 256 bits
  public static int SaltSize = 128 / 8; // 128 bits
  
  private static bool CheckPassword(string Password, string ExistingHashedPassword)
  {
    byte[] saltAndPassword = Convert.FromBase64String(ExistingHashedPassword);
    byte[] salt = new byte[SaltSize];
  
    Array.Copy(saltAndPassword, 0, salt, 0, SaltSize);
  
    Console.WriteLine("--Salt--");
    Console.WriteLine(Convert.ToBase64String(salt));
  
    string hashedPassword = HashPassword(Password, salt);
  
    Console.WriteLine("--HashedPassword--");
    Console.WriteLine(hashedPassword);
  
    return hashedPassword == ExistingHashedPassword;
  }
  
  private static string HashPassword(string Password, byte[] salt)
  {
    byte[] hash = new byte[PBKDF2SubkeyLength];
    using (var pbkdf2 = new Rfc2898DeriveBytes(Password, salt, PBKDF2IterCount))
    {
      hash = pbkdf2.GetBytes(PBKDF2SubkeyLength);
    }
  
    byte[] hashBytes = new byte[PBKDF2SubkeyLength + SaltSize];
    Array.Copy(salt, 0, hashBytes, 0, SaltSize);
    Array.Copy(hash, 0, hashBytes, SaltSize, PBKDF2SubkeyLength);
  
    string hashedPassword = Convert.ToBase64String(hashBytes);
    return hashedPassword;
  }
  </code></pre>
  
  <p>The console app will produce the following:</p>
  
  <pre><code>--Salt--
  5SyOX+Rbclzvvit3MEM2nA==
  --HashedPassword--
  5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ
  --IsValid--
  True
  </code></pre>
  
  <p>However in the PHP side I can't get the same results. My code so far is below.</p>
  
  <pre><code>$mySalt = base64_decode('5SyOX+Rbclzvvit3MEM2nA==');
  $dev = pbkdf2('sha1', '#0zEZcD7uNmv', $mySalt, 10000, 48, true);
  $key = substr($dev, 0, 32); //Keylength: 32
  $iv = substr($dev, 32, 16); // IV-length: 16
  
  echo 'PHP&lt;br/&gt;';
  echo 'PASS: '.base64_encode($dev).'&lt;br/&gt;';
  echo 'SALT: '.base64_encode($iv).'&lt;br/&gt;&lt;br/&gt;'; 
  
  echo '.NET&lt;br/&gt;';
  echo 'PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ&lt;br/&gt;';
  echo 'SALT: 5SyOX+Rbclzvvit3MEM2nA==&lt;br/&gt;&lt;br/&gt;'; 
  
  function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
  {
      $algorithm = strtolower($algorithm);
      if(!in_array($algorithm, hash_algos(), true))
          die('PBKDF2 ERROR: Invalid hash algorithm.');
      if($count &lt;= 0 || $key_length &lt;= 0)
          die('PBKDF2 ERROR: Invalid parameters.');
  
      $hash_length = strlen(hash($algorithm, "", true));
      $block_count = ceil($key_length / $hash_length);
  
      $output = "";
      for($i = 1; $i &lt;= $block_count; $i++) {
          // $i encoded as 4 bytes, big endian.
          $last = $salt . pack("N", $i);
          // first iteration
          $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
          // perform the other $count - 1 iterations
          for ($j = 1; $j &lt; $count; $j++) {
              $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
          }
          $output .= $xorsum;
      }
      return substr($output, 0, $key_length);
  }
  </code></pre>
  
  <p>And the results are:</p>
  
  <pre><code>PHP
  PASS: FFo9WjYztlOzuffOddN/Jbg6HBOUku+lxSUKvJuWCRCsYe+1Tgbb8Ob4FtxumMal
  SALT: rGHvtU4G2/Dm+BbcbpjGpQ==
  
  .NET
  PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ
  SALT: 5SyOX+Rbclzvvit3MEM2nA==
  </code></pre>
  
  <p>Any help would be appreciated.</p>