Расшифровка текста из библиотеки Java jasypt с помощью Python3

В базе данных у меня есть электронные письма пользователей, которые зашифрованы в бэкэнде с использованием библиотеки 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". Когда я попытался декодировать выходную строку из кодировщика в любой другой кодировке, это не удалось.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
32
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваша реальная проблема заключается в том, что ваш первый хэш неверен; вам нужно взять .digestпосле, выполнив два .updates. (Ваши повторяющиеся хэши верны.) Кроме того, ваша распаковка плохая: заполнение 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]

И просто убедитесь, что вы знаете, что это очень слабое шифрование и его легко взломать — но это вопрос безопасности, а не программирования, и здесь это оффтоп.

Большое спасибо, это работает! Я знаю, что это устаревшее шифрование — это старые данные, и мы знаем об этом.

mdziob 22.03.2022 23:54

Другие вопросы по теме