Reputation: 1669
I'm developing a so called AAC (Automatic Account Creator) for a game, it's basically a site with functions to create accounts, players and several more things for players. The server only supports SHA1 and plain - which is totally unsafe. I can't dive into the source code and make changes. If there's anyway to use SHA1 I would be grateful. I just read about BCrypt, it's great but I can't really change the source code to suit BCrypt. I managed to put SHA1 on registration like this:
$password = $input['password'];
$password = sha1($password);
But I simply can't login. am I doing it wrong? seems like Laravel won't let me login.
I've got get_register
and post_register
, also I've got get_login
and post_login
. Do i need to change something in the post_login to make it login or?
any hints?
I'm using Laravel's php server (php artisan serve) and phpMyAdmin on WAMP. I think Laravel checks when you are checking the DB via the Auth::attempt
method laravel is doing some form of hashing to check the current pw and the logged in one to check against each other.
Upvotes: 19
Views: 34747
Reputation: 586
You can do this
dd(
sha1(55),
hash('sha1', 55),
hash_hmac('sha1', 55, env('APP_KEY')),
hash_hmac('sha256', 55, env('APP_KEY')),
hash_hmac('sha512', 55, env('APP_KEY')),
);
// outputs:
/*
"8effee409c625e1a2d8f5033631840e6ce1dcb64"
"8effee409c625e1a2d8f5033631840e6ce1dcb64"
"a2ebb15e6747d1c09f2754787ab390d35c24996e"
"f0fadaa9fdd518947ac3f698196d5370dc2409bbdfbe9e37bd30f935b6cc1f47"
"c1e6f4e144565aa4fdb9c7ae34aba7d43424e20fa40ad3a0641d20bfbb3b9681ded4f4cc8b4661804e4a753118a3f984585d6915ee6d4b75a95310af48afe920"
*/
Upvotes: 1
Reputation: 41
In Laravel 7 adding new hash methods to Laravel got a lot easier you can also still support the old Hash methods instead of basically overwriting them.
First we will create a subfolder in the app folder called Libs or Libaries or basically whatever you want to call it. In that folder I created a folder called CustomHash where I store all my custom hashers.
Through PSR-4 it is automatically detected and we do not need to add it anywhere.
The Namespace is based on the folder names I chose.
app/AppServiceProvider.php
First we use the namespace of the Sha1Hasher
use App\Libs\CustomHash\Sha1Hasher;
then in the boot() function of your AppServiceProvide.php
Hash::extend("sha1", function($app)
{
return new Sha1Hasher();
});
app/Libs/CustomHash/Sha1Hasher.php
<?php
namespace App\Libs\CustomHash;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Hashing\AbstractHasher;
class Sha1Hasher extends AbstractHasher implements HasherContract {
/**
* Hash the given value.
*
* @param string $value
* @return array $options
* @return string
*/
public function make($value, array $options = array()) {
//I have custom encoding / encryption here//
//Define your custom hashing logic here//
return sha1($value);
}
/**
* Check the given plain value against a hash.
*
* @param string $value
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function check($value, $hashedValue, array $options = array()) {
return $this->make($value) === $hashedValue;
}
/**
* Check if the given hash has been hashed using the given options.
*
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function needsRehash($hashedValue, array $options = array()) {
return false;
}
}
And that's basically it if you want to change the default hash algorithm for everything there is one more thing to do:
config/hashing.php
Change the default driver for hashing to the sha1 driver we implemented with the edits above.
'driver' => 'sha1',
Upvotes: 4
Reputation: 1
Laravel 7 UPD
same as Das123 answer but a little fix to
app/Providers/SHAHashServiceProvider.php
namespace App\Libraries\ShaHash;
use Illuminate\Contracts\Hashing\Hasher as HasherContract;
use Illuminate\Hashing\AbstractHasher;
class SHAHasher extends AbstractHasher implements HasherContract
/**
* Register the service provider.
*
* @return void
*/
public function register() {
$this->app->singleton('hash', function() {
return new SHAHasher();
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides() {
return array('hash');
}
}
Upvotes: -1
Reputation: 865
It took me a lot of time to get something similar happening in Laravel 5.6 but this thread was invaluable. The accepted answer gets you very close but there are still some ambushes along the way (as can be seen in the comments) so instead of struggling with the comments I thought it would be helpful for others to have it presented as an answer.
In my case I needed to access an existing database and couldn't change the user file. The passwords were saved in SHA256 format with a hash key applied as well. So the objective for me was to really only get the check function working.
I'm really new to Laravel and I know there will be a better way around this issue but I couldn't get the app\Libraries
area to register so I put both SHAHasher.php and SHAHashServiceProvider.php into app\Providers
which I would assume is some sort of Laravel sacrilege but it was the only way I got it to work. :)
The steps I took (hijacking rmobis's excellent answer for Laravel 4) was:
The hash key used in the original app needed to be accessed by Laravel so I added this to the bottom of .env
.
.env
...
HASH_KEY=0123_key_code_added_here_xyz
app/Providers/SHAHasher.php
namespace App\Providers;
use Illuminate\Contracts\Hashing\Hasher;
class SHAHasher implements Hasher
{
/**
* Get information about the given hashed value.
* TODO: This was added to stop the abstract method error.
*
* @param string $hashedValue
* @return array
*/
public function info($hashedValue)
{
return password_get_info($hashedValue);
}
/**
* Hash the given value.
*
* @param string $value
* @return array $options
* @return string
*/
public function make($value, array $options = array())
{
// return hash('sha1', $value);
// Add salt and run as SHA256
return hash_hmac('sha256', $value, env('HASH_KEY'));
}
/**
* Check the given plain value against a hash.
*
* @param string $value
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function check($value, $hashedValue, array $options = array())
{
return $this->make($value) === $hashedValue;
}
/**
* Check if the given hash has been hashed using the given options.
*
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function needsRehash($hashedValue, array $options = array())
{
return false;
}
}
app/Providers/SHAHashServiceProvider.php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class SHAHashServiceProvider extends ServiceProvider {
/**
* Register the service provider.
*
* @return void
*/
public function register() {
$this->app->singleton('hash', function() {
return new SHAHasher();
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides() {
return array('hash');
}
}
app/config/app.php
remove or comment out // Illuminate\Hashing\HashServiceProvider::class,
Add App\Providers\SHAHashServiceProvider::class,
I didn't need to register the users (only to allow them to use their existing logins to get in) so I only tested it for access. I'm not sure why the app/Libraries area wouldn't take. I was getting an error
Class 'SHAHashServiceProvider' not found
when I ran the composer dump-autoload
command until I moved both into app/Providers.
Hope this helps others trying to get the anser to work in Laravel 5.
Upvotes: 8
Reputation: 26992
You'll have to rewrite the Hash
module. Thanks to Laravel's ideas of following IoC and Dependency Injection concepts, it'll be relatively easy.
First, create a app/libraries
folder and add it to composer's autoload.classmap
:
"autoload": {
"classmap": [
// ...
"app/libraries"
]
},
Now, it's time we create our class. Create a SHAHasher
class, implementing Illuminate\Hashing\HasherInterface
. We'll need to implement its 3 methods: make
, check
and needsRehash
.
Note: On Laravel 5, implement Illuminate/Contracts/Hashing/Hasher
instead of Illuminate\Hashing\HasherInterface
.
app/libraries/SHAHasher.php
class SHAHasher implements Illuminate\Hashing\HasherInterface {
/**
* Hash the given value.
*
* @param string $value
* @return array $options
* @return string
*/
public function make($value, array $options = array()) {
return hash('sha1', $value);
}
/**
* Check the given plain value against a hash.
*
* @param string $value
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function check($value, $hashedValue, array $options = array()) {
return $this->make($value) === $hashedValue;
}
/**
* Check if the given hash has been hashed using the given options.
*
* @param string $hashedValue
* @param array $options
* @return bool
*/
public function needsRehash($hashedValue, array $options = array()) {
return false;
}
}
Now that we have our class done, we want it to be used by default, by Laravel. To do so, we'll create SHAHashServiceProvider
, extending Illuminate\Support\ServiceProvider
, and register it as the hash
component:
app/libraries/SHAHashServiceProvider.php
class SHAHashServiceProvider extends Illuminate\Support\ServiceProvider {
/**
* Register the service provider.
*
* @return void
*/
public function register() {
$this->app['hash'] = $this->app->share(function () {
return new SHAHasher();
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides() {
return array('hash');
}
}
Cool, now all we have to do is make sure our app loads the correct service provider. On app/config/app.php
, under providers
, remove the following line:
'Illuminate\Hashing\HashServiceProvider',
Then, add this one:
'SHAHashServiceProvider',
Upvotes: 42
Reputation: 19487
There is actually a easier (or more simple, at least) solution for a case like this. you can 'fake' the hashing, by using this method in the user model:
public function getAuthPassword() {
return Hash::make($this->password);
}
And hashing the input with your own hash function. For instance, if your passwords are currently hashed with sha1, you can validate the user with
Auth::attempt(array('email' => $email, 'password' => sha1($password))
It doesn't feel like good coding practice, to do it this way, but it will certainly be easier than rewriting the hash module.
Upvotes: 5