用Laravel编码,用Python解码

用Laravel编码,用Python解码,python,laravel,encryption,openssl,aes,Python,Laravel,Encryption,Openssl,Aes,我在用拉威尔的方法加密我网站上的一些数据。这使用OpenSSL的256位AES-CBC加密,而不进行任何序列化。我现在正试图用Python解密这些数据,但我一直在得到关于密钥长度的错误,似乎不知道为什么 Example data to decrypt: eyJpdiI6ImdxY0VcLzFodmpISFV4allSWmJDdEpRPT0iLCJ2YWx1ZSI6IkxXd0ZJaUd2bTUweW5pNm0wUjQwOFM2N1wvWEs5SlYrNB4xNlR7Qkh1U3FvPSIsIm1

我在用拉威尔的方法加密我网站上的一些数据。这使用OpenSSL的256位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:error AES密钥长度不正确(60字节)
,所以我不确定我做错了什么。我尝试过填充/取消添加数据/键,但这似乎没有改变任何事情。我想知道我是否从Laravel获得了用于解密的错误密钥,但从链接文档中可以看出,它应该只是我的.env文件中的APP_密钥

如果有人能帮我或给我指出正确的方向,那将是令人惊讶的

这个问题与其他类似的问题不同,因为我主要是想弄清楚我是否从Laravel那里得到了正确的AES密钥,实际上我并不太需要帮助解密,我只是觉得我从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)
print语句现在打印一些字节,但是当我在上面运行.decode()时,我得到一个错误:
UnicodeDecodeError:'utf-8'编解码器无法解码位置0:invalid start byte
中的字节0xfa,并且似乎无法理解我需要做什么才能将其打印为字符串

问题:…试图用Python解密该数据,但我不断收到有关密钥长度的错误

在执行
.b64解码(…

示例代码
.encode(…
解码(…
按预期工作。
结论:钥匙没有问题

key = b"/AZejP0lh3McL/+Vy5yZcADdTcR65qnx5Jqinuw7raK="
key = base64.b64decode(key)

但是使用您的代码,我得到了与
IV
参数相关的TypeError

  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()
,导致值错误,与
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
这导致了

错误3表示“错误数据不足”

根据链接的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测试

问题:…试图用Python解密该数据,但我不断收到有关密钥长度的错误

在执行
.b64解码(…

示例代码
.encode(…
解码(…
按预期工作。
结论:钥匙没有问题

key = b"/AZejP0lh3McL/+Vy5yZcADdTcR65qnx5Jqinuw7raK="
key = base64.b64decode(key)

但是使用您的代码,我得到了与
IV
参数相关的TypeError

  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()
,导致值错误,与
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
这导致了

错误3表示“错误数据不足”

根据链接的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进行测试

我注意到它已经有一段时间没有激活了,但我正在尝试做同样的事情,似乎无法让它工作

我注意到,Laravel存储的编码密码字符串是一个Base64编码的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'编解码器无法解码位置0中的字节0xfa:无效的开始字节

这是我的完整代码

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
您将在dec_pass中获得解密的密码

请注意,有时Laravel会在base64中生成密钥。在这种情况下,字符串将类似于
base64:sdfsdjfhjsdf32
,然后您必须首先解码


干杯!

我注意到这已经有一段时间没有被激活了,但我正在尝试做同样的事情,似乎无法让它工作

我注意到,Laravel存储的编码密码字符串是一个Base64编码的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'编解码器无法解码位置0中的字节0xfa:无效的开始字节

这是我的完整代码

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
您将在dec_pass中获得解密的密码

请注意,有时Laravel会在base64中生成密钥。在这种情况下,字符串将类似于
base64:sdfsdjfhjsdf32
,然后您必须首先解码


干杯!

带有MAC验证的完整工作代码

除了Gonzalo的提交之外,Laravel的加密消息是一个base64 json编码数组,由以下密钥对组成:

[
      'iv' => 'generated initialization vector (iv)',
      'value' => 'encrypted, base64ed, signed value',
      'mac'  => 'message authentication code (mac)'
]
使用消息身份验证码(MAC)对“值”进行签名,以验证该值在传输过程中未发生更改

应从有效负载(加密消息)中提取的MAC应与 mac从“值”中提取(这可以使用密钥、iv和值完成)。可以在GitHub上找到Laravel的加密方案:

参考关于Laravel的讨论,我在Github上找到了一个部分解决方案:(这是一个分支)

我已经放弃了奥利安的密码和修正