I'm connecting lamp using JDBC and I have the word LondonWeight as a password hashed using MD5 on a MySQL database. I then need to check an inputted password against the collection, i.e LondonWeight to check to see if they match. However the hashing in my Java code returns a different output for the word.
MySQL hash:
1274d1c52d7a5a9125bd64f1f9a26dce
Java hash:
132310771724320562704545645352563257040366
Here's my hash code:
private String hashPass(String pass) throws NoSuchAlgorithmException {
MessageDigest mdEnc = MessageDigest.getInstance("MD5");
mdEnc.update(pass.getBytes(), 0, pass.length());
String md5 = new BigInteger(1, mdEnc.digest()).toString(8); // Encrypted
return md5;
}
It definitely hashes the String entered in the text box as I have it printed to the terminal so I can check. Any idea why it gives a different output? I understand there a different ways to hash the bytes or something?
You're currently converting the hash into octal in Java, whereas the MySQL version is in hex.
That's the first problem, but also:
Your MySQL hash appears to be 33 characters, which is too much data for an MD5 hash in hex. There's something odd going on there.
I wouldn't use BigInteger to convert a byte array into hex anyway; that's not what it's there for. Use Apache Commons Codec or something designed for hex conversion. For example, that way you'll get appropriate leading zeroes which BigInteger may suppress
Your current code assumes a single byte per character
Your current code assumes that the default character encoding is appropriate; I would suggest always specifying an encoding in String.getBytes
Using MD5 for password hashing is weak; update to a more appropriate hash if you possibly can
Related
I have java three strings. let say example.
String test = "Hi, ";
String test1 = "this is ";
String test2 = "Java programming!";
I wanna combine those 3 string and change it to md5 format. How could I do? I use MessageDigest class for one string but i have no idea how to append 3 string before change to md5. And I wanna to change back md5 to string. Do i need external library.
Well reversing MD5 is not really feasible as -
There can be more than one string giving the same MD5 (It is called a Hash collision.)
It was designed to be hard to "reverse"
You would have seen lot of websites that provide reverse MD5 (as - Option-1 , option-2).
These websites stores mapping of already used "String and MD5" (So if you use complex String they wont be able to deduce original one).
Moving back to Part - 1
MessageDigest can be used to calculate MD5 of a given String in Java.
Its usage is fairly Simple -
String testString="someText";
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] messageDigest = md.digest(testString.getBytes());
BigInteger number = new BigInteger(1, messageDigest);
String hashtext = number.toString(16);
So in your problem it depends how you want to create hash -
Way 1 - As you asked we can have -
StringBuilder simpleString=new StringBuilder(test);
simpleString.append(test1);
simpleString.append(test2);
String testString=simpleString.toString();
And finally call the method defined above with input as - testString.
Way 2 - I will suggest you to use MD5 of MD5 to have secured checksum.
Output = MD5(MD5(test)+MD5(test1)+MD5(test2))
You can try creating a brute-force attack on a string of 3 characters. Assuming only English letters (A-Z, a-z) and numbers (0-9) are allowed, there are "only" 623 (238,328) combinations in this case.
Hope it helps. :)
MD5 is not a format, or an encryption algorithm.
MD5 is a hash function. That means, long text to short digest - for anything apart of very short inputs this transformation will obviously be lossy. In general, there is no going back from MD5 to plain text.
I am converting my password in Md5 , its working fine and giving me md5 converted password but i also want to have special characters in my md5 password.
how can i achieve this
public String createMd5(String password){
String salt = "Random$SaltValue#WithSpecialCharacters12#$#4&#%^$*";
String hash = md5(password + salt);
return hash;
}
public static String md5(String input) {
String md5 = null;
if(null == input) return null;
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(input.getBytes(), 0, input.length());
md5 = new BigInteger(1, digest.digest()).toString(32);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return md5;
}
md5() is a hash function that maps from any string to {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}^32.
You usually use it when you want to make sure that in case of a successful attack (this means the attacker could get your users data) the attacker does not have all users plaintext passwords (and hack e.g. their email accounds with this information).
You cannot get special characters out of md5() and it would not improve anything.
WARNING: MD5 should not be used anymore for hashing passwords as it is too fast to calculate (more information). Instead, you should use bcrypt with salt (example).
there is nothing like "md5 converted password" md5 generates checksum which you can not control.
I think this question stems from a misunderstanding of password hashing. Hashed passwords work like this:
A hash function is deterministic, that is, with the same input you always get the same output.
A good hash function is one-way, that is, you can't get from the hash value to the input without a lot of effort.
So take a password + salt (the salt makes creating an exhaustive dictionary MUCH harder)
Feed that into the hash function to generate a hash.
Store the hash and the salt.
To check passwords hash the user input and the stored salt and compare to the stored hash.
This operates on the byte level, so special characters are obviously included in the input. The output of the hash function is represented in hexadecimal for your convenience and does not contain special characters. If you do want the raw output just parse the hexadecimal representation into bytes but I don't see why you would want to, it's still the same number of output bits represented differently.
Another thing to note: MD5 is not a good hash function for passwords because it is much too fast. A really fast hash function is a hash function where trying a large amount of passwords from a generator is a trivial task. You might want to look for something more password specific for this use case.
I'm creating a simple web application and want to store hashed passwords into a database. I need the hash function for the authentication token too (concatenating the user name and the date and send them with their hash to the client as the token).
I've found that MessageDigest Java class can help me with this. Here is one link.
The basic idea goes like this:
public String digestString (String stringToHash) throws NoSuchAlgorithmException {
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
byte[] stringBytes = stringToHash.getBytes();
byte[] stringDigest = sha256.digest(stringBytes);
return new String(stringDigest);
}
What I don't get is:
In this code, how can I set the hash key? I need to be sure that the same key will be used in the verification process. How can I do that if I don't set the key?
BTW: I know I should add a salt (256 bytes in this case) to the hashed text before hashing it.
A hash uses no key. It's just a one-way algorithm. You give it something to digest, and it returns a hash. What it guarantees is that it's extremely hard to find the original input or any other input that leads to the same hash.
Your algorithm has two basic problems (besides the lack of salting):
it uses String.getBytes(), which relied on the default platform encoding, and thus differs from platform to platform. You should specify an encoding such as UTF-8.
it uses new String(byte[]), which has the same problem as above + an additional one: all the sequence of bytes are not valid character. To transform a purely binary byte array into a String, use a base64 encoding algorithm. apache commons codes has one.
MessageDigest m=MessageDigest.getInstance("MD5");
StringBuffer sb = new StringBuffer();
if(nodeName!=null) sb.append(nodeName);
if(nodeParentName!=null) sb.append(nodeParentName);
if(nodeParentFieldName!=null) sb.append(nodeParentFieldName);
if(nodeRelationName!=null) sb.append(nodeRelationName);
if(nodeViewName!=null) sb.append(nodeViewName);
if(treeName!=null) sb.append(treeName);
if(nodeValue!=null && nodeValue.trim().length()>0) sb.append(nodeValue);
if(considerParentHash) sb.append(parentHash);
m.update(sb.toString().getBytes("UTF-8"),0,sb.toString().length());
BigInteger i = new BigInteger(1,m.digest());
hash = String.format("%1$032X", i);
The idea behind these lines of code is that we append all the values of a class/model into a StringBuilder and then return the padded hash of that (the Java implementation returns md5 hashes that are lenght 30 or 31, so the last line formats the hash to be padded with 0s).
I can verify that this works, but I have a feeling it fails at one point (our application fails and I believe this to be the probable cause).
Can anyone see a reason why this wouldn't work? Are there any workarounds to make this code less prone to errors (e.g. removing the need for the strings to be UTF-8).
There are a few weird things in your code.
UTF-8 encoding of a character may use more than one byte. So you should not use the string length as final parameter to the update() call, but the length of the array of bytes that getBytes() actually returned. As suggested by PaĆlo, use the update() method which takes a single byte[] as parameter.
The output of MD5 is a sequence of 16 bytes with quite arbitrary values. If you interpret it as an integer (that's what you do with your call to BigInteger()), then you will get a numerical value which will be smaller than 2160, possibly much smaller. When converted back to hexadecimal digits, you may get 32, 31, 30... or less than 30 characters. Your usage of the the "%032X" format string left-pads with enough zeros, so your code works, but it is kind of indirect (the output of MD5 has never been an integer to begin with).
You assemble the hash input elements with raw concatenation. This may induce issues. For instance, if modeName is "foo" and modeParentName is "barqux", then the MD5 input will begin with (the UTF-8 encoding of) "foobarqux". If modeName is "foobar" and modeParentName is "qux", then the MD5 input will also begin with "foobarqux". You do not tell why you want to use a hash function, but usually, when one uses a hash function, it is to have a unique trace of some piece of data; two distinct data elements should yield distinct hash inputs.
When handling nodeValue, you call trim(), which means that this string could begin and/or end with whitespace, and you do not want to include that whitespace into the hash input -- but you do include it, since you append nodeValue and not nodeValue.trim().
If what you are trying to do has any relation to security then you should not use MD5, which is cryptographically broken. Use SHA-256 instead.
Hashing an XML element is normally done through canonicalization (which handles whitespace, attribute order, text representation, and so on). See this question on the topic of canonicalizing XML data with Java.
One possible problem is here:
m.update(sb.toString().getBytes("UTF-8"),0,sb.toString().length());
As said by Robing Green, the UTF-8 encoding can produce a byte[] which is longer than your original string (it will do this exactly when the String contains non-ASCII characters). In this case, you are only hashing the start of your String.
Better write it like this:
m.update(sb.toString().getBytes("UTF-8"));
Of course, this would not cause an exception, simply another hash than would be produced otherwise, if you have non-ASCII-characters in your string. You should try to brew your failure down to an SSCCE, like lesmana recommended.
I am trying to hash a password and save it in the database; I know hashing is a one way process. How can I check whether the user supplied password and the one stored in the database are same? I am using MD5 and I am getting different values for the same input when I perform hashing each time. Can anyone help?
String pass = "wor1ldcup";
String pass1 = "wor1ldcup";
DigestUtils du = new DigestUtils();
byte[] b = du.md5(pass);
byte[] b1 = du.md5(pass1);
The code you supplied is basically correct, with a couple of caveats:
The methods of DigestUtils are all static, and hence should be invoked as:
byte[] b = DigestUtils.md5(...);
and not as
DigestUtils du = new DigestUtils(); // wrong ... no need to instantiate
byte[] b = du.md5(...); // wrong ... never use an instance to
// call a static method.
You don't show how you compare the b and b1, but b == b1 won't work, and neither will b.equals(b2) ... both compare references. You need to call Arrays.equals(b, b1).
It is a bad idea to try to turn an MD5 hash into a String. Depending on the default character set, the conversion may turn out to be lossy; i.e. not reversible. If you want to store an MD5 hash in a database, it is better to encode as a String using (for example) base64 encoding, and save the encoded hash.
You really should use bcrypt instead of MD5 for password storage. Here is an article on why (there are many more).
The jBcrypt library works well.
Use:
import java.security.*;
byte[] password;
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(password, 0, password.length);
byte[] passwordHashed = messageDigest.digest();
Need to convert String to byte[] and byte[] to hex or Base64 String.
Here's a few things to check:
Are you comparing the hashes in the same case? i.e. are the alphabetic digits in the hashes in lowercase in both versions?
Is it possible that a leading 0 has been truncated from the front of one of the hashes?
Are you comparing two Strings using == ? Use .equals instead.
If all of those are ok, the hashing should return the same value each time for the exact same input.
At the most basic level, when using a hashing function for passwords you hash the password when initially storing it and then hash any attempts to match that original.
So, when you are trying to validate a password for an existing user your basic query would use the hashed version of the submitted password as a parameter.
SELECT * FROM Users where ID = 1234 and Password = #Password
binding #Password to du.md5(submittedPassword)