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!
Related
The H2 HASH function returns bytes, and SELECT HASH('MD5', 'test') AS new_id FROM my_table; displays a text value:
098f6bcd4621d373cade4e832627b4f6
How to retrieve that same text value in Java? Using ResultSet.getBytes("new_id") gives the object's address, something like [B#48f278eb. Feeding that through new String(ResultSet.getBytes("new_id"), StandardCharsets.UTF_8) gives gobbledygook: �Oh�؆nr�Mz��.
The reason you see [B#48f278eb is because the resulting MD5 hash is in bytes in a non-string format.
Here is a complete example of generating the MD5 hash and converting the resulting bytes to a string by using a StringBuilder and formatting it String.format("%02x", b):
String text = "test";
//Generate MD5 hash
byte[] bytesOfMessage = text.getBytes("UTF-8");
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] arr = md.digest(bytesOfMessage);
//Convert the bytes to a string
StringBuilder strBuilder = new StringBuilder();
for(byte b:arr){
strBuilder.append(String.format("%02x", b));
}
//The complete string
String strHash = strBuilder.toString();
//Print or use the string
System.out.println("The MD of " + text + " is " + strHash);
And the output is as expected:
The MD of test is 098f6bcd4621d373cade4e832627b4f6
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");
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.
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.
I'm trying to create a PHP version of an existing JSP program, however I'm stuck at the password encryption part.
Could you please tell me how to convert this one? I know it tries to get the md5() but after that, I don't get it. I get lost in the Stringbuffer and for() parts.
Can you help me out?
public static String encryptPassword( String password )
{
String encrypted = "";
try
{
MessageDigest digest = MessageDigest.getInstance( "MD5" );
byte[] passwordBytes = password.getBytes( );
digest.reset( );
digest.update( passwordBytes );
byte[] message = digest.digest( );
StringBuffer hexString = new StringBuffer();
for ( int i=0; i < message.length; i++)
{
hexString.append( Integer.toHexString(
0xFF & message[ i ] ) );
}
encrypted = hexString.toString();
}
catch( Exception e ) { }
return encrypted;
}
Iraklis should be right. md5() gives you a hex-encoded output string by default. You only get the unencoded bytes like in Java by passing in TRUE for the optional $raw_output argument.
the lengths range from 29 to 32
Then your Java code has a bug. MD5 hashes are always 128 bits (32 hex digits). Here it is:
hexString.append( Integer.toHexString(0xFF & message[ i ] ) );
this will generate 1 instead of 01 for all bytes below 16. What you have stored is a mangled hash, from which you cannot recover the original MD5 value. If you absolutely must keep this broken data, you will have to reproduce the bug in PHP:
function makeBrokenMD5($s) {
$hash= md5($s, TRUE);
$bytes= preg_split('//', $hash, -1, PREG_SPLIT_NO_EMPTY);
$broken= '';
foreach ($bytes as $byte)
$broken.= dechex(ord($byte));
return $broken;
}
It converts the MD5 hash to a string hexadecimal numbers of the least significan byte of the character. In Java all chars are 2 bytes.
In practice this means just the ASCII value.
<?php
$password = "MyPass";
$hash = md5($password);
?>
UPDATE:
There are some discrepancies between the two versions. To fix this see #bobince answer.Here is the test code:
Java
package tests;
import java.security.MessageDigest;
/**
* Created by IntelliJ IDEA.
* User: Iraklis
* Date: 2 Ιουν 2010
* Time: 2:15:03 μμ
* To change this template use File | Settings | File Templates.
*/
public class Md5Test {
public static String encryptPassword(String password) {
String encrypted = "";
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] passwordBytes = password.getBytes();
digest.reset();
digest.update(passwordBytes);
byte[] message = digest.digest();
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < message.length; i++) {
hexString.append(Integer.toHexString(
0xFF & message[i]));
}
encrypted = hexString.toString();
}
catch (Exception e) {
}
return encrypted;
}
public static void main(String[] args) {
System.out.println("Pass1 md5 = " + encryptPassword("Test123FORXTREMEpass"));
System.out.println("Pass1 md5 = " + encryptPassword("Ijdsaoijds"));
System.out.println("Pass1 md5 = " + encryptPassword("a"));
System.out.println("Pass1 md5 = " + encryptPassword(" "));
}
}
Output:
Pass1 md5 = dc3a7b42a97a3598105936ef22ad2c1
Pass1 md5 = df7ca542bdbf7c4b8776cb21c45e7eef
Pass1 md5 = cc175b9c0f1b6a831c399e269772661
Pass1 md5 = 7215ee9c7d9dc229d2921a40e899ec5f
PHP
<?php
echo "Pass1 md5 = ".md5("Test123FORXTREMEpass")."<BR>";
echo "Pass2 md5 = ".md5("Ijdsaoijds")."<BR>";
echo "Pass3 md5 = ".md5("a")."<BR>";
echo "Pass4 md5 = ".md5(" ")."<BR>";
?>
output:
Pass1 md5 = dc3a7b42a97a35981059036ef22ad2c1
Pass2 md5 = df7ca542bdbf7c4b8776cb21c45e7eef
Pass3 md5 = 0cc175b9c0f1b6a831c399e269772661
Pass4 md5 = 7215ee9c7d9dc229d2921a40e899ec5f
To get the same results in both java and php I used this.
Java(make sure to call the method inside a "try" block):
public static String getHash(String pass) throws Exception
{
MessageDigest md=MessageDigest.getInstance("MD5");
md.update(pass.getBytes(),0,pass.length());
return new BigInteger(1,md.digest()).toString(16);
}
PHP:
<?php
echo md5(pass);
?>
Hope this helps
Edit: If the java variant returns 31 characters, adds a "0" in front of the string to match the php hash which returns 32 characters.