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).
Related
I'm moving an app from CakePHP 2 to CakePHP 3. There is a new hashing algorithm for Cake3. I'd like the existing users to be able to login to the app using their old passwords and for those passwords to then be updated to the new algorithm.
Unfortunatly, I can't get the correct hash to match up to what is in the database.
$person = $this->Auth->identify();
if(!$person){ # maybe they have old sha1 password?
$oldhash = Security::hash($this->request->data['password'],
'sha1', "oldsalt");
$person = $this->People->find()->where(['password' => $oldhash])->where(['email' =>$this->request->data['email'] ])->first();
if($person){
$person->password = Security::hash($this->request->data['password']);
$this->People->save($person);
}
}
The user is not found and if i debug the $oldhash out I get a different string than what is stored in the password field for that user.
What am I doing wrong?
Fallback classes
According to the documentation:
CakePHP provides a clean way to migrate your users’ passwords from one algorithm to another, this is achieved through the FallbackPasswordHasher class. Assuming you are migrating your app from CakePHP 2.x which uses sha1 password hashes, you can configure the AuthComponent as follows:
You will have to create an Custom Password Hasher class src/Auth/. A Custom Password hasher wil look something like this:
namespace App\Auth;
use Cake\Auth\AbstractPasswordHasher;
class LegacyPasswordHasher extends AbstractPasswordHasher {
public function hash($password)
{
return sha1($password);
}
public function check($password, $hashedPassword)
{
return sha1($password) === $hashedPassword;
} }
and then add it to passwordhasher in authenticate as fallback like this:
'authenticate' => [
'Form' => [
'passwordHasher' => [
'className' => 'Fallback',
'hashers' => [
'Default',
'Legacy'
]
]
]
]
The first name appearing in the hashers key indicates which of the classes is the preferred one, but it will fallback to the others in the list if the check was unsuccessful.
legacy is the Custom Password Hasher.
Updating the password
To update the users' password to the new hash you only have to add this code to your login procedure:
if ($this->Auth->authenticationProvider()->needsPasswordRehash()) {
$user = $this->Users->get($this->Auth->user('id'));
$user->password = $this->request->data('password');
$this->Users->save($user);
}
Documentation
More information about Changing hashing Algorithms
More information about the Custom Password Hasher
I had a CakePHP 2 app using Blowfish. Here's how I made it work with CakePHP 3:
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
// ...
'fields' => [
'username' => 'email',
'password' => 'pass', // make sure you match this with your corresponding login.ctp input name
],
// ...
'passwordHasher' => [
'className' => 'Fallback',
'hashers' => [
'Default' => ['hashType' => PASSWORD_BCRYPT],
]
],
// ...
]
],
Hope it helps someone googling this issue
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;
}
I'm trying to use the CRSF token management without a FormType. So in a twig template i just use that to generate a token:
{{ csrf_token( inception_inscription ) }}
In the controller i'm trying this :
$tokenManager = $this->get('security.csrf.token_manager');
$token = $request->get('token');
inception = $this->container->getParameter('crsf_inscription_inception');
if (!$tokenManager->isTokenValid($tokenManager->getToken($inception, $token))) {
throw new HttpException(400, 'Invalid token');
}
But in fact the method isTokenValid always return true. I can force the $token vaiable to what i want, it's never false, so the validation is useless.
When i do debug step by step, i walk throught a Symfony\Component\Security\Csrf::getToken() and that method is testing that : ($this->storage->hasToken($tokenId)) whic always return false and force the process to generate a new Token.
I don't really undertand how it works.
Here is ore information about my code :
Symfony 2.6.x
framework:
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form:
csrf_protection:
enabled: true
field_name: token_my
csrf_protection:
enabled: true
validation: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
handler_id: ~
name: 'my'
fragments: ~
http_method_override: true
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
inception_inscription: %crsf_inscription_inception%
From what I understand, $tokenManager->getToken($tokenId) always generates a new, valid token. You would probably check the provided token instead, e.g.:
$tokenManager = $this->get('security.csrf.token_manager');
$tokenId = $this->container->getParameter('crsf_inscription_inception');
$tokenValue = $request->get('token');
$token = new CsrfToken($tokenId, $tokenValue);
if (!$tokenManager->isTokenValid($token)) {
throw new HttpException(400, 'Invalid token');
}
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
I tried to encrypt a password in Griffon, but I don't know how to do that. Usually I'd use md5 in another language, but what in griffon?
Here is a bit of my code:
if (sql.firstRow("SELECT userID FROM tbluser WHERE userID = ${model.userID}") != null) {
// usually in SQL like this
user.executeUpdate("UPDATE tbluser SET username = ${model.username}, password = md5(${model.password}), level = ${model.level} WHERE userID = ${model.userID}")
edt {
int index = model.listUser.findIndexOf{it['userID'] == model.userID}
model.listUser[index] += [username: model.username, password: model.password, level: model.level] --> how to do md5 here?
}
} else {
user.add(userID: model.userID, username: model.username, password: model.password, level: model.level) --> and here?
edt { model.listUser << [userID: model.userID, username: model.username, password: model.password, level: model.level] }
}
I just get a sample code about it and it worked.
Here the code:
import java.security.MessageDigest
String generateMD5(String s) {
MessageDigest digest = MessageDigest.getInstance("MD5")
digest.update(s.bytes);
return new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
}
for my case: generateMD5(model.password)
Per se encryption is not related to Griffon, as it's just a transformation of a character/byte array. However there's a bcrypt plugin available that applies the BCrypt algorithm http://artifacts.griffon-framework.org/plugin/bcrypt
More information on BCrypt can be found at http://codahale.com/how-to-safely-store-a-password/
I'm very new to griffon but i think this can help you.
I hope i could help you with this.
Codesearch Griffon MD5