I am trying to do a project where I hashed the password and store hashed password in database.
Now I am facing problem in decrypting. How can I decrypt this pbkdf form of password? I am trying to do this in Java.
where I hashed the password and store hashed password in database.
Nice job! But, how did you accomplish this?
How can I decrypt this pbkdf form of password?
Impossible. That's the point.
There are only 2 operations a password hashing library should be exposing. Going back to the original question (HOW did you hash those passwords?), if the API of your library doesn't work like this, it's a crap library, find something else.
The 2 primitives are:
String encodeNewPassword(String password);
boolean verifyPassword(String passwordEnteredByUser, String thingThatEncodeNewPassReturned);
And the procedure is simply to invoke encodeNewPassword when you have a new password (a new account signup, or a user changed their password), take the string or byte[] or whatnot that this method returns, store the whole thing in a database someplace, and then retrieve that and pass it back when you need to verify later that the user entered 'their' password: You pass in the password the user just entered together with the thing you stored in the database and you get back a 'yes' or a 'no'.
The salt and hash are all baked into this one string.
At best, the createNewPassword call also lets you configure tolerances or difficulty (for example, if we're talking bcrypt, perhaps how many 'rounds' you want).
You didn't say which library you are using, but it is highly likely that it works as above (again, as I said, if it does not, get rid of it, it is bad), so go hunt for 'the other method', the one that takes in both a password as entered by a user and the string that you got before and returns a boolean to indicate whether it's right or it is wrong.
Note that this method, internally, is not decrypting anything. It's salt/hashing the entered password in the same way and is checking if the same hash comes out. If they are equal, the user entered the same password as they did before.
Hashing is a one way function, decrypting of hash is not possible. You can compare the text by hashing and then compare the hash in database if it is original or not.
To check logins, you hash the user input and compare it with the hashed password.
If your hash is not repeatable (same hash for same string) then you're doing it wrong - i.e., you chose the wrong hashing method.
For salted hashes, you need to store the salt with the hashed password, and use the same salt to hash the user input you're checking.
PBKDF is not encryption. As the same suggests it's a password based key derivation function. It's a hash but purposely slow. Short answer: you can't. The whole idea of PBKDF is to make it hard to find a collision. Even if you knew how many rounds were used, it would still take too much time to get a collision
Related
I have made a log-in screen and want to check the password that a client enters with passwords in a server's database. If their HashCodes match, the password is accepted. However, the HashCode I get when I write a password on the client screen is different to the HashCode of the received string (password) on the server side.
Does anybody know why? Thanks in advance for any insight.
You've misunderstood.
You should be using a secure hash, not thehashCode() method.
You must not store the plaintext password in the database. You must store the hash.
You should be getting the database to do the hashing and comparison:
SELECT COUNT(*) FROM USERS WHERE USERNAME = ? AND PASSWORD = MD5(?)
If this query returns 1, the user and password exist. If it returns zero, they don't. Note also that you don't want to distinguish between wrong username and wrong password, as this is an information leak to the attacker. Test them both together as above.
#EJP has pointed out (correctly) that you should be using a secure hash function not Java hashCode for this.
However, the HashCode I get when I write a password on the client screen is different to the HashCode of the received string (password) on the server side.
That is a puzzle. If you are using String.hashCode() the only possible explanation is that you are hashing different strings; e.g. there could be leading / trailing white-space in one and not the other, or maybe one was hashed with a "seed" added to it. I guess, another possible explanation could be that you are hashing a StringBuffer, StringBuilder, char[] or something else.
I am new to all the encryption, hashing etc.
I received email from my dba, telling me to read admin un, password from .properties file and it looks something like this:
ldap.provider.admin.password=fc34f78f665b60c5b99bad0ee1b228269e10e9cdd81c1a
Then in his email he specifies:
ldap.provider.admin.password is actual password encrypted with “SHA256”.
Telling me in my java programm I will have to decrypt this password in order to be able to use it.
Is it me or does he have it confused with crypto hash algorithm?
Can I actually get it decrypted?
"Encrypted" is a misleading term, because that implies that it can be decrypted. Something transformed with the "SHA256" algorithm is actually cryptographically hashed. There is no "decrypt" functionality for a cryptographic hashing algorithm.
But you can still use it. When a user submits a password, perform "SHA256" on the user's submitted password, and compare it with the stored, hashed password. By the looks of the string above, you may need to convert the hash output to a hex string to compare it.
Additionally, you may first need to find out if a salt is applied to the hash (additional random content added on a per-user basis to increase security). If so, then you'll need to apply the salt to the user's submitted password before hashing it.
I have a database where one of the column(password) datatype is Binary(60).
I am using password as STRING in java and trying to compare the password coming from java (from user interface) with the password (as binary) in MySQL.
But it never gives me any result ..
Please guide what datatype/value will be able to compare with the Binary type
thanks
Having the database field be configured as a binary string is maybe not ideal, but not a problem either.
The problem is however, that you intend to store the password in there directly. Please do not do this, as it will create a major security flaw.
Hashing it as suggested in another answer is better, but still not really good. The problem with that is, that there are so-called rainbow tables which can be used reverse-lookup hashes to their original value.
The minimum you need to do is use a salted hash (https://en.wikipedia.org/wiki/Salt_(cryptography)) or even better, use something like bcrypt or PBKDF2 (see Password Verification with PBKDF2 in Java) to create a secure hash of the user provided password. These hashes will have fixed lengths and can easily be stored as a binary string in your given database field.
When checking the user entry, just perform the same function again and compare that with the database content. Of course, you must use SSL to transfer the password from client to server.
I'm confused as to why you've used the binary type, but you can try:
String password = "a password";
// Run password through cryptographic functions.
String binaryStr = "";
for(char c : password)
{
int charInt = (int)c;
// Convert the character to it's integer representation.
binaryStr += Integer.toBinaryString(charInt);
// Convert that integer into a binary string.
}
The BINARY and VARBINARY types are similar to CHAR and VARCHAR, except that they contain binary strings rather than nonbinary strings.
Following the documentation, you can simply compare this new binary value you've generated with the value in the table.
HOWEVER, keep in mind that this is a really bizarre way of storing the password, and it makes much more sense just to store the message digest (given that storing it in binary form offers 0 additional security).
You should set your field as PASSWORD in MySQL instead. Like that the password will be hashed in MD5 whenever you save your password in the db. To make a comparison when a user logs in, you just hash your user given password to MD5 and do a string compare on the password which is stored in the DB.
I'm trying to determine the best way to implement password validation in Java. The password is stored as text in an SQL database.
Should I:
Query for password based on user name and validate it within Java app? (SELECT password FROM users WHERE username = 'foo')
Query for row based on user name + password input? (SELECT true FROM users WHERE username='foo' and password='bar')
Something else entirely...
If the answer is #1, what is the correct way to get the password hash into Java? I know that passwords should be stored as a char[] instead of a String to avoid leaving a copy in memory, but is it ok to retrieve it from the result set using ResultSet.getString("password")? Wouldn't that create a String constant and be a security risk (even if hashed)? The other option I see would be to store/convert the password to an array within SQL and then use ResultSet.getArray() to retrieve it, but that seems a little excessive unless absolutely necessary.
Edit:
Ok, maybe I made a mistake by using the word TEXT in the same post as PASSWORD, but I was referring to the data type, not saying that I'm saving the passwords in plain-text. In fact, I clearly asked "what is the correct way to get the password hash into Java". Please stick to the question that I asked if you want to be helpful.
Hash your passwords. Than you can compare hashes.
SELECT username FROM user WHERE username=username and password_hash=password_hash;
How can I hash a password in Java?
byte[] salt = new byte[16];
random.nextBytes(salt);
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 2048, 160);
SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = f.generateSecret(spec).getEncoded();
System.out.println("salt: " + new BigInteger(1, salt).toString(16));
System.out.println("hash: " + new BigInteger(1, hash).toString(16));
Both your methods are bad, since password is transmitting in plain text outside an application, probably by network. But the second method is slightly better since some transmitting passwords will be sometimes wrong.
Use some sort of hashing. Hash password then store it into database. Hash entered password too and compare hashes. Hashing is irreversible data transformation. Use MessageDigest class http://docs.oracle.com/javase/6/docs/api/java/security/MessageDigest.html to create hashes in Java. Use one your database knows.
Option 3: completely different.
Step 1:
SELECT passwordHASH from users WHERE username=? (note the placeholder to avoid SQL injection attacks - check your API on how to use placeholders)
Step 2: extract salt from the password hash.
Step 3: use the salt to compute the hash from the plain text received from the user
Step 4: compare existing passwordHash with the newly computed passwordHash.
Seriously: read up on salted password hashes. This is the only proper way of storing passwords. And the best is, it already exists. Don't even try to reinvent this wheel, unless you are a cryptography genius (and then you should know better).
Don't leave away the hash. It prevents two users from having the same hash when they just happen to choose the same password. Plus, it largely avoids dictionary attacks such as rainbow tables.
I have used MD5 for password encryption and stored encrypted format password in database. Now I want to rehash it. How can I do this?
I assume you want to change/upgrade the hashing algorithm used in your database.
Technically it's not possible to do that, if you only have the hash result of the old system.
But you can create a new hash value each time a user successfully logs in using his password: in this case you first use the normal procedure to check for correctness (hash the input, compare that with the stored hash) and if that's correct, hash the entered password with the new system (preferably with a good salt and using a good hashing algorithm, it's probably best to use bcrypt) and store that as the new hash.
You dont re-hash the password.
You take the password entered from the logon screen and hash it the same way the stored password was hashed and then compare the two hashed values. If they match the passwords are the same.
You can't do that. Hashing is one-way, you can't get the original password from a hash and then rehash it.