Большая часть данных в базе данных, которую я взял, содержит зашифрованные поля. Метод, используемый для шифрования данных, представляет собой следующий код PHP:
<?php
$text = "test 1234\ntest 2345\ntest 3456\ntest 4567";
$key = "0123456789abcdefghijklmnopqrstuv";
$enc = openssl_encrypt($text, "AES-256-CBC", $key);
echo "Raw: " . $text . "\n";
echo "Key: " . $key . "\n";
echo "Key (Hex) " . bin2hex($key) . "\n";
echo $enc;
echo "\n";
?>
Когда я запускаю код, я получаю следующий вывод, включая предупреждение о пустом векторе инициализации (iv), который я должен игнорировать, потому что все данные БД зашифрованы таким образом (я прекрасно знаю, что это не должно быть сделано таким образом).
Warning: openssl_encrypt(): Using an empty Initialization Vector (iv) is potentially insecure and not recommended in /tmp/cp3_encdec/enc2.php on line 5
Raw: test 1234
test 2345
test 3456
test 4567
Key: 0123456789abcdefghijklmnopqrstuv
Key (Hex) 303132333435363738396162636465666768696a6b6c6d6e6f70717273747576
uPNXdo2K0Gvy/+MW0YFR7utFsrNDAp8yYaDxT352W3lPKNOkNMg+l3eFKEi0zeze
Расшифровать с помощью php openssl_decrypt($encrypted, "AES-256-CBC", $key)
дает мне полный вывод. Руководство по php не дает большого понимания того, что используется для шифрования в отношении заполнения и iv, когда эти значения остаются пустыми.
Затем я попытался расшифровать в командной строке, используя команду openssl:
echo "uPNXdo2K0Gvy/+MW0YFR7utFsrNDAp8yYaDxT352W3lPKNOkNMg+l3eFKEi0zeze" | openssl aes-256-cbc -d -a -K 303132333435363738396162636465666768696a6b6c6d6e6f70717273747576 -iv 0
который отлично работает и возвращает начальный вход:
test 1234
test 2345
test 3456
test 4567
Попытка расшифровки в Python с использованием следующего кода приводит к неправильной расшифровке:
import base64
from Crypto.Cipher import AES
PAD = u'\0000'
def decrypt(enc, key):
decobj = AES.new(key, AES.MODE_ECB)
data = decobj.decrypt(base64.b64decode(enc))
data = data.rstrip(PAD.encode())
print(str(data))
key = "0123456789abcdefghijklmnopqrstuv"decrypt("uPNXdo2K0Gvy/+MW0YFR7utFsrNDAp8yYaDxT352W3lPKNOkNMg+l3eFKEi0zeze", key)
Результат, первые 16 байтов читаются, но не остальные:
b'test 1234\ntest 2\x8b\xc7b|\xf9\xef\xa3\x1f\xd2\xcc\xd7#\xe7\x8b%\x8b\x981\x92\x87v4\xa8;h\xa9\xf8Fw\x7fRp'
Изменение моего ввода, чтобы он содержал больше данных, также нарушит расшифровку с помощью команды openssl:
Raw: [system] test:1234
[system] test:2345
[database] test:3456
[unknown] test:4567
Key: 0123456789abcdefghijklmnopqrstuv
Key (Hex) 303132333435363738396162636465666768696a6b6c6d6e6f70717273747576
9KWsGGLa1/g3f36kUJJ/oHNiEnIDorZULwR8pXZHwJhul2XsdZLwLN8jMptP9fcWgY42oTq7RTm+/8CKPiGFPWrY/3neLvf8UNedsVuKRlc=
Командная строка Openssl:
echo "9KWsGGLa1/g3f36kUJJ/oHNiEnIDorZULwR8pXZHwJhul2XsdZLwLN8jMptP9fcWgY42oTq7RTm+/8CKPiGFPWrY/3neLvf8UNedsVuKRlc=" | openssl aes-256-cbc -d -a -K 303132333435363738396162636465666768696a6b6c6d6e6f70717273747576 -iv 0
bad decrypt
15143:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:/BuildRoot/Library/Caches/com.apple.xbs/Sources/OpenSSL098/OpenSSL098-64/src/crypto/evp/evp_enc.c:323:
То же самое, используя приведенный выше код Python, даст первые 16 байт для чтения, но не для остальных:
b'[system] test:12\xc7\x91\xa6C\x11\xa3\xa4\x8cR\x12#\x84$\xf7\x0c\xd4IP!F6\xa8\xed0Np\x1d\xc7\x174\xa5\xc5N\xe3\x00\x9f\x01\xa8\xc3\x18\xea\x158\xc0:\x9b\x9cx\xee\xf9X\xfc\x1a\xcf J\xca\xc5\xf4\xbf\x08\x16\x8f<'
Опять же, если работает php openssl_decrypt:
<?php
$text = "9KWsGGLa1/g3f36kUJJ/oHNiEnIDorZULwR8pXZHwJhul2XsdZLwLN8jMptP9fcWgY42oTq7RTm+/8CKPiGFPWrY/3neLvf8UNedsVuKRlc=";
$key = "0123456789abcdefghijklmnopqrstuv";
$dec = openssl_decrypt($text, "AES-256-CBC", $key);
echo $dec;
echo "\n";
?>
[system] test:1234
[system] test:2345
[database] test:3456
[unknown] test:4567
У кого-то есть идея, как php шифрует данные, я полагаю, что это проблема заполнения, но я не уверен, и я открыт для любой помощи по этой теме.
Я сделал некоторые изменения в своем коде Python, который, кажется, решил проблему:
import base64
from Crypto.Cipher import AES
IV = 16 * '\x00'
def decrypt(enc, key):
decobj = AES.new(key, AES.MODE_CBC, IV)
data = decobj.decrypt(base64.b64decode(enc))
print(str(data.decode()))
key = "0123456789abcdefghijklmnopqrstuv"decrypt("uPNXdo2K0Gvy/+MW0YFR7utFsrNDAp8yYaDxT352W3lPKNOkNMg+l3eFKEi0zeze", key)
В командной строке я пока не нашел решения.
Других решений пока нет …