PC Review


Reply
Thread Tools Rate Thread

C# MD5 Hash Does Not Match Hash Generated From Java

 
 
Ratfish
Guest
Posts: n/a
 
      5th Jun 2011
I've got a problem where a MD5 Hash function in .NET generates a
different hash than a similar routine in Java/Android. The Android
hash is calculated as "J0t��j#߸�bq-�",while the .NET hash is
calculated as "SjB0j+xqI9+4hxticS0Cjw==". Is this due to a character
set issue? Unicode versus non-unicode?

The code is below. Any suggestions would be greatly appreciated.

Aaron

=====================================
Here's the .NET code:

public static string EncodeText(byte[] key, string sText, Encoding
encoding)
{
HMACMD5 hmacMD5 = new HMACMD5(key);
byte[] textBytes = encoding.GetBytes(sText);
byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
string sEncodedText = Convert.ToBase64String(encodedTextBytes);
return sEncodedText;
}

=====================================
Here's the Android code:

public class HMACMD5 {

private final String HMAC_MD5_NAME = "HmacMD5";

private SecretKeySpec sk;
private Mac mac;

public HMACMD5(byte[] key) throws GeneralSecurityException {
init(key);
}

public HMACMD5(String key) throws GeneralSecurityException {
init(EncodingUtils.getAsciiBytes(key));
}

private void init(byte[] key) throws GeneralSecurityException {
sk = new SecretKeySpec(key, HMAC_MD5_NAME);
mac = Mac.getInstance(HMAC_MD5_NAME);
mac.init(sk);
}

public byte[] ComputeHash(byte[] data) {
return mac.doFinal(data);
}

public byte[] ComputeHash(String data) {
return ComputeHash(EncodingUtils.getAsciiBytes(data));
}
}

public String encodeText(String sKey, String sSrc) throws Exception {
HMACMD5 hmacMD5 = new HMACMD5(sKey);
byte[] textBytes = EncodingUtils.getBytes(sSrc, "UTF-8");
byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
String sEncodedText = EncodingUtils.getString(encodedTextBytes,
"BASE64");
return sEncodedText;
}


 
Reply With Quote
 
 
 
 
Arne Vajhøj
Guest
Posts: n/a
 
      6th Jun 2011
On 6/5/2011 1:34 AM, Ratfish wrote:
> I've got a problem where a MD5 Hash function in .NET generates a
> different hash than a similar routine in Java/Android. The Android
> hash is calculated as "J0t��j#߸�bq-�", while the .NET hash is
> calculated as "SjB0j+xqI9+4hxticS0Cjw==". Is this due to a character
> set issue? Unicode versus non-unicode?
>
> The code is below. Any suggestions would be greatly appreciated.


> =====================================
> Here's the .NET code:
>
> public static string EncodeText(byte[] key, string sText, Encoding
> encoding)
> {
> HMACMD5 hmacMD5 = new HMACMD5(key);
> byte[] textBytes = encoding.GetBytes(sText);
> byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> string sEncodedText = Convert.ToBase64String(encodedTextBytes);
> return sEncodedText;
> }
>
> =====================================
> Here's the Android code:
>
> public class HMACMD5 {
>
> private final String HMAC_MD5_NAME = "HmacMD5";
>
> private SecretKeySpec sk;
> private Mac mac;
>
> public HMACMD5(byte[] key) throws GeneralSecurityException {
> init(key);
> }
>
> public HMACMD5(String key) throws GeneralSecurityException {
> init(EncodingUtils.getAsciiBytes(key));
> }
>
> private void init(byte[] key) throws GeneralSecurityException {
> sk = new SecretKeySpec(key, HMAC_MD5_NAME);
> mac = Mac.getInstance(HMAC_MD5_NAME);
> mac.init(sk);
> }
>
> public byte[] ComputeHash(byte[] data) {
> return mac.doFinal(data);
> }
>
> public byte[] ComputeHash(String data) {
> return ComputeHash(EncodingUtils.getAsciiBytes(data));
> }
> }
>
> public String encodeText(String sKey, String sSrc) throws Exception {
> HMACMD5 hmacMD5 = new HMACMD5(sKey);
> byte[] textBytes = EncodingUtils.getBytes(sSrc, "UTF-8");
> byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> String sEncodedText = EncodingUtils.getString(encodedTextBytes,
> "BASE64");
> return sEncodedText;
> }


Difficult to say based on just some of the code.

But I can see two potential sources for errors:
1) you use byte[] as key for .NET and String being converted to
byte[] as US-ASCII for Java
2) the .NET code gets encoding of data as input while the Java code
treat data as US-ASCII

The code below are:
- complete
- generates same result "QkY+XkbFsIqyaQp5jPuLjw==" on .NET 4.0 and Java
SE 1.6

I have modified the Java code slightly to:
- fix the above
- avoid using the StringUtil class [it should be easy to convert the
code back to use StringUtil]

Arne

====

using System;
using System.Text;
using System.Security.Cryptography;

namespace E
{
public class Program
{
public static string EncodeText(byte[] key, string sText, Encoding
encoding)
{
HMACMD5 hmacMD5 = new HMACMD5(key);
byte[] textBytes = encoding.GetBytes(sText);
byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
string sEncodedText = Convert.ToBase64String(encodedTextBytes);
return sEncodedText;
}
public static void Main(string[] args)
{
Console.WriteLine(EncodeText(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
"This is a test!", Encoding.UTF8));
Console.ReadKey();
}
}
}

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.mail.MessagingException;
import javax.mail.internet.MimeUtility;

public class HMACFun {
public static String encodeText(byte[] key, String sSrc, String
encoding) throws Exception {
HMACMD5 hmacMD5 = new HMACMD5(key);
byte[] textBytes = sSrc.getBytes(encoding);
byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
String sEncodedText = B64.b64encode(encodedTextBytes);
return sEncodedText;
}
public static void main(String[] args) throws Exception {
System.out.println(encodeText(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
"This is a test!","UTF-8"));
}
}

class HMACMD5 {
private final String HMAC_MD5_NAME = "HmacMD5";
private SecretKeySpec sk;
private Mac mac;
public HMACMD5(byte[] key) throws GeneralSecurityException {
init(key);
}
public HMACMD5(String key, String encoding) throws
GeneralSecurityException, UnsupportedEncodingException {
init(key.getBytes(encoding));
}
private void init(byte[] key) throws GeneralSecurityException {
sk = new SecretKeySpec(key, HMAC_MD5_NAME);
mac = Mac.getInstance(HMAC_MD5_NAME);
mac.init(sk);
}
public byte[] ComputeHash(byte[] data) {
return mac.doFinal(data);
}
public byte[] ComputeHash(String data, String encoding) throws
UnsupportedEncodingException {
return ComputeHash(data.getBytes(encoding));
}
}

class B64 {
public static String b64encode(byte[] b) throws MessagingException,
IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream b64os = MimeUtility.encode(baos, "base64");
b64os.write(b);
b64os.close();
return new String(baos.toByteArray());
}
public static byte[] b64decode(String s) throws
MessagingException, IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
InputStream b64is = MimeUtility.decode(bais, "Base64");
byte[] tmp = new byte[s.length()];
int n = b64is.read(tmp);
byte[] res = new byte[n];
System.arraycopy(tmp, 0, res, 0, n);
return res;
}
}




 
Reply With Quote
 
Ratfish
Guest
Posts: n/a
 
      6th Jun 2011
On Jun 5, 6:23Â*pm, Arne Vajhøj <a...@vajhoej.dk> wrote:
> On 6/5/2011 1:34 AM, Ratfish wrote:
>
>
>
> > I've got a problem where a MD5 Hash function in .NET generates a
> > different hash than a similar routine in Java/Android. Â*The Android
> > hash is calculated as "J0t j#߸ bq- ", while the .NET hash is
> > calculated as "SjB0j+xqI9+4hxticS0Cjw==". Â*Is this due to a character
> > set issue? Â*Unicode versus non-unicode?

>
> > The code is below. Â*Any suggestions would be greatly appreciated.
> > =====================================
> > Here's the .NET code:

>
> > public static string EncodeText(byte[] key, string sText, Encoding
> > encoding)
> > {
> > Â* Â* HMACMD5 hmacMD5 = new HMACMD5(key);
> > Â* Â* byte[] textBytes = encoding.GetBytes(sText);
> > Â* Â* byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> > Â* Â* string sEncodedText = Convert.ToBase64String(encodedTextBytes);
> > Â* Â* return sEncodedText;
> > }

>
> > =====================================
> > Here's the Android code:

>
> > public class HMACMD5 {

>
> > Â* Â* private final String HMAC_MD5_NAME = "HmacMD5";

>
> > Â* Â* private SecretKeySpec sk;
> > Â* Â* private Mac mac;

>
> > Â* Â* public HMACMD5(byte[] key) throws GeneralSecurityException {
> > Â* Â* Â* Â*init(key);
> > Â* Â* }

>
> > Â* Â* public HMACMD5(String key) throws GeneralSecurityException {
> > Â* Â* Â* Â*init(EncodingUtils.getAsciiBytes(key));
> > Â* Â* }

>
> > Â* Â* private void init(byte[] key) throws GeneralSecurityException {
> > Â* Â* Â* Â*sk = new SecretKeySpec(key, HMAC_MD5_NAME);
> > Â* Â* Â* Â*mac = Mac.getInstance(HMAC_MD5_NAME);
> > Â* Â* Â* Â*mac.init(sk);
> > Â* Â* }

>
> > Â* Â* public byte[] ComputeHash(byte[] data) {
> > Â* Â* Â* Â*return mac.doFinal(data);
> > Â* Â* }

>
> > Â* Â* public byte[] ComputeHash(String data) {
> > Â* Â* Â* Â*return ComputeHash(EncodingUtils.getAsciiBytes(data));
> > Â* Â* }
> > }

>
> > public String encodeText(String sKey, String sSrc) throws Exception {
> > Â* Â* HMACMD5 hmacMD5 = new HMACMD5(sKey);
> > Â* Â* byte[] textBytes = EncodingUtils.getBytes(sSrc, "UTF-8");
> > Â* Â* byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> > Â* Â* String sEncodedText = EncodingUtils.getString(encodedTextBytes,
> > "BASE64");
> > Â* Â* return sEncodedText;
> > }

>
> Difficult to say based on just some of the code.
>
> But I can see two potential sources for errors:
> 1) you use byte[] as key for .NET and String being converted to
> Â* Â* byte[] as US-ASCII for Java
> 2) the .NET code gets encoding of data as input while the Java code
> Â* Â* treat data as US-ASCII
>
> The code below are:
> - complete
> - generates same result "QkY+XkbFsIqyaQp5jPuLjw==" on .NET 4.0 and Java
> SE 1.6
>
> I have modified the Java code slightly to:
> - fix the above
> - avoid using the StringUtil class [it should be easy to convert the
> code back to use StringUtil]
>
> Arne
>
> ====
>
> using System;
> using System.Text;
> using System.Security.Cryptography;
>
> namespace E
> {
> Â* Â* Â* Â* public class Program
> Â* Â* Â* Â* {
> Â* Â* Â* Â* Â* Â* Â* Â* public static string EncodeText(byte[] key, string sText, Encoding
> encoding)
> Â* Â* Â* Â* Â* Â* Â* Â* {
> Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*HMACMD5 hmacMD5 = new HMACMD5(key);
> Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*byte[] textBytes = encoding.GetBytes(sText);
> Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*string sEncodedText = Convert.ToBase64String(encodedTextBytes);
> Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*return sEncodedText;
> Â* Â* Â* Â* Â* Â* Â* Â* }
> Â* Â* Â* Â* Â* Â* Â* Â* public static void Main(string[] args)
> Â* Â* Â* Â* Â* Â* Â* Â* {
> Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Console.WriteLine(EncodeText(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8},
> "This is a test!", Encoding.UTF8));
> Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Console.ReadKey();
> Â* Â* Â* Â* Â* Â* Â* Â* }
> Â* Â* Â* Â* }
>
> }
>
> import java.io.ByteArrayInputStream;
> import java.io.ByteArrayOutputStream;
> import java.io.IOException;
> import java.io.InputStream;
> import java.io.OutputStream;
> import java.io.UnsupportedEncodingException;
> import java.security.GeneralSecurityException;
>
> import javax.crypto.Mac;
> import javax.crypto.spec.SecretKeySpec;
> import javax.mail.MessagingException;
> import javax.mail.internet.MimeUtility;
>
> public class HMACFun {
> Â* Â* Â* Â* public static String encodeText(byte[] key, String sSrc, String
> encoding) throws Exception {
> Â* Â* Â* Â* Â* Â*HMACMD5 hmacMD5 = new HMACMD5(key);
> Â* Â* Â* Â* Â* Â*byte[] textBytes = sSrc.getBytes(encoding);
> Â* Â* Â* Â* Â* Â*byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> Â* Â* Â* Â* Â* Â*String sEncodedText = B64.b64encode(encodedTextBytes);
> Â* Â* Â* Â* Â* Â*return sEncodedText;
> Â* Â* Â* Â* }
> Â* Â* Â* Â* public static void main(String[] args) throwsException {
> Â* Â* Â* Â* Â* Â* Â* Â* System.out.println(encodeText(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
> "This is a test!","UTF-8"));
> Â* Â* Â* Â* }
>
> }
>
> class HMACMD5 {
> Â* Â* Â* Â* private final String HMAC_MD5_NAME = "HmacMD5";
> Â* Â* Â* Â* private SecretKeySpec sk;
> Â* Â* Â* Â* private Mac mac;
> Â* Â* Â* Â* public HMACMD5(byte[] key) throws GeneralSecurityException {
> Â* Â* Â* Â* Â* Â* Â* Â* init(key);
> Â* Â* Â* Â* }
> Â* Â* Â* Â* public HMACMD5(String key, String encoding) throws
> GeneralSecurityException, UnsupportedEncodingException {
> Â* Â* Â* Â* Â* Â* Â* Â* init(key.getBytes(encoding));
> Â* Â* Â* Â* }
> Â* Â* Â* Â* private void init(byte[] key) throws GeneralSecurityException {
> Â* Â* Â* Â* Â* Â* Â* Â* sk = new SecretKeySpec(key, HMAC_MD5_NAME);
> Â* Â* Â* Â* Â* Â* Â* Â* mac = Mac.getInstance(HMAC_MD5_NAME);
> Â* Â* Â* Â* Â* Â* Â* Â* mac.init(sk);
> Â* Â* Â* Â* }
> Â* Â* Â* Â* public byte[] ComputeHash(byte[] data) {
> Â* Â* Â* Â* Â* Â* Â* Â* return mac.doFinal(data);
> Â* Â* Â* Â* }
> Â* Â* Â* Â* public byte[] ComputeHash(String data, Stringencoding) throws
> UnsupportedEncodingException {
> Â* Â* Â* Â* Â* Â* Â* Â* return ComputeHash(data.getBytes(encoding));
> Â* Â* Â* Â* }
>
> }
>
> class B64 {
> Â* Â* Â*public static String b64encode(byte[] b) throws MessagingException,
> IOException Â*{
> Â* Â* Â* Â* Â*ByteArrayOutputStream baos = new ByteArrayOutputStream();
> Â* Â* Â* Â* Â*OutputStream b64os = MimeUtility.encode(baos, "base64");
> Â* Â* Â* Â* Â*b64os.write(b);
> Â* Â* Â* Â* Â*b64os.close();
> Â* Â* Â* Â* Â*return new String(baos.toByteArray());
> Â* Â* Â* }
> Â* Â* Â* public static byte[] b64decode(String s) throws
> MessagingException, IOException Â*{
> Â* Â* Â* Â* Â*ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
> Â* Â* Â* Â* Â*InputStream b64is = MimeUtility.decode(bais, "Base64");
> Â* Â* Â* Â* Â*byte[] tmp = new byte[s.length()];
> Â* Â* Â* Â* Â*int n = b64is.read(tmp);
> Â* Â* Â* Â* Â*byte[] res = new byte[n];
> Â* Â* Â* Â* Â*System.arraycopy(tmp, 0, res, 0, n);
> Â* Â* Â* Â* Â*return res;
> Â* Â* Â* }
>
> }



Thanks Arne for the detailed response. And the others who set me
straight. I understand the suggested changes, but am still getting
strange results on the Android side: I've included the full example
projects I'm using for .NET and Android, using Arne's test case, which
should produce "QkY+XkbFsIqyaQp5jPuLjw==" on the Java side, but
doesn't. I did not implement Arne's B64 class yet, but that does not
appear to be the problem. The bytes returned from the computeHash
call do not match the bytes returned from the equivalent .NET call.
Anyone know what's going on with the Android project. Why doesn't it
yield the correct result?

Aaron

Android Project
================
package org.example.hmacmd5;

import org.apache.http.util.EncodingUtils;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class Test extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
TextView tv = new TextView(this);
try {
tv.setText(encodeText(new byte[] { 1, 2, 3, 4, 5, 6, 7,
8 }, "This is a test!", "UTF-8"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setContentView(tv);
}

public String encodeText(byte[] key, String sSrc, String sEncoding)
throws Exception {
HMACMD5 hmacMD5 = new HMACMD5(key);
byte[] textBytes = EncodingUtils.getBytes(sSrc, sEncoding);
byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
String sEncodedText = EncodingUtils.getString(encodedTextBytes,
"BASE64");
return sEncodedText;
}
}

package org.example.hmacmd5;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class HMACMD5 {
private final String HMAC_MD5_NAME = "HmacMD5";
private SecretKeySpec sk;
private Mac mac;

public HMACMD5(byte[] key) throws GeneralSecurityException {
init(key);
}

public HMACMD5(String key, String encoding) throws
GeneralSecurityException, UnsupportedEncodingException {
init(key.getBytes(encoding));
}

private void init(byte[] key) throws GeneralSecurityException {
sk = new SecretKeySpec(key, HMAC_MD5_NAME);
mac = Mac.getInstance(HMAC_MD5_NAME);
mac.init(sk);
}

public byte[] ComputeHash(byte[] data) {
return mac.doFinal(data);
}

public byte[] ComputeHash(String data, String encoding) throws
UnsupportedEncodingException {
return ComputeHash(data.getBytes(encoding));
}
}

..NET code
===================
using System;
using System.Text;
using System.Security.Cryptography;

namespace HmacMD5Test
{
class Program
{
public static string EncodeText(byte[] key, string sText,
Encoding encoding)
{
HMACMD5 hmacMD5 = new HMACMD5(key);
byte[] textBytes = encoding.GetBytes(sText);
byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
string sEncodedText =
Convert.ToBase64String(encodedTextBytes);
return sEncodedText;
}

static void Main(string[] args)
{
Console.WriteLine(EncodeText(new byte[] { 1, 2, 3, 4, 5, 6,
7, 8 }, "This is a test!", Encoding.UTF8));
Console.ReadKey();
}
}
}


 
Reply With Quote
 
Ratfish
Guest
Posts: n/a
 
      6th Jun 2011
On Jun 5, 10:31Â*pm, Ratfish <aaron.rad...@gmail.com> wrote:
> On Jun 5, 6:23Â*pm, Arne Vajhøj <a...@vajhoej.dk> wrote:
>
>
>
> > On 6/5/2011 1:34 AM, Ratfish wrote:

>
> > > I've got a problem where a MD5 Hash function in .NET generates a
> > > different hash than a similar routine in Java/Android. Â*The Android
> > > hash is calculated as "J0t j#߸ bq- ", while the .NET hash is
> > > calculated as "SjB0j+xqI9+4hxticS0Cjw==". Â*Is this due to a character
> > > set issue? Â*Unicode versus non-unicode?

>
> > > The code is below. Â*Any suggestions would be greatly appreciated..
> > > =====================================
> > > Here's the .NET code:

>
> > > public static string EncodeText(byte[] key, string sText, Encoding
> > > encoding)
> > > {
> > > Â* Â* HMACMD5 hmacMD5 = new HMACMD5(key);
> > > Â* Â* byte[] textBytes = encoding.GetBytes(sText);
> > > Â* Â* byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> > > Â* Â* string sEncodedText = Convert.ToBase64String(encodedTextBytes);
> > > Â* Â* return sEncodedText;
> > > }

>
> > > =====================================
> > > Here's the Android code:

>
> > > public class HMACMD5 {

>
> > > Â* Â* private final String HMAC_MD5_NAME = "HmacMD5";

>
> > > Â* Â* private SecretKeySpec sk;
> > > Â* Â* private Mac mac;

>
> > > Â* Â* public HMACMD5(byte[] key) throws GeneralSecurityException {
> > > Â* Â* Â* Â*init(key);
> > > Â* Â* }

>
> > > Â* Â* public HMACMD5(String key) throws GeneralSecurityException {
> > > Â* Â* Â* Â*init(EncodingUtils.getAsciiBytes(key));
> > > Â* Â* }

>
> > > Â* Â* private void init(byte[] key) throws GeneralSecurityException {
> > > Â* Â* Â* Â*sk = new SecretKeySpec(key, HMAC_MD5_NAME);
> > > Â* Â* Â* Â*mac = Mac.getInstance(HMAC_MD5_NAME);
> > > Â* Â* Â* Â*mac.init(sk);
> > > Â* Â* }

>
> > > Â* Â* public byte[] ComputeHash(byte[] data) {
> > > Â* Â* Â* Â*return mac.doFinal(data);
> > > Â* Â* }

>
> > > Â* Â* public byte[] ComputeHash(String data) {
> > > Â* Â* Â* Â*return ComputeHash(EncodingUtils.getAsciiBytes(data));
> > > Â* Â* }
> > > }

>
> > > public String encodeText(String sKey, String sSrc) throws Exception {
> > > Â* Â* HMACMD5 hmacMD5 = new HMACMD5(sKey);
> > > Â* Â* byte[] textBytes = EncodingUtils.getBytes(sSrc, "UTF-8");
> > > Â* Â* byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> > > Â* Â* String sEncodedText = EncodingUtils.getString(encodedTextBytes,
> > > "BASE64");
> > > Â* Â* return sEncodedText;
> > > }

>
> > Difficult to say based on just some of the code.

>
> > But I can see two potential sources for errors:
> > 1) you use byte[] as key for .NET and String being converted to
> > Â* Â* byte[] as US-ASCII for Java
> > 2) the .NET code gets encoding of data as input while the Java code
> > Â* Â* treat data as US-ASCII

>
> > The code below are:
> > - complete
> > - generates same result "QkY+XkbFsIqyaQp5jPuLjw==" on .NET 4.0 and Java
> > SE 1.6

>
> > I have modified the Java code slightly to:
> > - fix the above
> > - avoid using the StringUtil class [it should be easy to convert the
> > code back to use StringUtil]

>
> > Arne

>
> > ====

>
> > using System;
> > using System.Text;
> > using System.Security.Cryptography;

>
> > namespace E
> > {
> > Â* Â* Â* Â* public class Program
> > Â* Â* Â* Â* {
> > Â* Â* Â* Â* Â* Â* Â* Â* public static string EncodeText(byte[] key, string sText, Encoding
> > encoding)
> > Â* Â* Â* Â* Â* Â* Â* Â* {
> > Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*HMACMD5 hmacMD5 = new HMACMD5(key);
> > Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*byte[] textBytes = encoding.GetBytes(sText);
> > Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> > Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*string sEncodedText = Convert.ToBase64String(encodedTextBytes);
> > Â* Â* Â* Â* Â* Â* Â* Â* Â* Â*return sEncodedText;
> > Â* Â* Â* Â* Â* Â* Â* Â* }
> > Â* Â* Â* Â* Â* Â* Â* Â* public static void Main(string[] args)
> > Â* Â* Â* Â* Â* Â* Â* Â* {
> > Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Console.WriteLine(EncodeText(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
> > "This is a test!", Encoding.UTF8));
> > Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Â* Console.ReadKey();
> > Â* Â* Â* Â* Â* Â* Â* Â* }
> > Â* Â* Â* Â* }

>
> > }

>
> > import java.io.ByteArrayInputStream;
> > import java.io.ByteArrayOutputStream;
> > import java.io.IOException;
> > import java.io.InputStream;
> > import java.io.OutputStream;
> > import java.io.UnsupportedEncodingException;
> > import java.security.GeneralSecurityException;

>
> > import javax.crypto.Mac;
> > import javax.crypto.spec.SecretKeySpec;
> > import javax.mail.MessagingException;
> > import javax.mail.internet.MimeUtility;

>
> > public class HMACFun {
> > Â* Â* Â* Â* public static String encodeText(byte[] key,String sSrc, String
> > encoding) throws Exception {
> > Â* Â* Â* Â* Â* Â*HMACMD5 hmacMD5 = new HMACMD5(key);
> > Â* Â* Â* Â* Â* Â*byte[] textBytes = sSrc.getBytes(encoding);
> > Â* Â* Â* Â* Â* Â*byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> > Â* Â* Â* Â* Â* Â*String sEncodedText = B64.b64encode(encodedTextBytes);
> > Â* Â* Â* Â* Â* Â*return sEncodedText;
> > Â* Â* Â* Â* }
> > Â* Â* Â* Â* public static void main(String[] args) throws Exception {
> > Â* Â* Â* Â* Â* Â* Â* Â* System.out.println(encodeText(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 },
> > "This is a test!","UTF-8"));
> > Â* Â* Â* Â* }

>
> > }

>
> > class HMACMD5 {
> > Â* Â* Â* Â* private final String HMAC_MD5_NAME = "HmacMD5";
> > Â* Â* Â* Â* private SecretKeySpec sk;
> > Â* Â* Â* Â* private Mac mac;
> > Â* Â* Â* Â* public HMACMD5(byte[] key) throws GeneralSecurityException {
> > Â* Â* Â* Â* Â* Â* Â* Â* init(key);
> > Â* Â* Â* Â* }
> > Â* Â* Â* Â* public HMACMD5(String key, String encoding)throws
> > GeneralSecurityException, UnsupportedEncodingException {
> > Â* Â* Â* Â* Â* Â* Â* Â* init(key.getBytes(encoding));
> > Â* Â* Â* Â* }
> > Â* Â* Â* Â* private void init(byte[] key) throws GeneralSecurityException {
> > Â* Â* Â* Â* Â* Â* Â* Â* sk = new SecretKeySpec(key, HMAC_MD5_NAME);
> > Â* Â* Â* Â* Â* Â* Â* Â* mac = Mac.getInstance(HMAC_MD5_NAME);
> > Â* Â* Â* Â* Â* Â* Â* Â* mac.init(sk);
> > Â* Â* Â* Â* }
> > Â* Â* Â* Â* public byte[] ComputeHash(byte[] data) {
> > Â* Â* Â* Â* Â* Â* Â* Â* return mac.doFinal(data);
> > Â* Â* Â* Â* }
> > Â* Â* Â* Â* public byte[] ComputeHash(String data, String encoding) throws
> > UnsupportedEncodingException {
> > Â* Â* Â* Â* Â* Â* Â* Â* return ComputeHash(data.getBytes(encoding));
> > Â* Â* Â* Â* }

>
> > }

>
> > class B64 {
> > Â* Â* Â*public static String b64encode(byte[] b) throws MessagingException,
> > IOException Â*{
> > Â* Â* Â* Â* Â*ByteArrayOutputStream baos = new ByteArrayOutputStream();
> > Â* Â* Â* Â* Â*OutputStream b64os = MimeUtility.encode(baos, "base64");
> > Â* Â* Â* Â* Â*b64os.write(b);
> > Â* Â* Â* Â* Â*b64os.close();
> > Â* Â* Â* Â* Â*return new String(baos.toByteArray());
> > Â* Â* Â* }
> > Â* Â* Â* public static byte[] b64decode(String s) throws
> > MessagingException, IOException Â*{
> > Â* Â* Â* Â* Â*ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
> > Â* Â* Â* Â* Â*InputStream b64is = MimeUtility.decode(bais, "Base64");
> > Â* Â* Â* Â* Â*byte[] tmp = new byte[s.length()];
> > Â* Â* Â* Â* Â*int n = b64is.read(tmp);
> > Â* Â* Â* Â* Â*byte[] res = new byte[n];
> > Â* Â* Â* Â* Â*System.arraycopy(tmp, 0, res, 0, n);
> > Â* Â* Â* Â* Â*return res;
> > Â* Â* Â* }

>
> > }

>
> Thanks Arne for the detailed response. Â*And the others who set me
> straight. Â*I understand the suggested changes, but am still getting
> strange results on the Android side: Â*I've included the full example
> projects I'm using for .NET and Android, using Arne's test case, which
> should produce "QkY+XkbFsIqyaQp5jPuLjw==" on the Java side, but
> doesn't. Â*I did not implement Arne's B64 class yet, but that does not
> appear to be the problem. Â*The bytes returned from the computeHash
> call do not match the bytes returned from the equivalent .NET call.
> Anyone know what's going on with the Android project. Â*Why doesn't it
> yield the correct result?
>
> Aaron
>
> Android Project
> ================
> package org.example.hmacmd5;
>
> import org.apache.http.util.EncodingUtils;
>
> import android.app.Activity;
> import android.os.Bundle;
> import android.widget.TextView;
>
> public class Test extends Activity {
> Â* Â*/** Called when the activity is first created. */
> Â* Â*@Override
> Â* Â*public void onCreate(Bundle savedInstanceState) {
> Â* Â* Â* Â* super.onCreate(savedInstanceState);
> Â* Â* Â* Â* //setContentView(R.layout.main);
> Â* Â* Â* Â* TextView tv = new TextView(this);
> Â* Â* Â* Â* try {
> Â* Â* Â* Â* Â* Â*tv.setText(encodeText(new byte[]{ 1, 2, 3, 4, 5, 6, 7,
> 8 }, "This is a test!", "UTF-8"));
> Â* Â* Â* Â* } catch (Exception e) {
> Â* Â* Â* Â* Â* Â*// TODO Auto-generated catch block
> Â* Â* Â* Â* Â* Â*e.printStackTrace();
> Â* Â* Â* Â* }
> Â* Â* Â* Â* setContentView(tv);
> Â* Â*}
>
> Â* Â*public String encodeText(byte[] key, String sSrc, String sEncoding)
> throws Exception {
> Â* Â* Â* HMACMD5 hmacMD5 = new HMACMD5(key);
> Â* Â* Â* byte[] textBytes = EncodingUtils.getBytes(sSrc, sEncoding);
> Â* Â* Â* byte[] encodedTextBytes = hmacMD5.ComputeHash(textBytes);
> Â* Â* Â* String sEncodedText = EncodingUtils.getString(encodedTextBytes,
> "BASE64");
> Â* Â* Â* return sEncodedText;
> Â* Â*}
>
> }
>
> package org.example.hmacmd5;
>
> import java.io.UnsupportedEncodingException;
> import java.security.GeneralSecurityException;
> import javax.crypto.Mac;
> import javax.crypto.spec.SecretKeySpec;
>
> public class HMACMD5 {
> Â* Â*private final String HMAC_MD5_NAME = "HmacMD5";
> Â* Â*private SecretKeySpec sk;
> Â* Â*private Mac mac;
>
> Â* Â*public HMACMD5(byte[] key) throws GeneralSecurityException {
> Â* Â* Â* init(key);
> Â* Â*}
>
> Â* Â*public HMACMD5(String key, String encoding) throws
> GeneralSecurityException, UnsupportedEncodingException {
> Â* Â* Â* init(key.getBytes(encoding));
> Â* Â*}
>
> Â* Â*private void init(byte[] key) throws GeneralSecurityException {
> Â* Â* Â* sk = new SecretKeySpec(key, HMAC_MD5_NAME);
> Â* Â* Â* mac = Mac.getInstance(HMAC_MD5_NAME);
> Â* Â* Â* mac.init(sk);
> Â* Â*}
>
> Â* Â*public byte[] ComputeHash(byte[] data) {
> Â* Â* Â* return mac.doFinal(data);
> Â* Â*}
>
> Â* Â*public byte[] ComputeHash(String data, String encoding) throws
> UnsupportedEncodingException {
> Â* Â* Â* return ComputeHash(data.getBytes(encoding));
> Â* Â*}
>
> }
>
> .NET code
> ===================
> using System;
> using System.Text;
> using System.Security.Cryptography;
>
> namespace HmacMD5Test
> {
> Â* Â*class Program
> Â* Â*{
> Â* Â* Â* public static string EncodeText(byte[] key, string sText,
> Encoding encoding)
> Â* Â* Â* {
> Â* Â* Â* Â* Â*HMACMD5 hmacMD5 = new
> ...
>
> read more »


Realized that Java has signed and unsigned bytes. This got me looking
at the Base64 encoding, which wasn't working. Found a working Android
Base64 class that fixed the problem. Thanks for all the help.

Aaron
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Explorer.exe dies and autocheck hash doesn't match Mr. Arnold Windows Vista General Discussion 0 7th Sep 2008 04:57 PM
Re: Explorer.exe dies and autocheck hash doesn't match Kayman Windows Vista General Discussion 0 7th Sep 2008 06:38 AM
Comment on how to uniquely track your objects in C# / hash table /get hash code raylopez99 Microsoft C# .NET 25 11th Aug 2008 06:54 AM
get same hash string from .NET and java? G Tsang Microsoft Dot NET Compact Framework 1 10th Jul 2004 01:10 PM
Fast Substring Match in Hash without Iterating? bdwise Microsoft C# .NET 1 10th Nov 2003 04:58 AM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 10:41 AM.