В базе данных у меня есть электронные письма пользователей, которые зашифрованы в бэкэнде с использованием библиотеки Java Jasypt с конфигурацией по умолчанию. Насколько я понимаю, он использует PBEWITHMD5 и DES и 1000 итераций для генерации ключа.
@Bean
StringEncryptor encryptor() {
StandardPBEStringEncryptor spbe = new StandardPBEStringEncryptor();
spbe.setPassword(symmetricKey);
return spbe;
}
Затем шифратор используется следующим образом:
@Before("insertAccount(account)")
public void beforeInsertAccount(Account account) {
account.setFirstName(encryptor.encrypt(StringUtils.defaultString(account.getFirstName())));
account.setPhone(encryptor.encrypt(StringUtils.defaultString(account.getPhone())));
account.setEmail(encryptor.encrypt(StringUtils.defaultString(account.getEmail())));
}
В AWS Glue (инструмент ETL) мне нужно расшифровать электронные письма пользователей или, по крайней мере, сопоставить зашифрованные электронные письма из двух разных таблиц. У меня есть возможность определить собственное преобразование, создав скрипт Python3.
На основе этого я написал скрипт: https://gist.github.com/jpralves/505e653fd1c7358ad2c540e25e1ee80a Он использует библиотеку pycryptodome. Переменная data_to_decrypt инициализируется с помощью jasypt-encrypted '[email protected]' с использованием пароля 'test'.
def MyTransform (glueContext, dfc) -> DynamicFrameCollection:
from Crypto.Hash import MD5
from Crypto.Cipher import DES
import base64
import sys
from pyspark.sql.functions import lit
newdf = dfc.select(list(dfc.keys())[0]).toDF()
data_to_decrypt = base64.b64decode("epncHsHYRZd8uIWncULit//8f0mhk8pn")
password = "test"
bs = 8
_iterations = 1000
salt = data_to_decrypt[:bs]
data = data_to_decrypt[bs:]
hasher = MD5.new()
result = hasher.digest()
hasher.update(bytearray(password.encode()))
hasher.update(bytearray(salt))
for i in range(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:bs], DES.MODE_CBC, result[bs:bs*2])
decrypted = encoder.decrypt(bytes(data))
length = len(decrypted)
unpadding = int(decrypted[length-1])
decryptedEmail = ''
if length - unpadding > 0:
decryptedEmail = decrypted[:(length - unpadding)].decode("latin")
else:
decryptedEmail = decrypted.decode("latin")
newdf = newdf.withColumn('decryptedEmail', lit(decryptedEmail))
dyf_filtered = DynamicFrame.fromDF(newdf, glueContext, "aaa")
return(DynamicFrameCollection({"CustomTransform0": dyf_filtered}, glueContext))
Скрипт выдает какую-то ерунду типа "’€ ‡>— ¦х8Þûð›7e". Когда я попытался декодировать выходную строку из кодировщика в любой другой кодировке, это не удалось.
Ваша реальная проблема заключается в том, что ваш первый хэш неверен; вам нужно взять .digest
после, выполнив два .update
s. (Ваши повторяющиеся хэши верны.) Кроме того, ваша распаковка плохая: заполнение PKCS5 не должно превышать один блок, который для DES составляет 8 байтов. Еще лучше было бы проверить все байтов заполнения, если их больше 1, но я не стал заморачиваться.
$ cat 71576901.py3
from Crypto.Hash import MD5
from Crypto.Cipher import DES
import base64
data_to_decrypt = base64.b64decode("epncHsHYRZd8uIWncULit//8f0mhk8pn")
password = "test"
bs = 8
_iterations = 1000
salt = data_to_decrypt[:bs]
data = data_to_decrypt[bs:]
hasher = MD5.new()
hasher.update(bytearray(password.encode()))
hasher.update(bytearray(salt))
result = hasher.digest() # moved down
for i in range(1, _iterations):
hasher = MD5.new()
hasher.update(result)
result = hasher.digest()
encoder = DES.new(result[:bs], DES.MODE_CBC, result[bs:bs*2])
decrypted = encoder.decrypt(bytes(data))
length = len(decrypted)
unpadding = int(decrypted[length-1])
if unpadding > 0 and unpadding <= bs: # better check
print (decrypted[:-unpadding].decode('latin1')) # or other decoding depending on what you encrypted
else:
print ('bad') # might better raise, but TBD
$ python3 71576901.py3
[email protected]
И просто убедитесь, что вы знаете, что это очень слабое шифрование и его легко взломать — но это вопрос безопасности, а не программирования, и здесь это оффтоп.
Большое спасибо, это работает! Я знаю, что это устаревшее шифрование — это старые данные, и мы знаем об этом.