Skip to content

Instantly share code, notes, and snippets.

Created June 4, 2015 13:52
Show Gist options
  • Save fideloper/c4806c504e46e8cdb00a to your computer and use it in GitHub Desktop.
Save fideloper/c4806c504e46e8cdb00a to your computer and use it in GitHub Desktop.
Decrypt Laravel-encrypted value
import os
import base64
import json
from Crypto.Cipher import AES
from phpserialize import loads
def decrypt(payload):
data = json.loads(base64.b64decode(payload))
value = base64.b64decode(data['value'])
iv = base64.b64decode(data['iv'])
return unserialize(mcrypt_decrypt(value, iv))
def mcrypt_decrypt(value, iv):
return crypt_object.decrypt(value)
def unserialize(serialized):
return loads(serialized)
Copy link

fideloper commented Apr 13, 2020 via email

Copy link

Thanks for your reply. Let me check it

Copy link

mcfoi commented Apr 21, 2020

Laraves sems to be using 256 bit since a while

So I tested the above code in the "php artisan tinker" console, by replacing:
key = b"tZMp17lQI70EEYqCsQfwLzlHm6tyaYWPAX66n7YA8KI="

where tZMp17lQI70EEYqCsQfwLzlHm6tyaYWPAX66n7YA8KI= is a string generated issuing the Laravel command

php artisan key:generate

that adds to Laravel's .env a line like:


I took just the part after "base64:".

With these small changes, I got the same error as @adamilleriam:
(repeated with both AES.key_size=256 or AES.key_size=128) : same error.

Traceback (most recent call last):
  File "", line 35, in <module>
    decrypted = decrypt(payload)
  File "", line 14, in decrypt
    return unserialize(mcrypt_decrypt(value, iv))
  File "", line 21, in mcrypt_decrypt,mode=AES.MODE_CBC,IV=iv)
  File "C:\Users\mcfoi\Desktop\pycrypt\venv\lib\site-packages\Crypto\Cipher\", line 232, in new
    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
  File "C:\Users\mcfoi\Desktop\pycrypt\venv\lib\site-packages\Crypto\Cipher\", line 79, in _create_cipher
    return modes[mode](factory, **kwargs)
  File "C:\Users\mcfoi\Desktop\pycrypt\venv\lib\site-packages\Crypto\Cipher\", line 274, in _create_cbc_cipher
    cipher_state = factory._create_base_cipher(kwargs)
  File "C:\Users\mcfoi\Desktop\pycrypt\venv\lib\site-packages\Crypto\Cipher\", line 92, in _create_base_cipher
    if len(key) not in key_size:
TypeError: argument of type 'int' is not iterable

Copy link

mcfoi commented Apr 21, 2020

Some hints:

  1. In 2020 we should rely on
    as original pakage pycrypt is no longer developed
    so use
    pip install pycryptodome

  2. While relying on pycryptodome, using in code:
    is EVIL as causes over-writing an internal list meant to check key size and this ultimately causes the reported error:

  File "C:\Users\mcfoi\Desktop\pycrypt\venv\lib\site-packages\Crypto\Cipher\", line 97, in _create_base_cipher
    if len(key) not in key_size:
TypeError: argument of type 'int' is not iterable

..stay tuned.. .. I am adding details here in future EDITS

Copy link

mcfoi commented Apr 21, 2020


Decode in Python a string encoded in Laravel 6.x

String ENCODED in Laravel 6.x with default pakage
and command like:
$encrypted = Crypt::encrypt('Hello world.');
Test in 
php artisan tinker
>>use Illuminate\Support\Facades\Crypt;
>>$encrypted = Crypt::encrypt('Hello world.');

Strings DECODED in Python 3.7 (64bit) with just following requirements:


NOTE: avoid using in Laravel
$encrypted = Crypt::encryptString('Hello world.');
as this does NOT serializes strings :  not-serialized strings are not handled by this script.
import os
import base64
import json
from Crypto.Cipher import AES
from phpserialize import loads

def decrypt(laravelEncrypedStringBase64, laravelAppKeyBase64):
    # Decode from base64 Laravel encrypted string
    dataJson = base64.b64decode(laravelEncrypedStringBase64)
    # Load JSON
    data = json.loads(dataJson)
    # Extract actual encrypted message from JSON (other parts are IV and Signature)
    value =  base64.b64decode(data['value'])
    # Extract Initialization Vector from JSON (required to create an AES decypher)
    iv = base64.b64decode(data['iv'])
    # Decode 
    key = base64.b64decode(laravelAppKeyBase64)  # Laravel KEY comes base64Encoded from .env!
    # Create an AES decypher
    decrypter = aesDecrypterCBC(iv, key)
    # Finally decypher the message
    decriptedSerializedMessage = decrypter.decrypt(value)
    # deserialize message
    try :
        # Attempt to deserialize message incase it was created in Laravel with Crypt::encrypt('Hello world.');
        decriptedMessage = unserialize(decriptedSerializedMessage)
        return str(decriptedMessage)
        raise Exception("Check you cyphered strings in Laravel using Crypt::encrypt() and NOT Crypt::encryptString()")

def aesDecrypterCBC(iv, _key):
    decrypterAES_CBC =,mode=AES.MODE_CBC,IV=iv)
    return decrypterAES_CBC

def unserialize(serialized):
    return loads(serialized)
if __name__ == "__main__":
    laravelAppKeyBase64 = b"tZMp17lQI70EEYqCsQfwLzlHm6tyaYWPAX66n7YA8KI="
    # Following string is obtained with: $encrypted = Crypt::encrypt('Hello world.');
    laravelEncrypedString = b"eyJpdiI6ImZTQnQ0VEF1NkdWVXdneXRjXC85RjdBPT0iLCJ2YWx1ZSI6IlIxcjhkNDVOZFV3djZLMVVmK0RZQkFYTjBOelpxMEtEYmRRdlBlbHhIcnM9IiwibWFjIjoiNzk3NzI2NTQyOGZkYWRlN2NjZjBiYTUxNWI0YWJlOGU0YjI4MDg2YzI3ZDRlNmMzZTQwOTk3ZTI0YmI2ZTBmYiJ9"
    # Following string is obtained with: $encrypted = Crypt::encryptString('Hello world.'); WILL NOT WORK!!
    #laravelEncrypedString = b"eyJpdiI6Iko0aWpwNFdKU0g2WE95TFlWY2dHaFE9PSIsInZhbHVlIjoiRTFtTG14eTZQbTMrVzZxS0R6OFBEZz09IiwibWFjIjoiYzhhN2VlNThmNDczNGM2M2M5ZDJiNzQ4ZjEzM2MxMDg2M2FmMzFmZTgwNjE3NDYyOWEzYzU1NTNmMmU2OWRjYSJ9"
    decrypted = decrypt(laravelEncrypedString, laravelAppKeyBase64)

Copy link

Thanks @mcfoi
it's working for me also :)

Copy link

temkovs commented Nov 24, 2020

Hello ^_^

I am seeing this a bit later, but I was looking for this same thing and now that I have tried it it has problems with the "json.loads" part.

Here is the exception I am getting

Traceback (most recent call last):
File "C:\Users\PC\AppData\Roaming\npm\node_modules\serverless\lib\plugins\aws
invokeLocal\runtimeWrappers\", line 86, in

result = handler(input['event'], context)

File ".\", line 52, in sendMailSMTP
print(decrypt(secret, app_key))
File ".\", line 98, in decrypt
data = json.loads(dataJson)
File "C:\Users\PC\Anaconda3\lib\", line 343, in loads

s = s.decode(detect_encoding(s), 'surrogatepass')

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8c in position 5: invalid
start byte

Can someone please help me with this, thanк you in advance

Copy link

any update on the Crypt::encryptString hash?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment