I want to develop a web application where users can login inserting their email and password (chosen when register). I want to know which would be the best password hashing algorithm. I have read that bcrypt is a good option, but what algorithm do sites like facebook use?
You'll want to store a hash and a salt in your database and use those for authentication. This article in particular was very helpful for me when I implemented this: http://www.codeproject.com/Articles/704865/Salted-Password-Hashing-Doing-it-Right
You should never store a password, even if it is encrypted. Because something that is encrypted can be descrypted, so an attacker could do the same.
Google for "hashing" and "salting", perhaps OWASP has some recommendations how to do this properly. Storing encrypted passwords will be on the list of vulnerabilities to avoid, I think.
I have written an 2 functions for handling passwords. The first one accepts a string (i.e. your password) and returns a seeded hash. It takes an MD5 hash of the time and prepends it to the string. It then takes a SHA256 hash of that string. It then prepends the original MD5 hash to the SHA256 hash. The function returns this 96-character string. The second function takes 2 strings as this arguments (the password being tested and the password hash you are tested it against) and returns a Boolean value. This is PHP, but the logic is of course transferable.
function hash_password( $password ){
$md5 = strtoupper( hash( 'md5', time() ) );
$hash = $md5 . strtoupper( hash( 'sha256', $md5 . $password ) );
return $hash;
}
function test_password( $password, $hash ){
$md5 = substr( $hash, 0, 32 );
$sha256 = substr( $hash, 32 );
if( $sha256 == strtoupper( hash( 'sha256', $md5 . $password ) ) )
return true;
else
return false;
}
Related
I have a plaintext password "welcome2022".
Expected SHA1 hash is wjC4KfO5XfMIRhi45M/VA/0i8NA=
However, SHA1 hash method of sql is generating SHA1 hash in hex string format which is C230B829F3B95DF3084618B8E4CFD503FD22F0D0.
I intend to convert the the above hex string to the base64 encoded hash wjC4KfO5XfMIRhi45M/VA/0i8NA=.
Below is the groovy code for your reference.
def cleartext = SecurityUtil.decrypt(password) //Decrypts the value of a GuardedString.
def password_bytes = [0, 0, 0, 0, 0] as byte[]
password_bytes = SecurityUtil.charsToBytes(cleartext.toCharArray())
def password2 = SecurityUtil.computeBase64SHA1Hash(password_bytes) //Computes the base 64 encoded SHA1 hash of the input.
Then running the below sql query,
sql.eachRow("SELECT id FROM users WHERE userName = ? AND password =CONCAT('{SHA1}', ?)", [username, password2]) {
....
}
Logs do not show any errors when this groovy script is executed.
I am not sure if I am writing the code correct syntactically.
So this function will give you the base64 encoded SHA-1 hash of a given password:
def sha64(String password) {
password.digest('SHA-1').decodeHex().encodeBase64()
}
And if you do:
println sha64('welcome2022')
It prints
wjC4KfO5XfMIRhi45M/VA/0i8NA=
I want to create a login in symfony2 that uses a user database table. The login runs with the encoders "plaintext", "sha1" (1 iteration, encode_as_base64: false), "sha512" (1 iteration, encode_as_base64: false).
Astonishingly it is not running with more than one iterations.
I have a "chain_providers" statement in my "security.yml" with two providers "in_memory" and "user_db" (=login with a user database). The first has no problems.
Let's use two iterations for example:
"security.yml":
security:
encoders:
Customer\MyBundle\Entity\User:
algorithm: sha512
iterations: 2
encode_as_base64: false
...
user_db:
entity:
class: Customer\MyBundle\Entity\User
property: login
Now I calculate a new password hash:
php -r '$pw = "new2"; $iter = 2; for ($i = 1; $i<= $iter; $i++) $pw = hash("sha512", $pw); print "pw ($iter): $pw\n";'
And I write this into the "password" column of my users entity (MySQL table):
update User set password = "239055fb839647cfd3d58d542db192aae36f108ebbe1a16e71d25178bc455b6a94e81e34fd96f8953663d9a3206ad23512d4b79ea78cc1f0bdbcc08275c732b6" where login="test";
I should be able to login now but all I get is "Bad credentials".
My user Entity implements interface "UserInterface". my getSalt() method returns an empty string or null (both tested). There's nothing special with getUsername() or getRoles().
What can be the problem with the iterations?
Why is it running only for "iterations: 1" / "$iter = 1"?
The multiple-hashed password is created in another way than expected.
The code in MessageDigestPasswordEncoder::encodePassword($raw, $salt) is:
...
$salted = $this->mergePasswordAndSalt($raw, $salt);
$digest = hash($this->algorithm, $salted, true);
// "stretch" hash
for ($i = 1; $i < $this->iterations; $i++) {
$digest = hash($this->algorithm, $digest.$salted, true);
}
return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
..with "mergePasswordAndSalt()" returning the $raw password for an empty $salt.
In other words: for an empty $salt it appends the original password to the hashed password in each iteration.
To offline generate a new password we need this changed code:
$pw = "neu";
$digest = "";
$salted = $pw; // for emtpy salt
for ($i = 1; $i<= 4398; $i++)
{
$digest = hash("sha512", $digest . $salted, true);
}
print base64_encode($digest) . "\n";
// now write the generated code into the password in the database table
And setup this in the security.yml:
security:
encoders:
Customer\MyBundle\Entity\User:
algorithm: sha512
iterations: 4398
encode_as_base64: true
security.yml:
providers:
main:
entity: { class: Tg\UserBundle\Entity\User, property: username }
encoders:
Tg\UserBundle\Entity\User: sha512
In my manager during registration I set the password:
$encoder = $this->encoder->getEncoder($user);
$raw = $user->getPassword();
$salt = $user->getSalt();
$encoded = $encoder->encodePassword($raw, $salt);
if (!$encoder->isPasswordValid($encoded, $raw, $salt)) {
throw new \Exception('Password incorrectly encoded during user registration', 428);
} else {
$user->setPassword($encoded);
}
In my User entity I have the basic salt on construct:
$this->salt = md5(uniqid(null, true));
I receive error on default login template:
The presented password is invalid.
Wtf?
This is not exactly an answer (i can't figure out why you r example is not working). But I'm using sha512 base64 encoded and this setup is working fine for me:
security:
encoders:
Acme\HelloBundle\Entity\User:
algorithm: sha512
encode_as_base64: true
iterations: 10
Salt initialization in User class:
$this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
Hope this helps.
I just hit this error as well. You need to make sure you password field can support the sha512 hash size. I think the tutorials make the password field default to a size of 40. You need to extend this to a larger size (125).
EDIT: Issue has been resolved. To contribute a bit to the community I setup some helper methods and an example how to use them on my blog. Find it here KeyChain MT example
--
Original question:
Running iOS4.2 on Simulator and iPad.
I'm trying to store and read a password from the keychain using the code below. My inspiration for the code was https://github.com/ldandersen/scifihifi-iphone/ but I can't get it to work. What am I missing?
// Create a record.
SecRecord o = new SecRecord ( SecKind.GenericPassword );
o.Service = "myService";
o.Label = "myService";
o.Account = "test#test.com";
// The super secret password.
o.Generic = NSData.FromString ( "secret!", NSStringEncoding.UTF8 );
// Add to keychain.
SecKeyChain.Add ( o );
// Now cerate another recored to query what we just saved.
o = new SecRecord ( SecKind.GenericPassword );
o.Service = "myService";
o.Account = "test#test.com";
// Query as record.
SecStatusCode code;
var data = SecKeyChain.QueryAsRecord ( o, out code );
// This will tell us "all good!"...
Console.WriteLine ( code );
// But data.Generic is NULL and this line will crash. :-(
Console.WriteLine ( NSString.FromData ( data.Generic, NSStringEncoding.UTF8 ) );
Rather than use SecRecord's .ValueData try this:
Console.WriteLine(NSString.FromData(data.Generic, NSStringEncoding.ASCIIStringEncoding));
Generic returns NSData from where SecKind.GenericPassword's are stored.
I'm trying to log in a user as part of a form submit, but why is the following not working:
$user = db_fetch_object(db_query("SELECT * FROM users WHERE mail = '%s' AND pass = '%s'", $mail, md5($pass)));
if ($user) {
// Authenticate user and log in
$params = array(
'name' => $user->name,
'pass' => trim($user->pass)
);
// Authenticate user
$account = user_authenticate($params);
}
if I dump $user I can see the correct values, but if I dump the account it's empty.
You are passing the hashed password to ´user_authenticate()´, while the function expects the clear password (it will hash it itself indirectly when loading the account via ´user_load()´).
So changing your $params array declaration to
$params = array(
'name' => $user->name,
'pass' => $pass
);
should make your example work.
BTW, you could use user_load() yourself to avoid querying the database directly:
$user = user_load(array('mail' => $mail, 'pass' => trim($pass), 'status' => 1));
(The 'status' => 1 will restrict results to active users - you can leave that out, of course, if you really want to allow log ins to disabled accounts ;)