title: Rfc2898DeriveBytes for .NET and Java generate different values
body: <p>I'm trying to use Rfc2898DeriveBytes for Android Java and .NET C# framework to generate key for encryption and decryption process. </p>
  
  <p>The problem is in spite of that the input values are same, I'm getting different keys in .NET and Java. </p>
  
  <p>.NET code:</p>
  
  <pre><code>private void btnRfc2898DeriveBytes_Click(object sender, EventArgs e)
  {
      byte[] salt = new byte[] { 19, 3, 24, 18, 14, 42, 57, 23 };
      Rfc2898DeriveBytes keyGenerator = null;
  
      keyGenerator = new Rfc2898DeriveBytes("somestring", salt, 1000);
  
      txtRfc2898DeriveBytes.Text = System.Text.Encoding.UTF8.GetString(keyGenerator.GetBytes(16));
  }
  </code></pre>
  
  <p>Java Code (used in an android application):</p>
  
  <pre><code>byte[] salt = new byte[] { 19, 3, 24, 18, 14, 42, 57, 23 };
  Rfc2898DeriveBytes keyGenerator = null;
  try {
      keyGenerator = new Rfc2898DeriveBytes("somestring", salt, 1000);
  } catch (InvalidKeyException e1) {
      e1.printStackTrace();
  } catch (NoSuchAlgorithmException e1) {
      e1.printStackTrace();
  } catch (UnsupportedEncodingException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
  }
  Log.i("key = ", decodeUTF8(keyGenerator.getBytes(16)));
  </code></pre>
  
  <p>Java Decode Method:</p>
  
  <pre><code>String decodeUTF8(byte[] bytes) {
      private final Charset UTF8_CHARSET = Charset.forName("UTF-8");
      return new String(bytes, UTF8_CHARSET);
  }
  </code></pre>
  
  <p>Rfc2898DeriveBytes java class:</p>
  
  <pre><code>import java.io.UnsupportedEncodingException;
  import java.security.InvalidKeyException;
  import java.security.NoSuchAlgorithmException;
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  
  /**
   * RFC 2898 password derivation compatible with .NET Rfc2898DeriveBytes class. 
   */
  public class Rfc2898DeriveBytes {
  
      private Mac _hmacSha1;
      private byte[] _salt;
      private int _iterationCount;
  
      private byte[] _buffer = new byte[20];
      private int _bufferStartIndex = 0;
      private int _bufferEndIndex = 0;
      private int _block = 1;
  
  
      /**
       * Creates new instance.
       * @param password The password used to derive the key.
       * @param salt The key salt used to derive the key.
       * @param iterations The number of iterations for the operation.
       * @throws NoSuchAlgorithmException HmacSHA1 algorithm cannot be found.
       * @throws InvalidKeyException Salt must be 8 bytes or more. -or- Password cannot be null.
       */
      public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations) throws NoSuchAlgorithmException, InvalidKeyException {
          if ((salt == null) || (salt.length &lt; 8)) { throw new InvalidKeyException("Salt must be 8 bytes or more."); }
          if (password == null) { throw new InvalidKeyException("Password cannot be null."); }
          this._salt = salt;
          this._iterationCount = iterations;
          this._hmacSha1 = Mac.getInstance("HmacSHA1");
          this._hmacSha1.init(new SecretKeySpec(password, "HmacSHA1"));
      }
  
      /**
       * Creates new instance.
       * @param password The password used to derive the key.
       * @param salt The key salt used to derive the key.
       * @param iterations The number of iterations for the operation.
       * @throws NoSuchAlgorithmException HmacSHA1 algorithm cannot be found.
       * @throws InvalidKeyException Salt must be 8 bytes or more. -or- Password cannot be null.
       * @throws UnsupportedEncodingException UTF-8 encoding is not supported. 
       */
      public Rfc2898DeriveBytes(String password, byte[] salt, int iterations) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException  {
          this(password.getBytes("UTF8"), salt, iterations);
      }
  
      /**
       * Creates new instance.
       * @param password The password used to derive the key.
       * @param salt The key salt used to derive the key.
       * @throws NoSuchAlgorithmException HmacSHA1 algorithm cannot be found.
       * @throws InvalidKeyException Salt must be 8 bytes or more. -or- Password cannot be null.
       * @throws UnsupportedEncodingException UTF-8 encoding is not supported. 
       */
      public Rfc2898DeriveBytes(String password, byte[] salt) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException {
          this(password, salt, 0x3e8);
      }
  
  
      /**
       * Returns a pseudo-random key from a password, salt and iteration count.
       * @param count Number of bytes to return.
       * @return Byte array.
       */
      public byte[] getBytes(int count) {
          byte[] result = new byte[count];
          int resultOffset = 0;
          int bufferCount = this._bufferEndIndex - this._bufferStartIndex;
  
          if (bufferCount &gt; 0) { //if there is some data in buffer
              if (count &lt; bufferCount) { //if there is enough data in buffer
                  System.arraycopy(this._buffer, this._bufferStartIndex, result, 0, count);
                  this._bufferStartIndex += count;
                  return result;
              }
              System.arraycopy(this._buffer, this._bufferStartIndex, result, 0, bufferCount);
              this._bufferStartIndex = this._bufferEndIndex = 0;
              resultOffset += bufferCount;
          }
  
          while (resultOffset &lt; count) {
              int needCount = count - resultOffset;
              this._buffer = this.func();
              if (needCount &gt; 20) { //we one (or more) additional passes
                  System.arraycopy(this._buffer, 0, result, resultOffset, 20);
                  resultOffset += 20;
              } else {
                  System.arraycopy(this._buffer, 0, result, resultOffset, needCount);
                  this._bufferStartIndex = needCount;
                  this._bufferEndIndex = 20;
                  return result;
              }
          }
          return result;
      }
  
  
      private byte[] func() {
          this._hmacSha1.update(this._salt, 0, this._salt.length);
          byte[] tempHash = this._hmacSha1.doFinal(getBytesFromInt(this._block));
  
          this._hmacSha1.reset();
          byte[] finalHash = tempHash;
          for (int i = 2; i &lt;= this._iterationCount; i++) {
              tempHash = this._hmacSha1.doFinal(tempHash);
              for (int j = 0; j &lt; 20; j++) {
                  finalHash[j] = (byte)(finalHash[j] ^ tempHash[j]);
              }
          }
          if (this._block == 2147483647) {
              this._block = -2147483648;
          } else {
              this._block += 1;
          }
  
          return finalHash;
      }
  
      private static byte[] getBytesFromInt(int i) {
          return new byte[] { (byte)(i &gt;&gt;&gt; 24), (byte)(i &gt;&gt;&gt; 16), (byte)(i &gt;&gt;&gt; 8), (byte)i };
      }
  
  }
  </code></pre>
  
  <p>Edit:</p>
  
  <p>I also convert it to Hex, but getting different values also. </p>
  
  <p>C# function:</p>
  
  <pre><code>public static String encode(byte[] data)
  {
      char[] lookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
      int i = 0, p = 2, l = data.Length;
      char[] c = new char[l * 2 + 2];
      byte d; c[0] = '0'; c[1] = 'x';
      while (i &lt; l)
      {
          d = data[i++];
          c[p++] = lookup[d / 0x10];
          c[p++] = lookup[d % 0x10];
      }
      return new string(c, 0, c.Length);
  }
  </code></pre>
  
  <p>Java method:</p>
  
  <pre><code>final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
  public static String bytesToHex(byte[] bytes) {
      char[] hexChars = new char[bytes.length * 2];
      int v;
      for ( int j = 0; j &lt; bytes.length; j++ ) {
          v = bytes[j] &amp; 0xFF;
          hexChars[j * 2] = hexArray[v &gt;&gt;&gt; 4];
          hexChars[j * 2 + 1] = hexArray[v &amp; 0x0F];
      }
      return new String(hexChars);
  }
  </code></pre>
  
  <p>What I'm doing wrong :( ?</p>