我一直在使用 gibberish.aes javascript 代码来加密一些字符串,但是当使用诸如 £ 或 á 之类的密码时,openssl 命令行不想解密它并会产生随机性,但它在 javascript 本身中运行良好,有人知道这里发生了什么吗?
例子:
加密文件:U2FsdGVkX18EWZNx70TPi0dYuiQG+7Zpg5RiGa2/mQsWU4A6JhWMwt3+mP1y6+xIQYN45t65oB+VntZfEd6EArB0X4nPmCJ18jBfO57a1jE=
密码:password£
答案1
有多种方法可以将这些字符表示为字节 - 例如,字母“š”{c5 a1}
在使用 UTF-8(JavaScript 使用)编码时变为,但它也可以是{f0}
ISO-8859-13 或 Windows-1257,或{61 01}
UTF-16LE。
因此,您需要确保始终使用相同的文本编码来存储密码(最好是 UTF-8)。具体怎么做取决于编程语言和加密库。某些 API 要求以字节数组形式提供密码,原因正是如此 — 强制开发人员选择特定的编码。
在源代码文件(.py 等)中直接指定带重音字符的密码时,文本编辑器会将它们编码为字节 - 确保您知道它使用的编码,并尽可能尝试使用 UTF-8。如果不可能,请使用\x
或\u
转义来编写带重音字符。例如(Py2/Py3):
passphrase = u"password£".encode("utf-8")
passphrase = u"password\u00A3".encode("utf-8")
passphrase = b"password\xC2\xA3" # byte array – already encoded
在某些语言中,编译器/解释器将再次解码源文件,因此请确保它知道编辑器使用了什么编码(例如,在 Python 中# encoding: utf-8
在顶部添加一行)。
当直接在命令行上工作时,从按键到字节的编码由你的终端应用程序,因此请确保它处于 UTF-8 模式。命令行 shell (bash) 也应该有 $LANG 告诉它使用 UTF-8。(终端内运行的所有程序都已接收一系列字节;它们无法控制终端使用的编码。)
如果有疑问,请尝试将密码发送到“hexdump”工具,hd
例如xxd
:
良好 (UTF-8):
$ echo -n password£á | hexdump -C 00000000 70 61 73 73 77 6f 72 64 c2 a3 c3 a1 |password....|
错误(ISO-8859-1):
$ echo -n password£á | hexdump -C 00000000 70 61 73 73 77 6f 72 64 a3 e1 |password..|
我使用以下方法测试了您的输入:
echo "U2FsdGVkX18EWZNx70TPi0dYuiQG+7Zpg5RiGa2/mQsWU4A6JhWMwt3+mP1y6+xIQYN45t65oB+VntZfEd6EArB0X4nPmCJ18jBfO57a1jE=" \
| base64 -d \
| openssl enc -aes-256-cbc -d -md md5 -k "password£"
也:
#!/usr/bin/env python3
from base64 import b64decode
from Crypto.Hash import MD5
from Crypto.Cipher import AES
def OpenSSL_parse_enc_header(data):
if data[0:8] != b"Salted__":
raise ValueError("missing OpenSSL header")
salt = data[8:16]
data = data[16:]
return salt, data
def OpenSSL_EVP_BytesToKey(passphrase, salt, key_size, iv_size):
buf = b""
hash = b""
while len(buf) < key_size + iv_size:
hash = MD5.new(hash + passphrase + salt).digest()
buf += hash
key = buf[0:key_size]
iv = buf[key_size:key_size+iv_size]
return key, iv
def PKCS7_remove_padding(data, block_size):
if len(data) % block_size != 0:
raise ValueError("data is not padded")
pad_len = data[-1]
if pad_len < 1 or pad_len > block_size:
raise ValueError("PKCS#7 padding incorrect")
if data[-pad_len:] != bytes([pad_len] * pad_len):
raise ValueError("PKCS#7 padding incorrect")
return data[:-pad_len]
enc_data = b64decode("U2FsdGVkX18EWZNx70TPi0dYuiQG+7Zpg5RiGa2/mQsWU4"
"A6JhWMwt3+mP1y6+xIQYN45t65oB+VntZfEd6EArB0X4nP"
"mCJ18jBfO57a1jE=")
kdf_salt, enc_data = OpenSSL_parse_enc_header(enc_data)
passphrase = "password£".encode("utf-8")
key, iv = OpenSSL_EVP_BytesToKey(passphrase,
kdf_salt,
key_size=256//8,
iv_size=AES.block_size)
plain_data = AES.new(key, AES.MODE_CBC, iv=iv).decrypt(enc_data)
plain_data = PKCS7_remove_padding(plain_data, AES.block_size)
print(plain_data)
在两种情况下,它都会返回此文本(具有有效的 PKCS#7 填充,因此解密成功):
L3scoV8yhgA9tqbXBA2SXTczghGUSGTDsWkakCwgK6jk13TAUfXi