質問

I am trying to hash a value (SHA1) in both C# and Java, and then return a base64 representation. I get 2 different results.

I know this is because Java uses signed bytes while C# doesn't.

C# version :

static public string toSHA1(string toEncrypt)
{
    return toSHA1(toEncrypt, new UTF8Encoding());
}

static public string toSHA1(string toEncrypt, Encoding encoding)
{
    String salt = "fE4wd#u*d9b9kdKszgè02ep5à4qZa!éi6";
    SHA256Managed sha256hasher = new SHA256Managed();
    byte[] hashedDataBytes = sha256hasher.ComputeHash(encoding.GetBytes(toEncrypt + salt));
    return Convert.ToBase64String(hashedDataBytes);
}

Java version :

public static String toSHA1(String toEncrypt) {
    return toSHA1(toEncrypt, "UTF-8");
}

public static String toSHA1(String toEncrypt, String encoding) {
    String salt = "fE4wd#u*d9b9kdKszgè02ep5à4qZa!éi6";
    String res = null;
    toEncrypt = toEncrypt + salt;
    try {
        byte[] dataBytes = toEncrypt.getBytes(encoding);
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        res = Base64.encodeBytes(md.digest(dataBytes));
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
    return res;
}

I can't manage to find a solution to get the correct base64 result using Java.

Converting signed values to unsigned ones forces the use of int data type, but as soon as I put it in a byte data type, I get my signed bytes back...

Base64.encodeBytes is waiting for a byte array, so is there any way I can pass an unsigned byte array to this method ? What can I do with that int array ? :

int[] dataInt = new int[dataBytes.length];
// signed to unsigned
for (int i=0; i<dataBytes.length; i++)
{
    dataInt[i] = (dataBytes[i] & 0xFF);
}

I can't modify the C# version, I have to adapt the Java version to give the same results.

役に立ちましたか?

解決

The problem is very simple... From your C# code:

SHA256Managed sha256hasher = new SHA256Managed()

SHA-256 != SHA-1. Use the SHA1 class instead in C#, or use SHA-256 in Java as well. As you apparently can't change the C# code, you should change the Java instead:

MessageDigest md = MessageDigest.getInstance("SHA-256");

Once you've done that, the base64-encoded data should be the same in both platforms. Even though bytes are signed in Java, base64 encoders treat them as unsigned... they're only interested in the bits, basically.

I'd also strongly suggest that you represent your salt in ASCII in the source code, using \uxxxx escaping for any non-ASCII characters. This will prevent problems due to compiling using the wrong encoding.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top