Decrypt Laravel-encrypted value
import base64 | |
import json | |
from phpserialize import loads | |
import hashlib | |
import hmac | |
from Crypto.Cipher import AES | |
def decrypt(payload, key): | |
""" | |
Decrypt strings that have been encrypted using Laravel's encrypter (AES-256 encryption). | |
Plain text is encrypted in Laravel using the following code: | |
>>> ciphertext = Crypt::encrypt('hello world'); | |
The ciphertext is a base64's json-encoded array consisting of the following keys: | |
[ | |
'iv' => 'generated initialization vector (iv)', | |
'value' => 'encrypted, base64ed, signed value', | |
'mac' => 'message authentication code (mac)' | |
] | |
The 'value' is signed using a message authentication code (MAC) so verify that the value has not changed during | |
transit. | |
Parameters: | |
payload (str): Laravel encrypted text. | |
key (str): Encryption key (base64 decoded). Make sure 'base64:' has been removed from string. | |
Returns: | |
str: plaintext | |
""" | |
data = json.loads(base64.b64decode(payload)) | |
if not valid_mac(key, data): | |
return None | |
value = base64.b64decode(data['value']) | |
iv = base64.b64decode(data['iv']) | |
return unserialize(mcrypt_decrypt(value, iv, key)).decode("utf-8") | |
def mcrypt_decrypt(value, iv, key): | |
AES.key_size=128 | |
crypt_object=AES.new(key=key,mode=AES.MODE_CBC,IV=iv) | |
return crypt_object.decrypt(value) | |
def unserialize(serialized): | |
return loads(serialized) | |
def valid_mac(key, data): | |
dig = hmac.new(key, digestmod=hashlib.sha256) | |
dig.update(data['iv'].encode('utf8')) | |
dig.update(data['value'].encode('utf8')) | |
dig = dig.hexdigest() | |
return dig==data['mac'] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Thank you so much for this example, have been searching for hours to find something to decode Laravel stored data.
I installed Python (3.8) and Visual C++ components.
If I add:
print(decrypt(payload, key)) (where payload and key are strings), the script runs but gives 'none' as answer.
I have the feeling I am really close, but missing somehting.
Any help is massively appreciated