Convert password hashing from SHA to bcrypt - grails

This questions has been answered in this Stack Overflow question already, but it's not Grails-specific and is also kind of vague.
I set my Grails app up with Spring Security, but apparently didn't get the newest version, because it defaulted to SHA-256 instead of bcrypt. Now I have production data with passwords hashed in what seems to be a less-than-ideal method.
It's a piece of cake to enable bcrypt hashing:
Config.groovy > grails.plugins.springsecurity.password.algorithm = 'bcrypt'
but now I need the app to convert the old hashes into new ones. Fundamentally, I understand that when a user logs in, I should have the app check to see if the password is an SHA-256 hash, and if so, re-hash the entered password with bcrypt. After a while, they'll all be upgraded and that code can be removed.
What is the actual code for determining if a password hash is from SHA-256 or bcrypt, though?
EDIT
That is to say, what is the actual function that I call to get a hash? How do I bcrypt(incomingpassword) to see if it matches the existing password hash?

bcrypt passwords will start with "$2a$10$" and be 60 chars long. There is no pattern for SHA-256, but it will be 64 chars long.

Related

Is Rails Devise gem truncating passwords?

OWASP ASVS Standards
I am testing a web app against OWASP standards:
2.1.3 Verify that password truncation is not performed. However, consecutive multiple spaces may be replaced by a single space
We are using Rails, along with Devise gem for authentication. While testing whether we meet the requirements of 2.1.3, I noticed that longer passwords are truncated.
I can set the following password:
NVjEuRjiFcDGYfhm9kh9pTxUvHwKyTpNMhXqwDBHoaU3cHKv2guZJTwrUZyNN9GiJ4B8TjtiWpCWZXVsRoXmhXKEtzqJr7qnngQlfldlfdlE (108 chars)
I can sign in with the above password fine. I can also sign in with this truncated version of it, though:
NVjEuRjiFcDGYfhm9kh9pTxUvHwKyTpNMhXqwDBHoaU3cHKv2guZJTwrUZyNN9GiJ4B8Tjti
Beyond those 72 chars, I can add or remove characters, or just lop them all off, and I can still sign in. I only need the first 72 chars to be correct, the rest appears to get ignored. I haven't checked yet, but different characters might require more storage, and could shorten the length required for authentication.
Looking in the db, I can see the field is varchar(128) - 128 being the maximum length, going by OWASP:
2.1.2 Verify that passwords 64 characters or longer are permitted but may be no longer than 128 characters.
I assumed the user entered password should be up to 128 chars, but it seems the field only stores 128 chars, and 29 of them are being used by Devise for the salt. How Devise Encrypts Passwords
I have only a vague understanding of how hashing/encrypting work - I understand the encrypted password length is not necessarily the same as the user entered password length. But since my password is being truncated, it seems like Devise didn't leave enough room for a user entered password to be 128 chars.
Am I mis-reading the OWASP standards, or is this a flaw in Devise, or am I missing something?
As the article you linked to states, Devise defaults to using bcrypt to encrypt your password. It's the bcrypt algorithm that has the limitation. See:
https://en.wikipedia.org/wiki/Bcrypt#Maximum_password_length
https://security.stackexchange.com/questions/39849/does-bcrypt-have-a-maximum-password-length
I think you could say this is flaw in that devise should handle this case better. You could also see it as a known limitation of the default devise condfiguration.
If you are going to use devise with bcrypt, I think you need to validate that passwords are within this limit. It's not uncommon to see this kind of limit in web registration forms. In the devise initializer, I see an option to change the encryption algorithm. I haven't done it myself, but I think if you wanted to exceed the limitations of bcrypt, the way to do it would be to pick a different algorithm.

Set password for user automatically - without Devise

I'm beginner with Rails 5, i would appreciate your help.
I have an user model, where obviously save a password for the user for a possible login.
The thing is i want to set the password automatically based on a text_field called identification_number.
Everything I've read is about doing it with Devise gem, but I'm not using it and also don't want to.
Once again, thanks for your help.
The password field is just another string field called :identification_number for your case.
But, saving password in the DB as plain strings is highly unrecommended.
There are a lot of security issues if you save the passwords as plain strings on your database.
Some of them are that:
You have full access on the passwords of your users
If someone, somehow manages to access your database they will also have full access to the passwords of your users.
In order to avoid these issues, most of the applications save the password strings as encrypted strings with some kind of salt for enhanced entropy.
With a quick google search I found some relevant blog posts that can help you build the password encryption from scratch, such as:
Without using a gem:
https://www.sitepoint.com/rails-userpassword-authentication-from-scratch-part-i/
Using some gems:
http://railscasts.com/episodes/250-authentication-from-scratch?view=asciicast
Apart from that, the password is not an identification_number. I would not use that name. The password is not used to identify the user. The id is most of the time the identification number. Better just call it :password. Also, it does not need to be a text field, it shouldn't be that long.
You can use bcrypt gem for implementing the secure password.
The bcrypt ruby gem provides you with has_secure_password method. The has_secure_password method encrypts passwords by hashing and salting the passwords and generate ‘password_digest’.
you can refer this link for more info

migrate ruby on rails salted bcrypt to md5

I'm trying to migrate a ruby on rails app to django, and got stuck with the fact that the RoR app is encrypting the user passwords in 2 feilds, crypted_password and password_salt, in addition the persistence_toke, so is there any play around to replace this with just a simple md5 hashed passwords without resetting the passwords of all users?
You need the password in plain text to store it hashed (with MD5 or any other algorithm). That said: You would need to restore the user's password from the current bcrypted version. And to avoid the possibility of a decryption is exactly the reason why bcrypt exists.
Therefore that answer is: No, you cannot do that without your user's help.
Btw MD5 is considered unsecure. You should try hard to get the bcrypt version working with Django.

How devise stores and read salts/hashes?

How does it work, that devise knows salts for encrypted passwords? Where does it store these hashes and how is that safe?
This is one of the main files for creating passwords: Devise::DatabaseAuthenticatable
Salt is not stored in the database, it is a string generated by this C program that is run by the BCrypt::Engine.generate_salt() function __bc_salt:
prefix = "$2a$05$CCCCCCCCCCCCCCCCCCCCC.E5YPO9kmyuRGyh0XouQYb4YMJKvyOeW"
__bc_salt(prefix, cost, OpenSSL::Random.random_bytes(MAX_SALT_LENGTH))
This can be found here:
BCrypt::Engine
With some other interesting code here: BCrypt::Password
From what I can gather though, the salt itself is the 29 characters that appear after the third $ in the encrypted password. This alone cannot tell you the password though, since you also need to know the pepper which is based on your apps secret key (usually stored in your /config/initializers/secret_token.rb)
Conclusion: In order to decrypt a password, one would have to be using the right version of BCrypt, have obtained the secret token from the app, and have the encrypted password, and I think that at that point, user passwords are probably the least of your security concerns, so I think its pretty safe.

Move database with bcrypt password field

I have a postgres database running at heroku. In the database I store passwords using bcrypt. The app is a Ruby on Rails 3 app using custom authorization. The authorization is using the rails method has_secure_password for the passwords.
I have planned to move my app to a VPS instead.
Will all my users passwords still be working after moving the database? I'm asking this because I'm not sure how the passwords are salted. Is the method used to crypt the passwords not tied to the database server in any way?
Source - bcrypt-ruby
"Hash algorithms take a chunk of data (e.g., your user‘s password) and
create a "digital fingerprint," or hash, of it. Because this process
is not reversible, there‘s no way to go from the hash back to the
password."
Assuming your storing a password hash and salt as a string then you will be able to store this in any data store. Take a look in db/schema and you will probably find that you are doing this.

Resources