I want to convert a some code which is in Java to C#.
Java Code:
private static final byte[] SALT = "NJui8*&N823bVvy03^4N".getBytes();
public static final String getSHA256Hash(String secret)
{
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.update(secret.getBytes());
byte[] hash = digest.digest(SALT);
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < hash.length; i++) {
hexString.append(Integer.toHexString(0xFF & hash[i]));
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
throw new RuntimeException("SHA开发者_如何转开发-256 realization algorithm not found in JDK!");
}
When I tried to use the SimpleHash class I got different hashs
UPDATE:
For example:
Java: byte[] hash = digest.digest(SALT); generates (first 6 bytes):
[0] = 9
[1] = -95
[2] = -68
[3] = 64
[4] = -11
[5] = 53
....
C# code (class SimpleHash): string hashValue = Convert.ToBase64String(hashWithSaltBytes); hashWithSaltBytes has (first 6 bytes):
[0] 175 byte
[1] 209 byte
[2] 120 byte
[3] 74 byte
[4] 74 byte
[5] 227 byte
The String.getBytes method encodes the string to bytes using the platform's default charset, whereas the example code you linked uses UTF-8.
Try this:
digest.update(secret.getBytes("UTF-8"));
Secondly, the Integer.toHexString method returns the hexadecimal result with no leading 0s.
The C# code you link to also uses salt - but the Java code does not. If you use salt with once, but not the other, then the results will be (and should be!) different.
hexString.append(Integer.toHexString(0xFF & hash[i]));
You are building the hash string incorrectly. Integer.toHexString
does not include leading zeros, so while Integer.toHexString(0xFF) == "FF"
, the problem is that Integer.toHexString(0x05) == "5"
.
Suggested correction: String.format("%02x", hash[i] & 0xFF)
public static String getEncryptedPassword(String clearTextPassword) throws NoSuchAlgorithmException{
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(clearTextPassword.getBytes(StandardCharsets.UTF_8));
byte[] digest = md.digest();
String hex = String.format("%064x", new BigInteger(1, digest));
String st = new String(hex.toUpperCase());
for (int i = 2; i < (hex.length() + hex.length() / 2) - 1 ;) {
st = new StringBuffer(st).insert(i, "-").toString();
i = i + 3;
}
return st ;
}
You can use the following java to match that of C#
You didn't really write how you called the SimpleHash class - with which parameters and such.
But note that its ComputeHash
method has in its documentation:
Hash value formatted as a base64-encoded string.
Your class instead formats the output in hexadecimal, which will obviously be different.
Also, the salt is in SimpleHash interpreted as base64, while your method interprets it as ASCII (or whatever your system encoding is - most probably something ASCII-compatible, and the string only contains ASCII characters).
Also, the output in SimpleHash includes the salt (to allow reproducing it for the "verify" part when using random salt), which it doesn't in your method.
(More points are already mentioned by the other answers.)
精彩评论