问题
I need to be able to validate in node
some password which were generated and stored using Symfony2
with sha512
encoding.
I can retrieve the hash
and the salt
just fine but when using crypto
I cannot manage to generate a hash using the salt which matches the one stored in the database.
Symfony security.yml
security:
encoders:
"FOS\UserBundle\Model\UserInterface": sha512
Hash stored in DB
6zxwRZc4EPXKxQes9avs0ZyCRFkC4dtpXrT983ML8VLvv9WhRnAi282bwuFuj3LHPQBGmqD1BfCLDUXGdHIjZQ==
Salt stored in DB
qu7rjvaietws8kg4cgsggksookwsws8
As there is a salt on the node side I'm using crypto.pbkdf2Sync
, there is no iterations set in the configuration and it seems like the Symfony default is 1000. The default length however is 40 yet the stored hash length is 128 so using 128 as length (tried 40 without success).
I have also tried 5000 iterations as used by Symfony 2 MessageDigestPasswordEncoder
and merging the raw password with the salt as symfony does raw_password{salt}
without success.
I can also get a base64 long enough if I use pbkdf2Sync
to generate a key of length 40
(as per symfony default) and then using that to update a hash generate with crypto.createHash
var hash = user.password;
var salt = user.salt;
console.log(hash);
console.log(crypto.pbkdf2Sync("password", salt, 1000, 128 >> 1, "sha512").toString("base64"));
The size of the hash generated and format matches the one stored in the database but they do not match in values which is my issue. I also tried multiple iteration values dynamically generated without any luck.
Output
6zxwRZc4EPXKxQes9avs0ZyCRFkC4dtpXrT983ML8VLvv9WhRnAi282bwuFuj3LHPQBGmqD1BfCLDUXGdHIjZQ==
5QPz3zXwhak/bTD2S9IFEEFmiJ8q/fqIlSF6cWin7dqmh92EFNXjw/FLtQw7NX3LVehwcXKjfypo2EhJxiLouQ==
w9+8xjklvGq9CuiqY8tEoxEetLV9lbhLJ/KaFQEooUFJrGT9/EdsVd/sSRJ+DXjsH4RQeaqsmftmuzLPgVv5MA==
How can I generate the hash so it matches the way used by Symfony 2?
回答1:
Symfony does 5000 iterations with sha512.
- They concatenate raw password with user's salt to generate a new salt
- They generate a starting hash with above data.
- On each iteration previous hash its updated with the current hash + new
salt
generated at step 1.
In node, on each iteration you should digest previous hash as binary and in the end digest as base64, to mimic what Symfony does.
And an example:
var crypto = require('crypto');
var encodePassword = function (raw, salt) {
var salted = raw + '{'+salt+'}',
hash = crypto.createHash('sha512').update(salted, 'utf-8');
for (var i = 1; i < 5000 ; i++) {
hash = crypto.createHash('sha512').update(hash.digest('binary')+salted);
}
return hash.digest('base64');
};
console.log("Password: "+ encodePassword("secret", "h2zaays1cx2og00c6ow2gc0k4skg41g"));
回答2:
Hello might be it will be useful for someone. This is part of code from my live website that works.
https://gist.github.com/konstantinzolotarev/deec71876739f8bf1058
回答3:
Check Pbkdf2PasswordEncoder source code to see defaults values. Also keep in mind that Symfony will do a base64_encode by default
来源:https://stackoverflow.com/questions/26179033/how-to-validate-symfony2-sha512-passwords-using-nodejs