Кодировать в Laravel, декодировать в Python
Я использую метод encryptString Laravel для шифрования некоторых данных на моем веб-сайте. Это использует 256-битное шифрование OpenSSL AES-CBC без какой-либо сериализации. Теперь я пытаюсь расшифровать эти данные в Python, но я продолжаю получать ошибки о длине ключа и не могу понять, почему.
Example data to decrypt: eyJpdiI6ImdxY0VcLzFodmpISFV4allSWmJDdEpRPT0iLCJ2YWx1ZSI6IkxXd0ZJaUd2bTUweW5pNm0wUjQwOFM2N1wvWEs5SlYrNB4xNlR7Qkh1U3FvPSIsIm1hYyI6Ijc5ZWM0YTYxYjljZGFiNzgwNjY2NDU1ZmQ5Yjc1ZmJlOGU4NzBkMjQzMzA3MmVhYzE3NzY4ZmU1MWIyMjZlOTQifQ==
Example Key to use for decryption (from laravel .env):
base64:/AZejP0lh3McL/+Vy5yZcADdTcR65qnx5Jqinuw7raK=
Я изменил эти значения, поэтому на самом деле расшифровка с этими значениями не даст никаких реальных данных, просто подумал, что это было бы хорошо, например. Затем я пытаюсь расшифровать эти данные в Python 3.7 с помощью:
import base64
from Crypto.Cipher import AES
def decrypt(enc, key):
IV = 16 * '\x00'
decobj = AES.new(key, AES.MODE_CBC, IV)
data = decobj.decrypt(base64.b64decode(enc))
print(str(data.decode()))
if __name__ == "__main__":
key = b"/AZejP0lh3McL/+Vy5yZcADdTcR65qnx5Jqinuw7raK="
decrypt("eyJpdiI6ImdxY0VcLzFodmpISFV4allSWmJDdEpRPT0iLCJ2YWx1ZSI6IkxXd0ZJaUd2bTUweW5pNm0wUjQwOFM2N1wvWEs5SlYrNB4xNlR7Qkh1U3FvPSIsIm1hYyI6Ijc5ZWM0YTYxYjljZGFiNzgwNjY2NDU1ZmQ5Yjc1ZmJlOGU4NzBkMjQzMzA3MmVhYzE3NzY4ZmU1MWIyMjZlOTQifQ==", key)
И кажется, что это должно работать, но когда я запускаю его, я получаю ошибку: ValueError: Incorrect AES key length (60 bytes)
, поэтому я не уверен, что я делаю неправильно. Я пробовал заполнять / распаковывать данные / ключ, но это, похоже, ничего не меняет. Мне интересно, получаю ли я неправильный ключ для расшифровки от Laravel, но из того, что я мог бы сказать в связанной документации, это должен быть просто APP_KEY в моем .env файл.
Если бы кто-нибудь мог помочь мне или указать мне в правильном направлении, это было бы удивительно!
Этот вопрос является уникальным на другие подобные вопросы, потому что я пытаюсь выяснить, в первую очередь, если я получаю правильный ключ AES. с что Laravel, я на самом деле не слишком нужна помощь в расшифровке, я просто думаю, что я взял не тот ключ с фреймворк Laravel.
Изменить: новый код, который кажется, что он работает:
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
def decrypt(enc, key):
IV = 16 * '\x00'.encode()
decobj = AES.new(key, AES.MODE_CBC, IV)
data = decobj.decrypt(pad(base64.b64decode(enc), 16))
print(base64.b64decode(data))
if __name__ == "__main__":
key = base64.b64decode(b"/AZejP0lh3McL/+Vy5yZcADdTcR65qnx5Jqinuw7raK=")
decrypt("eyJpdiI6ImdxY0VcLzFodmpISFV4allSWmJDdEpRPT0iLCJ2YWx1ZSI6IkxXd0ZJaUd2bTUweW5pNm0wUjQwOFM2N1wvWEs5SlYrNB4xNlR7Qkh1U3FvPSIsIm1hYyI6Ijc5ZWM0YTYxYjljZGFiNzgwNjY2NDU1ZmQ5Yjc1ZmJlOGU4NzBkMjQzMzA3MmVhYzE3NzY4ZmU1MWIyMjZlOTQifQ==", key)
Оператор печати теперь печатает несколько байтов, но когда я запускаю .decode() на нем я получаю ошибку: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfa in position 0: invalid start byte
и не может понять, что мне нужно сделать, чтобы он мог быть напечатан в виде строки.





Ответы - Кодировать в Laravel, декодировать в Python / Encode in Laravel, decode in Python

04.10.2018 03:41:02
Вопрос:...пытаясь расшифровать эти данные в Python, но я продолжаю получать ошибки о длине ключа
Я могу использовать ваш key
, в коде связанного ответа, после выполнения .b64decode(...
.
Пример кода .encode(...
и decode(...
работает как Терп.
Вывод: с вашим ключом все в порядке!
key = b"/AZejP0lh3McL/+Vy5yZcADdTcR65qnx5Jqinuw7raK="
key = base64.b64decode(key)
Но с вашим кодом я получил TypeError, связанный с параметром
IV
:expect_byte_string(iv) File "/usr/local/lib/python3.4/dist-packages/Crypto/Util/_raw_api.py", line 172, in expect_byte_string TypeError: Only byte strings can be passed to C code
Исправлено с
IV = 16 * '\x00'.encode()
, приводит к ValueError, связанному сenc
:data = decobj.decrypt(base64.b64decode(enc)) File "/usr/local/lib/python3.4/dist-packages/Crypto/Cipher/_mode_cbc.py", line 209, in decrypt ValueError: Error 3 while decrypting in CBC mode
Это приводит к проблемам github: 10
Ошибка 3 означает " ERR_NOT_ENOUGH_DATA"
Согласно связанной странице GitHub, вы должны перечитывать документацию о заполнении данных во время кодирования .
Рабочий пример на GitHub:
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
key = b"/AZejP0lh3McL/+Vy5yZcADdTcR65qnx5Jqinuw7raK="
key = base64.b64decode(key)
BLOCK_SIZE = 32
encryption_suite = AES.new(key, AES.MODE_CBC, b'This is an IV...')
cipher_text = encryption_suite.encrypt(pad(b'A really secret message...', BLOCK_SIZE))
decryption_suite = AES.new(key, AES.MODE_CBC, b'This is an IV...')
print(unpad(decryption_suite.decrypt(cipher_text), BLOCK_SIZE).decode())
>>> A really secret message...
Протестировано с Python: 3.4.2


pad(...
перед шифрованием и unpad(...
после расшифровки. Ошибка utf-8
-это результат, который вы pad(...
после кодирования.

29.10.2019 04:31:47
Я замечаю, что это не было активным в течение некоторого времени, но я пытаюсь сделать то же самое и не могу заставить его работать.
Я заметил, что кодированная строка пароля, сохраненная Laravel, является базовым 64-кодированным объектом json, который не был принят во внимание в исходном вопросе:
pass_obj = base64.b64decode('eyJpdiI6ImdxY0VcLzFodmpISFV4allSWmJDdEpRPT0iLCJ2YWx1ZSI6IkxXd0ZJaUd2bTUweW5pNm0wUjQwOFM2N1wvWEs5SlYrNB4xNlR7Qkh1U3FvPSIsIm1hYyI6Ijc5ZWM0YTYxYjljZGFiNzgwNjY2NDU1ZmQ5Yjc1ZmJlOGU4NzBkMjQzMzA3MmVhYzE3NzY4ZmU1MWIyMjZlOTQifQ==')
print(pass_obj)
>>> b'{"iv":"gqcE\\/1hvjHHUxjYRZbCtJQ==","value":"LWwFIiGvm50yni6m0R408S67\\/XK9JV+4\x1e16T{BHuSqo=","mac":"79ec4a61b9cdab780666455fd9b75fbe8e870d2433072eac17768fe51b226e94"}'
Из этого вы можете получить IV и зашифрованное значение, оба, похоже, закодированы в base64. Но я все еще получаю ошибку декодирования в конце, как;
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfa in position 0: invalid start byte
Вот мой полный код;
password = 'eyJpdiI6ImJGNDNNZjN3YWtpcDQ5VEJVXC9IazF3PT0iLCJ2YWx1ZSI6IkNVRW1VQUY1dXArYlFkU3NlY1pnZUE9PSIsIm1hYyI6ImM3ODk0NWQ0NjgxMzM4YjE0M2JhN2MzZWRmOWEwMWJiMjI2Y2FhYmUxYjFhYzAyYjY4YWZkZGE3N2EyMDYwNWYifQ=='
key = 'some secret key that i can't share'.encode()
p_obj = json.loads(base64.b64decode(password).decode())
decobj = AES.new(key, AES.MODE_CBC, base64.b64decode(p_obj['iv']))
data = decobj.decrypt(base64.b64decode(p_obj['value']))
print(data)
>>> b'l\xee:f\x9eZ\x90rP\x99\xca&@\x1d1\x9f'
data.decode()
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xee in position 1: invalid continuation byte
@Pecans ты когда-нибудь это понимал?
Спасибо.
Полный рабочий код править
Я вытерпел это, у меня была проблема с моим ключом изначально. Итак, вот полный фрагмент для дальнейшего использования;
import base64
import json
from phpserialize import unserialize
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
key = b'my secret key'
enc_pass = 'eyJpdiI6ImJGNDNNZjN3YWtpcDQ5VEJVXC9IazF3PT0iLCJ2YWx1ZSI6IkNVRW1VQUY1dXArYlFkU3NlY1pnZUE9PSIsIm1hYyI6ImM3ODk0NWQ0NjgxMzM4YjE0M2JhN2MzZWRmOWEwMWJiMjI2Y2FhYmUxYjFhYzAyYjY4YWZkZGE3N2EyMDYwNWYifQ=='
p_obj = json.loads(base64.b64decode(password).decode())
decobj = AES.new(key, AES.MODE_CBC, base64.b64decode(p_obj['iv']))
data = decobj.decrypt(base64.b64decode(p_obj['value']))
dec_pass = unserialize(unpad(data, 16)).decode()
Вы будете иметь расшифрованный пароль в dec_pass.
Обратите внимание, что иногда Laravel генерирует ключ в base64. В этом случае строка будет чем-то вроде base64:sdfsdjfhjsdf32
, тогда вам нужно сначала декодировать.
Ваше здоровье!

10.11.2019 06:23:46
Полный рабочий код с проверкой MAC
Добавляя к представлению Гонсало, зашифрованное сообщение Laravel представляет собой массив с кодировкой base64 json, состоящий из следующих пар ключей:
[
'iv' => 'generated initialization vector (iv)',
'value' => 'encrypted, base64ed, signed value',
'mac' => 'message authentication code (mac)'
]
"Значение" подписывается с помощью кода проверки подлинности сообщения (MAC), чтобы убедиться, что значение не изменилось во время передачи.
MAC, извлеченный из полезной нагрузки (зашифрованное сообщение) , должен быть проверен на соответствие mac извлекается из "значения" (это можно сделать с помощью ключа, iv и значения). Схему шифрования Laravel можно найти на GitHub: src / Illuminate / Encryption/Encrypter.РНР
Ссылаясь на дискуссионную тему на Laravel, я проследил частичное решение на Github: orian/crypt.py (который является вилкой fideloper/crypt.py ).
Я разветвил код Ориана и исправил проблему с входным параметром. Код работает так, как ожидалось, пока ключ шифрования (переданный в качестве входных данных для decrypt ()) декодируется base64 и не включает ' base64:', который обычно добавляется к назначению строки переменной среды APP_KEY, найденному в .env файл.
Решение : pilatuspc12ng/crypt.py
Фрагмент кода программы crypt.py показано ниже:
import base64
import json
from Crypto.Cipher import AES
from phpserialize import loads
import hashlib
import hmac
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']