I'd like to generate a series of usernames/passwords to be used with JHipster's Spring Security. My plan was to insert these into src/main/resources/config/liquibase/users.csv but I'm having trouble generating the encrypted password to go into this file.
I expected to be able to do something like this:
def encoder = new BCryptPasswordEncoder()
println encoder.encode('admin')
but the produced String ("$2a$10$icbkSBY4H/ub8pKAcnYhjeCit3A6e8JszUVZfu74sG6qqrSoT9CYW") does not match the known value in the default users.csv file ($2a$10$gSAhZrxMllrbgj/kkK9UceBPpChGWJA7SYIb1Mqo.n5aNLq1/oRrC).
Can someone please explain what I'm missing here?
Thanks!
--john
That's ok. BCrypt generates a new hash each time, because a part of this string is a random salt. Bcrypt encoder can compare such hashes, because it knows where to get salt and actual hash, so it can encrypt password using this salt and compare result with actual hash.
Your $2a$10$icbkSBY4H/ub8pKAcnYhjeCit3A6e8JszUVZfu74sG6qqrSoT9CYW contains:
icbkSBY4H/ub8pKAcnYhje as salt
IjZAgcfl7p92ldGxad68LJZdL17lhWy as hash
So first of all, it's ok to get different encrypted passwords each time even for same raw password. Second, you don't need to compare it manually, use PasswordEncoder.matches
You can also use any online BCrypt password encoder, instead of writing code for this. There're plenty of them.
See also: https://en.wikipedia.org/wiki/Bcrypt
Related
How can I parse a hash in ROR?
I have a hash in string format(enclosed by double quotes) and i need to parse them to a valid hash.
eg.
input_hash = "{"name" => "john"}"
desired
output_hash = {"name" => "john"}
This is the wrong approach. String representation of a ruby hash is not a good way to serialise data. It is well structured, and definitely possible to get it back to a ruby hash (eval), but it's extremely dangerous and can give an attacker who has control over the input string full control over your system.
Approach the problem from a different angle. Look for where the string gets stored and change the code there instead. Store it for example as JSON. Then it can easily and safely be parsed back to a hash and can also be sent to systems running on something that is not ruby.
I recently started getting BCrypt "invalid hash" errors when I tried to save a record with a password, so I looked into the BCrypt code, and found the following method for validating passwords:
def valid_hash?(h)
h =~ /^\$[0-9a-z]{2}\$[0-9]{2}\$[A-Za-z0-9\.\/]{53}$/
end
which is called by the initialize method:
def initialize(raw_hash)
if valid_hash?(raw_hash)
self.replace(raw_hash)
#version, #cost, #salt, #checksum = split_hash(self)
else
raise Errors::InvalidHash.new("invalid hash")
end
end
The following passwords:
"PassiveForbearenceFox"
"VindictivePurpleAlligator12345"
"LostBlueLizard!##$1234"
all return "Invalid Hash" errors.
I dug deeper, and found that the regex is checking the hashed password, but the hash that is getting passed has a stream of /x00s after it.
For example, if I use the password "LostBlueLizard!##1234", the hash that is passed to challenge the regex is:
"$2a$11$NcmldbbyCDfumGYALgYhfuIQt2FZ8gpbVCQfuiVlwjhCtkD2ndDFy\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\...
and so on, for farther than I could scroll.
If I remove the \x00s and pass in $2a$11$NcmldbbyCDfumGYALgYhfuIQt2FZ8gpbVCQfuiVlwjhCtkD2ndDFy, it passes the regex.
Why does the hash have those characters? I can't prove they weren't there before, but my passwords were always accepted until recently.
Also, it's actually the raw_hash that's getting input into the initialize method that's the hash with all the \x00s. So somewhere there's code that generates the faulty hash and passes it to initialize, but I searched the entire gem's codebase for the term "initialize" and there were no results like that, so I can't find where the hash is actually generated.
I tracked the issue further, to the BCrypt::Engine.create method, which calls __bc_crypt, which is what returns the faulty hash. __bc_crypt is actually from the C source file ext/mri/bcrypt_ext.c, which is beyond my ability to investigate.
I updated BCrypt from 3.1.11 to 3.1.13, and now it works fine. I'm not sure whether it was a bug or not, but the point is it works now.
It does not mean the Bcrypt's valid_hash? method is wrong, it means that the password stored, that one is invalid or nil which does not match the valid hash system
you may have to add
has_secure_password
if that one is not there and check the password_digest field after that.
Does ActiveSupport::MessageEncryptor support deterministic encryption so that we get the same encrypted value every time we encrypt a particular string? If not, are there any other Ruby libs that support deterministic encryption?
My goal is to get same encrypted value every time I encrypt a string and I should be able to decrypt it to original value as well.
Thanks.
You get different crypts because ActiveSupport::MessageEncryptor uses OpenSSL for encryption which requires an iv by default to prevent attackers from inferring relationships between segments of the encrypted message. I would highly recommend you to not mess around with that because you open ways for attackers to infer the encryption key.
However if you still want to do that take a look into the OpenSSL documentation of ruby. There should be a way to encrypt without vector.
Because it's a high security risk I don't add code to the answer to protect others from unnecessary loop holes.
I did not get why ActiveSupport:MessageEncryptor didn't work.
Here is another way to do it.
require 'bcrypt'
encrypted_password = BCrypt::Engine.hash_secret('password#!2#4', 'ADD SALT HERE')
you can also use it like this:
class User
SALT = 'GENERATE A STATIC SALT HERE AND KEEP IT SECURE'.freeze
include BCrypt
def password=(given_password)
#encrypted_password = Engine.hash_secret(given_password, SALT)
end
end
For the full documentation please check their repo
PS: using a static salt for all users for authentication is a bad idea.
Of course: one just need to use the same key to get the same encryption
x = ActiveSupport::MessageEncryptor.new('12345678901234567890123456789012').encrypt_and_sign('foo')
=> "bXJmRUczdjVXRFdLTitUcmkvRnk1UT09LS0vb2ZYdDRybGdWbmNXMUI1VDNnQzVBPT0=--13232bbe31d966f7d1df3aaa6fcc1cdc9eea60a1"
ActiveSupport::MessageEncryptor.new('12345678901234567890123456789012').decrypt_and_verify(x)
=> "foo"
It's hard to tell why you get different results since you didn't post any code...
I'm trying to use simple authentication for some post's comments.
Users type comment with instant id and password
and i use 'bcrypt' gem to store password in Database.
Like this in comments_controller.rb
#comment = Comment.new(comment_params)
bcrypted_pwd = BCrypt::Password.create(#comment.user_pwd)
#comment.user_pwd = bcrypted_pwd
and i use data-confirm-modal gem to confirm with data when user want to delete their comments
In this part, i have to decrypt user input password to compare with encrypted password in Database
how can i decrypt password and is there any good way to done this?
ency_pass = BCrypt::Password.create("testing")
new_pass = "testing"
Let’s look at how we compare two bcrypt hashes, one coming from the database & one from user input (like a form or something like that).
BCrypt::Password.new(ency_pass) == new_pass
# true
BCrypt::Password.new(ency_pass) == "testing2"
#false
The part on the left (BCrypt::Password.new) is a BCrypt object, which takes the hash stored in the database as a parameter.
The part on the right (new_pass) is just the plain-text password that the user is trying to log in with.
Let's understand this things:
BCrypt uses something called a “salt”, which is a random value used to increase security against pre-computed hashes. The salt is stored in the hash itself.
BCrypt defines its own == method, which knows how to extract that “salt” value so that it can take that into account when comparing the passwords.
BCrypt#== takes the “salt” value from the stored hash, then it hashes the plain-text password (the user input) using this salt so that both hashes will be identical if the password is valid.
If you were to look at the source code it would look something like this:
def ==(secret)
super(
BCrypt::Engine.hash_secret(secret, #salt)
)
end
Remember that super will call the same method (in this case ==) on the parent class. The parent class of BCrypt::Password is String.
how can i decrypt password and is there any good way to done this?
You can't. You can only decrypt something which is encrypted. Bcrypt is not an encryption algorithm, it is a hash algorithm. You cannot reverse a hash. It is provably impossible. (And the proof isn't even hard, it can be understood by a high schooler.)
just looking for some advise.
I have a website with around 2500 users - small but growing.
I built it with using SHA1 encryption on the passwords.
I've since read the SHA1 is insecure and would like to change to say SHA256 with a Salt.
Does anyone have any advice on how to make a transition like this?
Would be great if I could decrypt the passwords and just re-hash them but it doesn't appear doing able.
thx
Adam
The usual way of going about this is this:
Make the hashed-password column larger to accommodate a sha256 hash, and add a 'salt' column
Set the salt field to NULL initially, and adjust your password-check code so that a NULL salt means sha1, and non-NULL means sha256
Once a sha1-use has logged in successfully, re-hash the password to sha256 with salt, and update the database.
Over time, users will migrate to sha256 by themselves; the only problem are users who log in only very sporadically or not at all. For these, you may want to send a reminder e-mail, or even threaten to shut their account down if they don't log in before day X (don't give the actual reason though...)
Just to clarify, SHA is a hashing algorithm, which is (generally) a one way street. You can't decrypt hashes, which is kind of the strength of using them to authenticate passwords. You're on the right track with moving to a salted hash, and here's how I would do it.
The only way you're getting passwords is to let the user type it in themselves. As users visit your site and log in, update the passwords one by one. In your authentication method, I would perform the hash you're doing now, and compare it against what's in the existing field (nothing new here). Assuming it matches, go ahead and salt / re-hash using SHA256, and update the password field in the database. If you want, keep a bit in your user table tracking which users have been updated.
I'm making a lot of assumptions, but this is how I've solved the hash algorithm dance in the past. Good luck!
I have another suggestion to migrate your password hash from SHA1 to SHA256 immediately without waiting for user to visit the site again to rehash the password. The change will be one time password hash migration and change to your logon validation function.
Suppose your password hash are generated using the function: password + salt [Sha1]-> Hash-sha1
To migrate to Sha256, you may convert your password hash using the following algorithm:
Hash-sha1 + salt [Sha256]-> Hash-sha256 (The salt is used to increase the complexity of input.)
Depending on the acceptable value of your sha256 function, you can consider to encode the Hash-sha1 to base64 for printable ascii.
For your logon validation function, the password should be hashed using the following algorithm:
Password + salt [sha1] -> hash-sha1 + salt [sha 256] -> hash-sha256
The disadvantage is hashed twice (use some CPU time) but simplify the migration and better security.
Switching to SHA256 will hardly make your website more secure.
SHA1 and SH512 are message digests, they were never meant to be password-hashing (or key-derivation) functions. (Although a message digest could be used a building block for a KDF, such as in PBKDF2 with HMAC-SHA1.)
A password-hashing function should defend against dictionary attacks and rainbow tables.
Currently, the only standard (as in sanctioned by NIST) password-hashing or key-derivation function is PBKDF2. Better choices, if using a standard is not required, are bcrypt and the newer scrypt. Wikipedia has pages for all three functions:
https://en.wikipedia.org/wiki/PBKDF2
https://en.wikipedia.org/wiki/Bcrypt
https://en.wikipedia.org/wiki/Scrypt
The page at https://crackstation.net/hashing-security.htm contains an extensive discussion of password security.
This being said, tdhammers offers good advice regarding how to handle the migration.