I have an issue with the #Formula annotation in Hibernate when I'm trying to decrypt a password column (PWD_COL) using a key (which is retrieved from a properties file)
The code:
#Formula("decrypt(PWD_COL, '" + MyKeys.DECRYPT_KEY + "')")
private String myPwd;
I am trying to get the DECRYPT_KEY from another property file.
I am getting an error:
The value for annotation attribute Formula.value must be a constant
expression
Alternately, is there a way to mimic the SQL decrypt function in Java?
Note: Please read the password field as just another value. The eventual purpose of this exercise is for something far less important but nevertheless needs to be encrypted.
I know that this is not what you are looking for but let me give you a advice about store password on database, maybe you should change your mindset about how to work with passwords.
You should not decrypt passwords on database because security reasons, so if someone lost password they should create a new one.
To validate login and related tasks you should take the password from the form, encrypt it and compare with the encrypted on in database.
If you really want to keep doing in this way use #formula with valid sql values.
The value of a #Formula annotation has to be valid SQL since it is passed more or less directly to the underlying DB.
This also explains why your idea won't work - the DB will have no notion of the MyKeys class.
You could insert the key in a DB table and select it from there in the #Formula but security-wise that might not be a particularly sane idea...
What you really should be doing (or actually not doing) is to avoid storing passwords, but rather store hashes of passwords and then compare those hashes with the hash of whatever credentials your user presents. That moves encryption/hashing to Java/memory and avoids the embarassment when somebody steals your database, guesses the weak password or bruteforces the encryption and posts it all on pastebin!
Cheers,
Related
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
I am creating a user table where in I need to store the password in
an encrypted format.I need to know what datatype can be used to
create a column which accepts the encrypted password.Basically I don't
need any function to encrypt the password.This has to be taken care
when we create the table itself.
As per this link
https://oracle-base.com/articles/9i/storing-passwords-in-the-database-9i
Varchar is sufficient for it.Please let me know any other datatypes
that can hold the encripted password.
Database: Oracle 11g.
TIA
Pradeep
I strongly suggest not to store the password in any encrypted format. Rather, create some kind of hash value from the password, and store this value instead. This way the password can not be de-crypted, but you are still able to verify the password by generating the hash for the entered string and comparing it with the stored hash value. Just search for password hashing methods, you will find the best for yourself. Then the hash value can be stored in a simple VARCHAR field, nobody will be able to use it as a password.
I'm creating a table for users containing their hashed passwords and it's salt.
The issue is that when I create the user's row in the table and save the salt and password (both are byte[] stored in VARBINARY columns) and try to get that data back when the user logs back in, the returned salt and hashed password is different than it was when I created the row.
To get the data I am using ResultSet and I call resultSet.getBytes("password")
To create the row I use a query like this (removed other column data to make it simpler):
String query = String.format("insert into users (`password`, `salt`) values ('%s','%s');", user.getHashedPassword(), user.getSalt());
Could there be some conversion or something that is happening that causes this problem? Should I be using something other than VARBINARY for storing byte[]?
Could there be some conversion or something that is happening that causes this problem?
Yes. You're basically calling toString() on a byte array. That isn't going to do what you want. Did you look at the SQL you were executing?
More than that, you shouldn't be producing a SQL string like this anyway - it's an approach which is vulnerable to SQL Injection Attacks as well as conversion issues.
Instead, use a PreparedStatement with parameterized SQL, and specify the parameter values directly (PreparedStatement.setBytes etc).
More broadly than that, it would be a good idea not to roll your own authentication code at all - look for an existing library that fits in well with whatever framework you're using, that's likely to avoid any of the numerous security vulnerabilities that it's all too easy to create when doing it yourself.
I am looking for mechanism to generate random unique alpha numeric key for resetting user password.
I've goggled a lot in this direction, but looks like this thing is not obvious thing.
I've tried something like that:
new String(encodeBase64URLSafe(UUID.randomUUID()));
But after reading the following article: Is UUID.randomUUID() suitable for use as a one-time password? looks like that this way is not fully correct.
It would be really appreciate if you answer on the following questions:
Which is secure way to generate such token using UUID?
Do we need to convert UUID string to base64 in order to have safe URLs or it would be enough to remove dashes from generated string?
Would be it correct to use mechanism from this link in such purpouses How to generate a random alpha-numeric string?, why?
Using an UUID is safe and secure. The linked article just says that an UUID is maybe a little too much for this kind of security. But well ... if you are "too" secure, no one will blame you.
An UUID is just alpha numeric characters and dashes. So if you need to put it in a query string or an URL, you have nothing to escape. You can remove the dashes to save some space if you want. But it is not required.
This mechanism is secure too. Both (UUID and this one) will works.
For this kind of security, all you have to do is to ensure that your token is randomly generated (even partially).
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.