Laravel - How decrypt value of cookie - php

Hello i need to decrypt value of cookie.
My code to create and destroy:
public function setSession($id){
Cookie::queue('userId', $id, 10000);
}
public function destroySession(){
Cookie::queue(Cookie::forget('userId'));
}
But i need to get value of cookie without encrypt.

In web request context cookies are usually automatically encrypted and decrypted by the EncryptCookies middleware. So easiest option would be just to enable this middleware (and it's enabled by default in Laravel).
If you need to decrypt any value manually, the following will do the trick:
// get the encrypter service
$encrypter = app(\Illuminate\Contracts\Encryption\Encrypter::class);
// decrypt
$decryptedString = $encrypter->decrypt($encryptedString);
Check the code of the EncryptCookies middleware to learn more about what it does internally.

By default Crypt::decrypt tries to deserialize the value, and yours is not serialized and that's why you get the error. You need to pass a second argument like:
Crypt::decrypt(Cookie::get('userId'), false);

Related

Laravel cookie unexpected output i.e. encrypted result on service provider

I am developing a package where I am registering ServiceProvider and inside my class methods I am saving cookie data as this
Cookie::queue(Cookie::make('my_name', 'manash', 120));
and I am retrieving like this
Cookie::get('my_name')
but I am not getting the value as I have stored, instead it is outputting me this value
eyJpdiI6InlcL3VxNklrejlKemxLQ012T0pcL3U1QT09IiwidmFsdWUiOiJpbzRmajVEUU90YkhhdTdpeFNlcURBPT0iLCJtYWMiOiI1MTFiMTk5YjY3ZTczMzI2Nzc1MGI1Mzk3NmU1MjJhYjE3MWRhYWE2OGQ4NWE1Y2Y2NDgyZWQ1YmYxOGQ4OWU1In0=
I think it encrypted, but as per my knowledge it should be automatically decrypted when we use get method.
I am using laravel 5.3.28
What happens is that all cookies created by laravel are encrypted and signed with an authentication code.
Have you tried with the request?
Like this:
Illuminate\Http\Request
Request $request;
$request->cookie('my_name');
Check if your middleware is not triggering before Encrypt Cookie middleware
Try https://laravel.com/docs/master/encryption see if it works

How to decrypt password in laravel

$user = User::where('email',$request['email'],'password', Crypt::decrypt($request['password']))->first();
How do I decrypt a password in laravel?
This is the error that I'm getting:
DecryptException in Encrypter.php line 144: The payload is invalid.
As mentioned, it makes little sense why you would want/need to do this, given Laravel's authentication library. However, in an effort to help, I'll make this suggestion:
I'm assuming this code is inside a controller and you're passing the request object. If so, you're using the request object incorrectly, as it's not a simple array. To obtain the values, you should be calling the input method of the request object:
$value = $request->input('password');
Docs are here.

Verifying JWT from Azure Active Directory

I have followed the instructions here to obtain an access token for a web API.
https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx
I have this working but the documentation is vague when it comes to figuring out how to validate the token in PHP.
You can use the access token that is returned in the response to authenticate to a protected resources, such as a web API. Typically, the token is presented to the web API in an HTTP request using the Bearer scheme, which is described in RFC 6750. This specification explains how to use bearer tokens in HTTP requests to access protected resources.
When the web API receives and validates the token, it gives the native client application access to the web API.
How do I validate the JWT in application? I have a PHP framework which is using PHP openssl_verify() function with the token, signiture, key and algorithm but I receive error of when I use the private key from Azure with the SHA256 algorithm:
openssl_verify(): supplied key param cannot be coerced into a public key
This leads me to believe that the key I am using in PHP to validate is not correct. At the moment, I am using the private key I generated for the Active Directory Application, which happens to also be the same value I am using for the "client_secret" parameter when hitting the oauth2/token url (any other value causes no token to be generated so this is probably correct).
The key is similar to (BUT IT NOT ACTUALLY):
cLDQWERTYUI12asdqwezxctlkjpoiAn7yhjeutl8jsP=
Where I beleive openssl needs to have a certificate... if so I can't seem to find where this certificate is in the Azure portal.
What am I missing here? What is the key I should be using with openssl_verify() to verify the JWT and where do I find it in Azure?
Thanks
--
UPDATE:
I have found the public keys here: https://login.windows.net/common/discovery/keys
However I still cannot use the X5C provided to verify the signature. How do you do this in PHP?
--
UPDATE 2:
I used a converted to create a .pem file for the public key using both the 'e' and 'n' parameters. This received a public key.
Now I get OPEN SSL errors when decrypting with it:
error:0906D06C:PEM routines:PEM_read_bio:no start line
Closing this question as I have moved on from the origional issue. Updated my question with comments showing how I have progressed.
Created a new question for the new specific issue: How do I verify a JSON Web Token using a Public RSA key?
--
Just in case it helps anyone else:
For further information on a solution to obtaining a public key from Microsoft in PHP I did the following:
$string_microsoftPublicKeyURL = 'https://login.windows.net/common/discovery/keys';
$array_publicKeysWithKIDasArrayKey = loadKeysFromAzure($string_microsoftPublicKeyURL);
function loadKeysFromAzure($string_microsoftPublicKeyURL) {
$array_keys = array();
$jsonString_microsoftPublicKeys = file_get_contents($string_microsoftPublicKeyURL);
$array_microsoftPublicKeys = json_decode($jsonString_microsoftPublicKeys, true);
foreach($array_microsoftPublicKeys['keys'] as $array_publicKey) {
$string_certText = "-----BEGIN CERTIFICATE-----\r\n".chunk_split($array_publicKey['x5c'][0],64)."-----END CERTIFICATE-----\r\n";
$array_keys[$array_publicKey['kid']] = getPublicKeyFromX5C($string_certText);
}
return $array_keys;
}
function getPublicKeyFromX5C($string_certText) {
$object_cert = openssl_x509_read($string_certText);
$object_pubkey = openssl_pkey_get_public($object_cert);
$array_publicKey = openssl_pkey_get_details($object_pubkey);
return $array_publicKey['key'];
}
Its better however to cache these to disk so your not loading these them every time, but this is just a simple example of how to do this.
Then, using the array of public keys, check the JWT header for the 'kid' value to find the correct public cert to verify against and use this in parameter 3 within openssl_verify(). I used the JWT class to deal with this for me.
Using this public key array created above and the JWT class should allow you to validate microsoft JWTs.
Link to JWT class from firebase: https://github.com/firebase/php-jwt
Call JWT::Decode with param 1 of your JWT, param 2 of this public key array and param three of an array of just 'RS256'.
JWT::decode($string_JSONWebToken, $array_publicKeysWithKIDasArrayKey, array('RS256'));
This will throw an exception if the JWT is invalid or return a decrypted JWT for you to use (and check the claims).
If you want to verify the jwt then go to jwt.io
This will allow you to paste the JWT and it will then verify the header, claims, and if you add the Public key or private key (depending how the server verifies the signature) it will also verify the signature of the JWT.

What is the best practice for substituting config parameters during testing?

I'm testing a method that uses a public key to encrypt a social security number before it is saved to a database. It looks like this:
public function setSsnAttribute($value)
{
// Load the public key
$public = file_get_contents(Config::get('certificates.public'));
// Attempt to encrypt the social security number using the public key
if (!openssl_public_encrypt($value, $crypted, $public))
{
throw new Exception('Could not encrypt data. Nothing was stored.');
}
// The value of $crypted returned by openssl_public_encrypt contains
// binary characters. Rather than storing the data in a BLOB, I'm
// electing to use base64 encoding to convert it to a string that is
// suitable for storage in the database.
$crypted = base64_encode($crypted);
$this->attributes['ssn'] = $crypted;
}
The issue is with the Config::get('certificates.public') call. I want to make sure that the appropriate exception is thrown if the encryption step fails. The value from Config::get('certificates.public') returns the path to the public certificate that is defined in a config file. My thinking is that the simplest way to test the exception would be to provide a bad path for the public certificate.
I could define an additional parameter in my config file. I'm thinking something along the lines of certificates.test.public.bad would return /dev/null or something like that.
What is the best practice for specifying alternate config parameters during unit testing? Loading the path to the certificate within the setSsnAttribute method seems suspect to me. Is there a more testing-friendly way to load config parameters?
After going back to the Laravel documentation, I realized that I can override any config parameters I need to by simply calling Config::set() on the parameter from within the unit test. For example:
/**
* #expectedException Exception
*/
public function testSsnDecryptionFailureThrowsException()
{
// Replace the private certificate with
Config::set('certificates.private', '/dev/null');
$application = FactoryMuff::create('Lease317\RentalApplication');
// I must access the attribute in order to trigger the decryption
$application->ssn;
}
This works as expected and now I have 100% code coverage on the model.

Validating HMAC using SecurityServiceProvider with Silex

I'm sending an hmac within the URL that I want to valid before allowing users access to the system. There is no user database, so its simply validating the url parameters to verity it was generated by the correct server and users can't change those parameters to access other parts of the system.
I'm wondering if anyone has done something similar with the SecurityServiceProvider. I can do this using the before middleware which is fired after routing and security firewall rules. I'd like to stop this request at the firewall though if possible.
I decided to go with silex's middleware function 'before'. I'm sure this probably isn't the best way to go about this, but my app doesn't have users or authentication so I just need to check the key is correct and return the response. If anyone has any comments on improving this I'd love to hear them.
When an external system is generating a url they must use the shared secret key defined in my config file, and accessible through $app['config']['hmac_key']. the hmac is generated on everything after the hmac in the path. so if ive got sub folders domain.com/folder/hmac/arg1/arg2/arg3. The before filter splits the route at the hmac and builds the path after that.
// Before firing the controller check the hmac matches, otherwise return 403.
$app->before(function (Request $request) use ($app) {
// 40 chars in a sha1 hmac hash
if(!preg_match('/^[0-9a-f]{40}$/i', $request->get('hmac')))
$app->abort(403, "Invalid key.");
// break the route down to the arguments used in hmac
$route = explode('hmac_', $request->get('_route'));
$route = explode('_',$route[1]);
// build the path used to generate hmac
$path = array();
foreach($route as $r)
if($v = $request->get($r))
$path[] = $v;
$path = implode('/', $path);
// Generate hmac hash from path and key
$hmac = hash_hmac("sha1", $path, $app['config']['hmac_key']);
// If the hmac's don't match return 403
if($hmac !== $request->get('hmac'))
$app->abort(403, "Invalid key.");
});

Categories