-
-
Save fideloper/c4806c504e46e8cdb00a to your computer and use it in GitHub Desktop.
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): | |
AES.key_size=128 | |
key=os.environ['APP_KEY'] | |
crypt_object=AES.new(key=key,mode=AES.MODE_CBC,IV=iv) | |
return crypt_object.decrypt(value) | |
def unserialize(serialized): | |
return loads(serialized) |
HERE IS A TESTED WORKING SCRIPT
"""
Decode in Python a string encoded in Laravel 6.x
String ENCODED in Laravel 6.x with default pakage
Illuminate\Support\Facades\Crypt
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:
phpserialize==1.3
pycryptodome==3.9.7
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)
except:
raise Exception("Check you cyphered strings in Laravel using Crypt::encrypt() and NOT Crypt::encryptString()")
def aesDecrypterCBC(iv, _key):
decrypterAES_CBC = AES.new(key=_key,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)
print(decrypted)
Thanks @mcfoi
it's working for me also :)
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\invoke.py", line 86, in
result = handler(input['event'], context)
File ".\sendMail.py", line 52, in sendMailSMTP
print(decrypt(secret, app_key))
File ".\sendMail.py", line 98, in decrypt
data = json.loads(dataJson)
File "C:\Users\PC\Anaconda3\lib\json_init_.py", 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
any update on the Crypt::encryptString hash?
Some hints:
In 2020 we should rely on
https://pycryptodome.readthedocs.io/en/latest/src/installation.html
as original pakage pycrypt is no longer developed
so use
pip install pycryptodome
While relying on pycryptodome, using in code:
AES.key_size=256
is EVIL as causes over-writing an internal list meant to check key size and this ultimately causes the reported error:
..stay tuned.. .. I am adding details here in future EDITS