So I have made an encryption middleware in laravel that encrypts data using the following code
public function handle($request, Closure $next)
{
return response()->json(encrypt($response->content()),$response->status());
}
I ran the command
php artisan:generate key
So now I'm trying to decrypt this data from flutter I tried using encrypt package in flutter but still no luck in making it work.
I feel the problem is the following:
1- The key used in encryption ni laravel is APP_KEY right it is in the format base64:random string this should be my key without base64?
2- Flutter encryption package needs IV I keep trying to set it from the key but still failing would really appreciate any help.
I have never done this between laravel and dart, but i have between two laravel apps.
// bits stolen from the laravel EncryptionServiceProvider.php
if (Str::startsWith($key = env('OTHER_APPS_API_APP_KEY'), 'base64:')) {
$key = base64_decode(substr($key, 7));
}
$encrypter = new Encrypter($key, config('app.cipher')); // probably AES-256-CBC
// decrypt the data
$encrypter->decrypt($theDataToDecrypt);
If you can find a library in dart that supports the same ciper you shoud be able to do the same
Related
I am using Laravel to decrypt a string encrypted from another application (also in Laravel) but I have a problem at the beginning.
I created a new object from \Illuminate\Encryption\Encrypter class in this way in order to use a different key instead the default one:
$new_encypter = new \Illuminate\Encryption\Encrypter("base64:ABCDEFGHIJKLF=", config('app.cipher'));
but I have this error:
The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths.
The key that I used is a valid key because is from another Laravel application that works correctly and used the same encryption configuration.
The cipher passed to the constructor is correct because in the exception trace there is this line of code:
Illuminate\Encryption\Encrypter::__construct("base64:ABCDEFGHIJKLF=", "AES-256-CBC")
Where is the error?
I am using Laravel 6.
The key is base64 encoded and prefixed with base64:. You would have to remove the prefix and base64 decode it.
This is how the EncryptionServiceProvider does it:
// get the app config
$config = $app->make('config')->get('app');
// see if the key starts with 'base64:'
if (Str::startsWith($key = $this->key($config), 'base64:')) {
// decode the key
$key = base64_decode(substr($key, 7));
}
return new Encrypter($key, $config['cipher']);
$this->key() just retrieves the key key from the config array.
from laravel docs
Application Key The next thing you should do after installing Laravel
is set your application key to a random string. If you installed
Laravel via Composer or the Laravel installer, this key has already
been set for you by the php artisan key:generate command.
Typically, this string should be 32 characters long. The key can be
set in the .env environment file. If you have not renamed the
.env.example file to .env, you should do that now. If the application
key is not set, your user sessions and other encrypted data will not
be secure!
What I know about application key is: If the application key is not set, generally I do get an exception.
How do this random string help to secure the session?
What are the other uses of this application key?
If I use the same application key everywhere (like staging, production etc..) does it make the application less secure?
what are some best practices for this key
As we can see its used in EncryptionServiceProvider:
public function register()
{
$this->app->singleton('encrypter', function ($app) {
$config = $app->make('config')->get('app');
// If the key starts with "base64:", we will need to decode the key before handing
// it off to the encrypter. Keys may be base-64 encoded for presentation and we
// want to make sure to convert them back to the raw bytes before encrypting.
if (Str::startsWith($key = $this->key($config), 'base64:')) {
$key = base64_decode(substr($key, 7));
}
return new Encrypter($key, $config['cipher']);
});
}
So every component that uses encryption: session, encryption (user scope), csrf token benefit from the app_key.
Rest of the questions can be answered by "how encryption" (AES) works, just open up Encrypter.php, and confirm that Laravel uses AES under the hood and encodes the result to base64.
Further more we can see how its all done by using tinker:
➜ laravel git:(staging) ✗ art tinker
Psy Shell v0.8.17 (PHP 7.1.14 — cli) by Justin Hileman
>>> encrypt('Hello World!')
=> "eyJpdiI6ImgzK08zSDQyMUE1T1NMVThERjQzdEE9PSIsInZhbHVlIjoiYzlZTk1td0JJZGtrS2luMlo0QzdGcVpKdTEzTWsxeFB6ME5pT1NmaGlQaz0iLCJtYWMiOiI3YTAzY2IxZjBiM2IyNDZiYzljZGJjNTczYzA3MGRjN2U3ZmFkMTVmMWRhMjcwMTRlODk5YTg5ZmM2YjBjMGNlIn0="
Note: I used this key: base64:Qc25VgXJ8CEkp790nqF+eEocRk1o7Yp0lM1jWPUuocQ= to encrypt Hello World!
After decoding the result we get (you can try decode your own cookie with session):
{"iv":"h3+O3H421A5OSLU8DF43tA==","value":"c9YNMmwBIdkkKin2Z4C7FqZJu13Mk1xPz0NiOSfhiPk=","mac":"7a03cb1f0b3b246bc9cdbc573c070dc7e7fad15f1da27014e899a89fc6b0c0ce"}
to understand above json (iv, value, mac) you need to understand AES:
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
Best practices for application key
do store it in .env file only
do not store it in app.php, in fact in any git tracked file
do not change it unless you really want to
invalidate sessions/cookies (user logout)
invalidate password reset tokens
invalidate signed urls
Obvious Note: Changing application key has no effect on hashed passwords since hashing algorithms do not require encryption keys.
for a customer we are migrating a Laravel application to a Ruby application. We have some data stored in the database that we would like to decrypt in the ruby world.
This is the laravel part that was used to encrypt the data: https://laravel.com/docs/5.0/encryption
Now when importing the data to ruby we need a counter part that can decrypt the data.
In the laravel console I was able to decrypt the data like this:
>>> Crypt::decrypt('eyJpdiI6ImZyek9ZTjJNSW5ZYlhSa2ZYUldVbEE9PSIsInZhbHVlIjoia20zMTRLWEpCdXM2K05DZDBHSlE5SDlcL2pYVXk5aE5RWWR3dHFQT1dGQzA9IiwibWFjIjoiZWZlNGE3NTRhMDDlNzk2MjhlYjI1Mzc1NGNiYmRjNDMwZjM1NzdiMzkyZTU4ZjA4ZDNkMGE0YjUyOTBjMDAzOCJA')
=> "123123123123"
I am no laravel expert, but in the app.php file a secret key was set. So I need to be able to pass it somehow to the decrypt function.
The goal is to have a ruby function that takes the laravel password, encryption key and returns the decrypted value.
def decrypt_laravel_crypt(value, encryption_key)
end
Thanks for the help!
You can reverse engineer Laravel's Encrypter::decrypt method using mostly standard libs. Laravel will serialize data before encrypting it unless told explicitly not to. This means attempting to unserialize the decrypted string prior to using it.
require 'base64'
require 'openssl'
require 'json'
require 'php_serialize'
def lara_decrypt(encryptedString, appKey)
data = JSON.parse(Base64::decode64(encryptedString))
decipher = OpenSSL::Cipher.new('aes-256-cbc')
decipher.decrypt
decipher.key = Base64::decode64(appKey)
decipher.iv = Base64::decode64(data['iv'])
decrypted = decipher.update(Base64::decode64(data['value'])) + decipher.final
begin
PHP.unserialize(decrypted)
rescue
decrypted
end
end
Also when you set the app key be sure to drop base64: from the beginning of it (if it's there).
I was asked to create an API using the Laravel framework on an existing Web application. The web application uses the Zend 2 Block Cipher encryption to encrypt user password. The previous developer who developed the site has already moved on and I need to create a service to verify the user's password in the API. The problem is I can't crack Zend's encryption. I even tried using the PHP mcrypt function but I'm getting this error.
mcrypt_decrypt(): Size of key is too large for this algorithm
This is a bit odd but is there anyway I can decrypt Zend's encryption using just plain PHP? Or is there a work around here? I can't change the current web application as it is being used.
Here is the sample code of the encryption:
use Zend\Crypt\BlockCipher;
class Encryption {
private $_cipher = null;
public function __construct(){
$this->_cipher = BlockCipher::factory('mcrypt',array('algo'=>'aes'));
$this->_cipher->setKey('fltjXW05820D[1(Z5SknJBZ12goBbyK<*271biqT5"j$WvA2JCycgA"{UIe6qJ2');
}
public function encrypt($plainText){
return $this->_cipher->encrypt($plainText);
}
public function decrypt($enctyptedData){
return $this->_cipher->decrypt($enctyptedData);
}
}
Any advice by the experts?
Thank you in advance. Sorry I'm a beginner in Laravel and Zend.
I am building an iOS app for an already existing web application I created. The web app uses laravel and sentry to encrypt passwords. New users have to be able to be created from the iOS app.
The server that the web app talks to is written in php but does not use laravel or sentry.
The only sentry function I need is the one they use to encrypt passwords.
What function does sentry use to hash passwords? I am talking about Cartalyst\Sentry\Hashing\NativeHasher
I need to be able to duplicate this function and use it in a separate php file.
i've found this link : https://github.com/cartalyst/sentry/blob/master/src/Cartalyst/Sentry/Hashing/NativeHasher.php
and this code is what you want probably:
public function hash($string)
{
// Usually caused by an old PHP environment, see
// https://github.com/cartalyst/sentry/issues/98#issuecomment-12974603
// and https://github.com/ircmaxell/password_compat/issues/10
if (!function_exists('password_hash')) {
throw new \RuntimeException('The function password_hash() does not exist, your PHP environment is probably incompatible. Try running [vendor/ircmaxell/password-compat/version-test.php] to check compatibility or use an alternative hashing strategy.');
}
if (($hash = password_hash($string, PASSWORD_DEFAULT)) === false) {
throw new \RuntimeException('Error generating hash from string, your PHP environment is probably incompatible. Try running [vendor/ircmaxell/password-compat/version-test.php] to check compatibility or use an alternative hashing strategy.');
}
return $hash;
}