Matching JAVA SHA-512 to Salesforce's Crypto Generated Digest - java

I have a key, precisely which is to hashed in SHA-512 at my end in Java, I am getting the SHA-512 of the same key in Salesforce, but its not matching,
here is the key
T100375|Z123456|3.00|999999999|https://c.ap2.visual.force.com/apex/ThankYou|45454545|test_1.00_0.00~test_1.00_0.00~test_1.00_0.00|prasad.vandavasi#techprocess.co.in|7506384658|11740|Prasad
Vandavasi|7895455555|Y|F|40000000.00|6274148983DTKQQK
here is the salesforce logic..
String salt = '6274148983DTKQQK' //String.valueOf(Crypto.getRandomInteger());
String key = 'T100375|Z123456|3.00|999999999|https://c.ap2.visual.force.com/apex/ThankYou|45454545|test_1.00_0.00~test_1.00_0.00~test_1.00_0.00|prasad.vandavasi#techprocess.co.in|7506384658|11740|Prasad Vandavasi|7895455555|Y|F|40000000.00|6274148983DTKQQK'
Blob digest = Crypto.generateDigest('SHA-512', Blob.valueOf(key));
which generates following
01b80979c6ea2fb6cca5864386ccc9109f6d05d1d9d1a553b2ac8f82ed347a00ed2d940e5e898c0611ebd4f20e41ed8d9619cec8d6e5e1e5a81e1b5d7e6c7dd3
here is my java code..
public static void main(String[] args)throws Exception
{
String password = "T100375|Z123456|3.00|999999999|https://c.ap2.visual.force.com/apex/ThankYou|45454545|test_1.00_0.00~test_1.00_0.00~test_1.00_0.00|prasad.vandavasi#techprocess.co.in|7506384658|11740|Prasad Vandavasi|7895455555|Y|F|40000000.00|6274148983DTKQQK";
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(password.getBytes());
byte byteData[] = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Hex format : " + sb.toString());
//convert the byte to hex format method 2
StringBuffer hexString = new StringBuffer();
for (int i=0;i<byteData.length;i++) {
String hex=Integer.toHexString(0xff & byteData[i]);
if(hex.length()==1) hexString.append('0');
hexString.append(hex);
}
System.out.println("Hex format : " + hexString.toString());
}
which generates following..
d5da285c8eb9e93f55185c36e00efccaf77ea778e3443e43b0f22e14600951c8bd61b847604b010e2ebc9b3fbea06c5b817ac8e560d8ae6e59d8e9cef89842d7
Problem is both of these aren't matching, the keys, they should Ideally right ? what Should I do for them to match ?? I can write Java logic to match, salesforce side is something I have to comply with in my java code, and can not do anything on salesforce side.

Related

Java SHA not woking. Hash value dosen't equal String. Is there an issue with my encoding?

Basically I have this
if (args.length != 1) {
System.err.println("Usage: java MyMd5 <message>");
System.exit(1);
}
try {
// get message
byte[] message = args[0].getBytes("UTF8");
// create message digest object for MD5
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
// System.out.println("Provider: " +
messageDigest.getProvider().getInfo();
// create message digest
messageDigest.update(message);
byte[] md = messageDigest.digest();
// print result
System.out.println("Message Digest Algorithm: MD5");
System.out.println("Message: " + new String(message));
System.out.println("Message Digest: \"" + new String(md, "UTF8") + "\"");
String HashPassword=new String(md, "UTF8");
System.out.println(HashPassword);
System.out.println(HashPassword.equals("???8p???W?B:??N?~"));
but somehow when I try to compare it is returning false. Is it some problem with my encoding? Thanks!
Message Digest Algorithm: MD5
Message: pass123
Message Digest: "???8p???W?B:??N?~"
???8p???W?B:??N?~
false
The problem is with unnecessary encoding, with md5 we have to encode the String in the correct way instead of using UTF8 encoding
public static void main(String[] args) throws Exception {
String pass = "pass123";
byte[] message = pass.getBytes();
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
messageDigest.update(message);
byte[] md = messageDigest.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < md.length; i++) {
sb.append(Integer.toString((md[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("encoded pass:" + sb.toString());
System.out.println(sb.toString().equals("aafdc23870ecbcd3d557b6423a8982134e17927e"));
}
If I understood your question correctly you want to compare newly generated hash string with existing one (stored in a data base or somewhere else). It's possible with provided above code and you will get true if you store generated value (not copy it from console) to the data base for example, and then compare it with newly generated.
But when you generate hash it contains symbols (characters), that doesn't have correct representation in any String encoding. So, nobody don't store hashes as a plain strings. Usually they are stored in hex string representation or Base64 representation.
Implementation with the use of hex strings provided below:
public static void main(String[] args) throws Exception { // args = ["Hello world"]
if (args.length != 1) {
System.err.println("Usage: java MyMd5 <message>");
System.exit(1);
}
// get message
byte[] message = args[0].getBytes("UTF8"); //You may have problems with encoding here. In Windows, for example, with symbols that are out of English alphabet range
// create message digest object for MD5
MessageDigest messageDigest = MessageDigest.getInstance("SHA");
// System.out.println("Provider: " +
messageDigest.getProvider().getInfo();
// create message digest
messageDigest.update(message);
byte[] md = messageDigest.digest();
System.out.println("Digest: " + byteArrayToHexString(md));
System.out.println("Is equals? " + byteArrayToHexString(md).equals("7b502c3a1f48c8609ae212cdfb639dee39673f5e"));
}
private static String byteArrayToHexString(byte[] array) {
StringBuilder result = new StringBuilder(array.length);
IntStream.range(0, array.length)
.forEach(i -> result.append(Integer.toString( (array[i] & 0xff) + 0x100, 16).substring(1)));
return result.toString();
}
Also, in provided example mentioned that you are using MD5, but actually it's SHA. MessageDigest messageDigest = MessageDigest.getInstance("SHA");

Format sha-1 hash like .net does

I have a question about how java prints the HexString and how to print it in the same format that C# using the BitConverter does.
We (both) are generating this Hex as result of hashing a string with SHA-1 :
a94a8fe5ccb19ba61c4c873d391e987982fbbd3 (hash for "test" string)
The problem is when we test the hashing in C# , C# prints with uppercase and separated with "-" , like A9-4A-8F .. and so on.
How can I print the same format with java?
The code for hashing and printing is this:
String password = "test";
byte[] key = password.getBytes();
MessageDigest md = MessageDigest.getInstance("SHA-1",new BouncyCastleProvider());
byte[] hash = md.digest(key);
String result = "";
for (byte b : hash) {
result += Integer.toHexString(b & 255);
}
return result;
String result = "";
for (byte b : hash) {
result += Integer.toHexString(b & 255).toUpperCase() + "-";
}
return result.subString(0, result.length()-1);

SHA 256 in NodeJs

I am facing issue implementing this JAVA code in NodeJS
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(val.getBytes());
byte byteData[] = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(
Integer.toString(
(byteData[i] & 0xff) + 0x100, 16
).substring(1)
);
}
return sb.toString();
This is not strictly SHA-256. I wouldd like to understand what different is happening here.
I understand the way to generate a SHA-256 in NodeJS is:
crypto.createHash('sha256').update(message).digest('hex')
But in this case, it gives me a different result than the JAVA code.
Do I need to get the digest binary and then generate the hex in a way different than what digest(hex) does ?

Android's string hash doesn't match serverisde's

I'm developing an Android app and I need to send some data from server to Android device.
To prevent app from downloading too much data,I wrote a php service, which takes hash (md5 hash of last downloaded data), provided by Android and compares it to latest data's hash on server. If hashes match each other, it prints 'no_new_data', otherwise it prints latest data. Php uses md5($string) method to calculate hash - this part seems to work fine.
The problem is that hash calculated on device never matches server's one - it is wrong, even though string seems to be same. I tried even with changing encoding but it didn't help.
My md5 java code:
public static String md5(String base){
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(base.getBytes());
byte byteData[] = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
//System.out.println("Digest(in hex format):: " + sb.toString());
//convert the byte to hex format method 2
StringBuffer hexString = new StringBuffer();
for (int i=0;i<byteData.length;i++) {
String hex=Integer.toHexString(0xff & byteData[i]);
if(hex.length()==1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
}catch (Exception e){
return "a";
}
}
Thnks :)
Sometimes md5 hash is different from serverside hash. Try this method.
public static String getMD5Hash(String s) throws NoSuchAlgorithmException {
String result = s;
if (s != null) {
MessageDigest md = MessageDigest.getInstance("MD5"); // or "SHA-1"
md.update(s.getBytes());
BigInteger hash = new BigInteger(1, md.digest());
result = hash.toString(16);
while (result.length() < 32) { // 40 for SHA-1
result = "0" + result;
}
}
return result;
}
Never, ever use String.getBytes(), which depends on the platform-default charset, which is almost never what you want. It seems likely that the platform default charset differs between Android and your server side.
Pass it a Charset instead, e.g.
myString.getBytes(StandardCharsets.UTF_8)
if you have Java 7, or
myString.getBytes("UTF-8")
if you cannot.

hashing password using md5 and a control field

I want to hash a password using MD5 and I have given a string named MD5ControlHash
I found that I can hash a password in this way:
public static void main(String[] args)throws Exception
{
String password = "123456";
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(password.getBytes());
byte byteData[] = md.digest();
//convert the byte to hex format method 1
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
System.out.println("Digest(in hex format):: " + sb.toString());
}
However I don't know where should I use MD5ContolHash. Can anyone help me?
Does this code work correctly?
Thanks
If MD5ControlHash is a string, where should be stored hash of the password, you need to replace this line of code:
System.out.println("Digest(in hex format):: " + sb.toString());
with
MD5ControlHash = sb.toString();
If this string called MD5ControlHash stores the source data to hash, just use MD5ControlHash instead of password
And if you doubt about correctness of the code, just try it out!

Categories

Resources