note: i am not looking for workaround, i am looking for a plain ruby solution!
this question is the similar to this question, but it isn't answerd, its just a workaround to a shell commando there.
i want to generate a sha512 encrypted string which is compatible with the format in debian /etc/shadow.
the following create a correct string with php:
$salt = 'fGn9LR75';
$hash = crypt('test', '$6$'.$salt);
// hash is:
// $6$fGn9LR75$YpI/vJHjEhvrYp5/eUSRinpiXdMthCxFWSEo0ktFNUaRBsA7pCWYzzmQptmnfyHno9YEJFNHYuESj3nAQmSzc1
as far as i know this a normal, salted base64 encoded string. the spec of the sha generation method is here
irb(main):001:0> salt = 'fGn9LR75';
irb(main):002:0* hash = 'test'.crypt('$6$' + salt);
irb(main):003:0* hash
=> "$6$fGn9LR75$YpI/vJHjEhvrYp5/eUSRinpiXdMthCxFWSEo0ktFNUaRBsA7pCWYzzmQptmnfyHno9YEJFNHYuESj3nAQmSzc1"
The crypt() algorithm for SHA256/512 is not simply a base64-encoded hash. It's an intentionally crazy process which involves multiple hashes running in parallel.
Related
I have a big problem, I have to write a php login page using an db where password are stored as PBKDF2 (with another perl script). When I get the password with a query I read this:
sha256:1000:2SeBDP88w4bqKbJaCJNpNuRHQhUM96X1:jgh/SZtmRWH5iDIwtXyFLtuuDf7YE+7HQEJZ4KFFNAg= (I know this password but I cannot regenerate it in php).
I tried with this script (get from php.net):
$password = "qqqqq";
$iterations = 1000;
$salt = "2SeBDP88w4bqKbJaCJNpNuRHQhUM96X1";
$hash = hash_pbkdf2("sha256", $password, $salt, $iterations, 20);
echo $hash // result a2ba3349194c38f828af
but the pass generate is a2ba3349194c38f828af and not jgh/SZtmRWH5iDIwtXyFLtuuDf7YE+7HQEJZ4KFFNAg=
who wrote the perl script that store these password told me "The passwords are getting encoded though one-way hashing scheme named 'PBKDF2'"
Some ideas? Someone know where I'm wrong?
jgh/SZtmRWH5iDIwtXyFLtuuDf7YE+7HQEJZ4KFFNAg= is Base64 (the = on the end is a dead giveaway, though Base64 exists without a trailing =).
Converted to hex, the value is 8E087F499B664561F9883230B57C852EDBAE0DFED813EEC7404259E0A1453408
This is still not your answer, but now we can easily see it is 64 hex characters => 32 bytes.
You asked for 20 bytes.
It also looks like your salt input is base64, but the function you're passing it to expects ... whatever the output of base64_decode is.
So, you need to consistently process the base64-encoded data. And then you'll need to make sure that your hash algorithm, iteration count, and output byte count all match what the perl script says.
try this
$hash = strtoupper(bin2hex($hash));
We have a website built in Ruby on Rails.
User registration is processed through the site in Ruby and the password is hashed using SHA1.HexDigest function of Ruby with a different salt for every user.
What I need to do is that - create a webservice in PHP which will login the user already registered on the website.
For that I will need to produce a same hash from the user input.
As I have almost zero knowledge of Ruby, so I did a lot of research on how we can reproduce the same with PHP. I went through the following link, but to no avail.
How to generate the password in PHP as it did by Devise Gem in Ruby on Rails
Ruby also processes/hashes the input for a number of times (i.e. stretches, as you may call it in Ruby).
The hash saved in the database is 128 characters in length.
Salt length is 20 characters.
Don't know if some sort of pepper is used as well.
Example,
user input = 123456
salt = g0i3A51x0xa7wrfWCMbG
database password (128 char hash) = 5374f9853f96eaa5b3c1124f9eb1dbbb63fb5c5ce40abb41ec88c745ec3455328685f3046cac8c356a4d81dbd315fd09173c54dc94a4208e5bc091776b02eb77
If someone can replicate the same hash with PHP, using the above given user-input and salt, then please share the code.
Please help.
It'll be very helpful of urs.
Thanks
class Sha1 < Base
# Gererates a default password digest based on stretches, salt, pepper and the
# incoming password.
def self.digest(password, stretches, salt, pepper)
digest = pepper
stretches.times { digest = self.secure_digest(salt, digest, password, pepper) }
digest
end
private
# Generate a SHA1 digest joining args. Generated token is something like
# --arg1--arg2--arg3--argN--
def self.secure_digest(*tokens)
::Digest::SHA1.hexdigest('--' << tokens.flatten.join('--') << '--')
end
I would start with a simpler hashing routine on both sides, stretching and salt are great, but start without those and do a simple hash on both sides to see if you can get them to line up. Then you can go add salt/stretching later.
On the ruby side start with something like:
require 'digest/sha1'
Digest::SHA1.hexdigest(string)
When you hash you cant decrypt, you have to hash on both sides and compare the result.
If you really want to encrypt something and then decrypt, try this:
http://jnylund.typepad.com/joels_blog/2007/11/cross-language-.html.
A straightforward translation of the above Ruby code is:
function hashPassword($password, $stretches, $salt, $pepper) {
$digest = $pepper;
for ($i = 0; $i < $stretches; $i++) {
$digest = sha1("--$salt--$digest--$password--$pepper--");
}
return $digest;
}
To use SHA-512 (128 hex digit output) instead of SHA-1 (40 hex digit output), replace sha1(...) with hash('sha512', ...).
I cannot check this code against the hash you posted because the "pepper" is a secret configuration setting I do not know. If it is not configured, try the empty string.
I understand that PHP's crypt() function works like so:
crypt($password,$salt);
And that to create a bcrypt hash(which is considered very secure) the format is:
crypt("$2y$15$password",$salt);
Where $2y specifies the use of bcrypt, and 15 is the number of rounds, and it should be above 10.
Here's my question. Running:
crypt("$2y$15$password");
in my understanding, generates a nice big random salt and adds it to the hash, and when comparing passwords, this is extracted automatically. This would mean that I wouldn't have to have a salt field in my table, or generate a salt independently. Is this secure and correct?
For example, when I run:
$test = "Hello";
echo crypt("$2y$15$test") . "\n";
I get:
$6$R59d/nemygl0$/Gk6s57K2eFAkH4BWDGYhfdhbYGcqz.GRbD7qGDKOlhE5Lk.kgCoGQo/sDCCf1VDffdh7jtXPn/9rsexwrpFk1
Where the first 6 refers to some algorithm number, the next bit between the two $ is the salt, and the bit after that is the hash. Is this correct?
Also, what is the syntax for comparing this hash to another for verification?
Thanks.
I think crypt as you're using it uses SHA-512.
You probably forgot to pass $test as parameter in your crypt().
According to php docs you should pass the password as first argument (without any prefix) and then pass the salt as second argument with the $2y$15 prefix and a 22 characters salt. E.g.
crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$');
The function crypt() should be used like this:
$hashvalue = crypt($password, $cryptParams);
whereas the salt must be generated by yourself and is part of $cryptParams.
$bcryptAlgo = '$2y';
$cost = '$15';
$salt = '$' . functionThatGenerates22CharRandomSalt();
$cryptParams = $bcryptAlgo . $cost . $salt;
One of the difficulties is to generate a valid, unique and unpredictable salt. The best you can do is to read from the operating systems random source.
PHP 5.5 will have it's own functions password_hash() and password_verify() ready, to simplify this task. I strongly recommend to use this excellent api, there is also a compatibility pack available for earlier PHP versions. If you want to know more about how to use crypt, have a look at this article.
Your cost parameter of 15 is quite high, use it if you can afford this much of time, but today a number of 10 is ok.
I am rewriting a PHP Login system and I just faced this
function createSalt()
{
$string = md5(uniqid(rand(), true));
return substr($string, 0, 3);
}
$salt = createSalt();
$hash = hash('sha256', $salt . $hash);
Actualy I never worked with salting before, I searched a bit and found it useful.
But my answer is, Is this a good way to work with salt?
Wouldn't $string = sha1(uniqid(mt_rand(), true)) be better?
And what about returning only 3 characters of the hash? I really don't get it.
What you think?
Consider using PHP's crypt() instead of reinventing the wheel. It is specifically designed for password hashing, and offers hash algorithms suited for that purpose.
I prefer sha1 or sha256, md5 is super-outdated, the sha-functions are way better. But this is my opinion, choose what you want.
What is really important in this case is the salt. A salt is always stored in plaintext together with the hash and is used to improve the length of a password (if you want to hash the password, might be something else of course) to prevent attacks based on rainbow/lookup tables. This is no protection against cracking the password by using bruteforce (which works quite well against md5, so use sha256 which is harder to crack).
Therefore it is totally unimportant if you use 32 random chars for the hash, or something like md5(mt_rand()) - important is the length. I would use something like
$hash = md5(mt_rand()) . md5(mt_rand());
md5() results in 32 bytes string, based on a random number (mt_rand() is better then uniqueid()). With this simpel line you get a very "strong" hash which should secure every password against rainbow tables.
I don't agree with the given function createSalt() - mainly for the same reasons as you.
My approach to this would be
define(SALT_LENGTH,32);
function createSalt()
{
$string='';
for ($i=0;$i<SALT_LENGTH;$i++) $string.=chr(rand(0,255));
return $string;
}
A good salt is a random byte sequence - no MD5 or SHA1 makes any sense, as there is nothing to hash!
I no master PHP programmer but I've been working on the same hash script for a login system.
Im storing it on GitHub - https://github.com/revitalagency/PHP5-Salt-Super-Admin
I created my hash using...
hash_hmac('sha256', $_POST['pass'], GLOBAL_SALT);
GLOBAL_SALT is defined in a config file not in the DB for extra protection.
I'm trying to find a hashing algorithm to use to save my passwords in the DB (along with a salt). I found this on SO: How do you use bcrypt for hashing passwords in PHP?. The top answer has a library that seems to work. I'm just a bit confused by the verify method.
To run the script, the author of the library provides:
$bcrypt = new Bcrypt(15);
$hash = $bcrypt->hash('password');
$isGood = $bcrypt->verify('password', $hash);
The hash method takes the input string and hashes it using mcrypt + a salt. The result is returned to $hash. Then the verify method takes the same input as hash method + $hash. verify then calls mcrypt + the value of $hash (instead of some random salt) -- and somehow the results are the same $hash???
Simplified:
hash = password + salt
verify = password + hash
verify = hash <-- huh???
What did I miss?
ALSO:
I plan to modify the code such that hash method accepts a $salt parameter. I will make getSalt a public method. This way, I can get a salt, store it in the DB, store the hash in the DB, and use user's input + salt to see if it hashes to what I have stored in the DB. Any problems with this idea?
I'm not familiar with the actual bcrypt, but something along the following lines must be what happens:
When you create the "hash", $bcrypt->hash('password') returns a string that contains both the hash value and the initial salt.
When you subsequently say $bcrypt->verify('password', $mystring), the function first reads the salt part out of your input string, then creates the hash again with that salt, and finally compares that computed hash with the hash part of your input string.
In any salinated hashing scheme, you will always have to store the salt along with the hash value.
The hash in this case also contains the salt. It's concatenated to the beginning of the string, usually as something like $2a$12$SALT.... Passing the hash to verify is just done to use that salt value again, the rest of the hash is ignored. That also means you do not need to modify the function for use with salts, that's already part of the algorithm.