SHA 256 in NodeJs - java

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 ?

Related

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

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.

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!

Implementing AES Encryption/Decryption around existing PHP System on Android

I'm expanding an iOS project over to Android. My existing application communicates with a server via PHP using an AES encryption system.
Here are the functions that I am using on the PHP side:
Encrypt
function cryptAESEncrypt($string,$key) {
$key = md5($key);
$iv = "1234567890123436"; //IV isn't needed if MCRYPT_MODE is ECB (What we are using)
$data = $data = base64_encode($string);
$algorythm = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_ECB;
$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_MODE_ECB,$iv);
return base64_encode($encrypted);
}
Decrypt
function cryptAESDecrypt($string,$key) {
$key = md5($key);
$iv = "1234567890123436"; //IV isn't needed if MCRYPT_MODE is ECB (What we are using)
$data = base64_decode($string);
$algorythm = MCRYPT_RIJNDAEL_128;
$mode = MCRYPT_MODE_ECB;
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128,$key,$data,MCRYPT_MODE_ECB,$iv);
return base64_decode($decrypted);
}
The general flow of the process is:
md5 hash the $key (brings it down to 16 characters regardless)
Base64 Encode the $string
Encrypt the Base64'ed using 128Bit AES/RIJNDAEL in ECB mode (no IV)
Base64 the encrypted data and returns it as a string.
The decryption works the same but in reverse.
Now I'm just playing with samples but don't seem to be having much luck. I've encrypted the string "test" in PHP using that function ("test" was the key too - MD5'ed to 098f6bcd4621d373cade4e832627b4f6) and I am given the output of "ijzLe/2WgbaP+n3YScQSgQ==".
Now what I tried in Java didn't work as I get an incorrect key length error but I had more luck with a previous snippet earlier. Here's what I had anyway:
String key = "test";
String in = "ijzLe/2WgbaP+n3YScQSgQ==";
SecretKeySpec skeySpec = new SecretKeySpec(md5(key).getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] encryptedByteArray = Base64.decode(in.getBytes(),0);
byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
String decryptedData = new String(Base64.decode(decryptedByteArray, 0));
Log.v("NOTE","Data: "+decryptedData);
As I said though, that doesn't work. Now my question is, is there anybody that can help me make my Java code work with the supplied PHP code as I can't change that (had other code working using different PHP snippets).
Thanks to Duncan in the comments I found out the issue was with my MD5 hash function..
Found a working version for reference:
public String md5(String s) {
if (s != null)
{
try { // Create MD5 Hash
MessageDigest digest = java.security.MessageDigest .getInstance("MD5");
digest.update(s.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < messageDigest.length; i++) {
String h = Integer.toHexString(0xFF & messageDigest[i]);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
return "";
}

How to translate to JavaScript this custom MD5 Java function

I have this custom function to calculate MD5 hash, written in Java. I can't change it. I need to translate it to JavaScript to use it on client side. I tried on my own but I can't manage with JavaScript data types (expecially Java char[])... Any help is appreciated, thanks!
// codes array
char[] codes = new char[64];
// initialise
private void initCodes(){
codes = new char[64];
codes[0] = '$';
int count = 0;
for (char i='0';i<='9';i++){ count++; codes[count] = i; }
for (char i='A';i<='Z';i++){ count++; codes[count] = i; }
for (char i='a';i<='z';i++){ count++; codes[count] = i; }
codes[63] = '£';
}
// custom MD5 algorithm
public String customMD5(String source) {
initCodes();
byte[] buf = new byte[source.length()];
buf = source.getBytes();
MessageDigest algorithm = null;
try {
algorithm = MessageDigest.getInstance("MD5");
} catch(NoSuchAlgorithmException e){}
algorithm.reset();
algorithm.update(buf);
byte[] digest = algorithm.digest();
int len = digest.length;
char[] encrypted = new char[len];
for (int i=0;i<len;i++)
encrypted[i] = codes[(int)(Math.floor((double)((digest[i]+128)/4)))];
return new String(encrypted);
}
See this part here:
MessageDigest algorithm = null;
try{
algorithm = MessageDigest.getInstance("MD5");
}catch(NoSuchAlgorithmException e){}
? That's where that stuff is accessing the MD5 code that's built into the Java runtime. You'll have to come up with your own implementation of MD5 there, which (to put it mildly) will be the tricky part.
All that the posted Java code really does (on top of calling the runtime to do the actual hashing) is to map the resulting hash (part of it, anyway) through a character lookup table.
edit — the lookup table built by that Java code is an array with "$", the digits, the upper-case letters, the lower-case letters, and then (surprisingly) "£". (The last character is surprising because it's not an old-school 7-bit ASCII character code, but whatever.) In JavaScript, that's:
var codes = "$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz£";
The Java code then takes each 8-bit byte produced by the hash algorithm and looks up a code character by adding 128 to the byte and then dividing by 4. Java bytes are treated as signed values, so that has the effect of mapping every byte into the range 0 ... 63. That value is then used as a lookup into the code array.
Thus if you have a JavaScript MD5 facility that can give you back an array of numbers in the range -128 ... 127 (that is, signed 8-bit values), you could translate the result through the code array like this:
var digest = MagicJavaScriptMD5(source);
var result = [];
for (var i = 0; i < digest.length; ++i)
result.push(codes.charAt(~~((digest[i] + 128) / 4)));
var resultString = result.join('');
EDIT by the OP:
I take the liberty of posting here the right solution, that is highly derived from #Pointy's one. It requires md5.js from http://pajhome.org.uk/crypt/md5/.
/* MD5 in byte[] format */
function byteArray_md5(s) {
var output = [];
var input = rstr_md5(str2rstr_utf8(s)); //here it uses md5.js
for(var i = 0; i < input.length; i++)
output[i] = input.charCodeAt(i);
return output;
}
/* MD5 with custom mapping.
* It's a normal MD5 with a final char mapping of the hash.
*/
function md5WithCustomMapping(source) {
var codes = "$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz£";
var digest = byteArray_md5(source);
var result = [];
for (var i = 0; i < digest.length; ++i)
result.push(
codes.charAt(
~~( ( digest[i] + 128 * (digest[i]<128 ? 1 : -1) )/4 )
)
);
return result.join('');
}

Categories

Resources