Расшифровать строку с помощью BC

У меня есть веб-приложение, написанное с использованием Grails 6.1.2. Мне нужно зашифровать пару полей в базе данных, поэтому я решил использовать Grails-jasypt, основанный на знаменитой библиотеке jasypt. Отлично работает.

Теперь мне нужно написать небольшое приложение на C#, и мне нужно получить доступ к БД, чтобы прочитать некоторые из этих зашифрованных полей. Конечно, я знаю свой пароль и алгоритм, используемый веб-приложением, из имеющихся у меня свойств:

jasypt {
    algorithm = "PBEWITHSHA256AND256BITAES-CBC-BC"
    providerName = "BC"
    password = "my-strong-pwd"
    keyObtentionIterations = 1000 }

К сожалению, плагин в Grails скрывает весь код, который использовался для шифрования строки. Я просто добавляю в домен это сопоставление, чтобы наверняка зашифровать и расшифровать то, что мне нужно:

static mapping = { dbPassword type: GormEncryptedStringType } 

Я написал эту статическую функцию на C# для расшифровки строки, полученной из БД:

 public static string Decrypt(string toDecrypt)
    {
        byte[] decoded = Convert.FromBase64String(toDecrypt);
        if (decoded == null || decoded.Length <= 16)
        {
            throw new ArgumentException("Bad input data", "toDecrypt");
        }

        byte[] salt = new byte[16];
        byte[] wrappedKey = new byte[decoded.Length - 16];
        Array.Copy(decoded, 0, salt, 0, 16);
        Array.Copy(decoded, 16, wrappedKey, 0, decoded.Length - 16);

        int iterationCount = 1000;
        string algName = "PBEWITHSHA256AND256BITAES-CBC-BC";

        PbeParametersGenerator generator = new Pkcs5S2ParametersGenerator(new Org.BouncyCastle.Crypto.Digests.Sha256Digest());
        generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(key.ToCharArray()), salt, iterationCount);

        ICipherParameters parameters = generator.GenerateDerivedParameters("AES", 256);

        IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CBC/NoPadding");
        cipher.Init(false, new ParametersWithIV(parameters, new byte[16])); // Assuming 16-byte IV

        byte[] keyText = cipher.DoFinal(wrappedKey);
        return Convert.ToBase64String(keyText);
    }

Это работает, но строка не расшифрована правильно, я мало что знаю о BC, возможно, мне придется изменить строку GetCipher, но я не знаю, чем именно. Я пытаюсь добавить заполнение с помощью AES/CBC/PKCS5Padding, но у меня возникает «блок заполнения поврежден».

Можете ли вы сгенерировать тестовые данные с непродуктивным паролем и опубликовать их? Кроме того, вы должны опубликовать код Grails (часть, касающуюся шифрования).

Topaco 01.04.2024 18:24

Хотелось бы, но использование плагина в Grails скрывает всю сложность, поэтому я его не выложил и не смог найти. Я просто сообщаю об этом в домене, чтобы установить зашифрованное статическое сопоставление поля = { тип dbPassword: GormEncryptedStringType }

NiBE 01.04.2024 18:28

Без кода портирование может быть затруднено. Можете ли вы хотя бы поделиться полными данными испытаний?

Topaco 01.04.2024 18:34

Я вижу @Topaco с полными тестовыми данными, вы имеете в виду пример данных? Я зашифровал эту строку Test1234$$, и результат: Xw4VoIGs7FtD71gVwrDlCweSK7S/Z8ikg39rTxdiOcg=, пароль — dfglhkgfhljktypoio34537567--,dfd435, спасибо!

NiBE 01.04.2024 18:48
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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
4
112
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Расшифровка с помощью PBEWITHSHA256AND256BITAES-CBC-BC реализована некорректно, работает следующая реализация:

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Security;

...

// input data
string algorithm = "PBEWITHSHA256AND256BITAES-CBC-BC";
int iterations = 1000;
string password = "dfglhkgfhljktypoio34537567--,dfd435";
string encryptedDataB64 = "Xw4VoIGs7FtD71gVwrDlCweSK7S/Z8ikg39rTxdiOcg = ";

// separate salt and ciphertext
byte[] encryptedData = Convert.FromBase64String(encryptedDataB64);
byte[] salt = encryptedData[0..16];
byte[] ciphertext = encryptedData[16..];

// decrypt with PBEWITHSHA256AND256BITAES-CBC-BC
IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(algorithm, salt, iterations);
ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(algorithm, password.ToCharArray(), algParams);
cipher.Init(false, cipherParams);
byte[] decrypted = cipher.DoFinal(ciphertext);

// UTF-8 decode and output
Console.WriteLine(Encoding.UTF8.GetString(decrypted)); // Test1234$$

Редактировать:
Приведенная выше реализация использует идентификатор PBEWITHSHA256AND256BITAES-CBC-BC и не требует каких-либо дополнительных детальных знаний алгоритма.

Альтернативный (более низкоуровневый) способ, при котором алгоритм (AES/CBC/PKCS7Padding), получение ключа (PKCS#12) и такие параметры, как размер ключа и размер IV, должны быть явно указаны:

using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Generators;
...
// apply PKCS#12 key derivation and decrypt with AES/CBC/PKCS7Padding
IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CBC/PKCS7Padding");
PbeParametersGenerator generator = new Pkcs12ParametersGenerator(new Sha256Digest());
generator.Init(PbeParametersGenerator.Pkcs12PasswordToBytes(password.ToCharArray()), salt, iterations);
ICipherParameters cipherParams = generator.GenerateDerivedParameters("AES", 256, 128);
cipher.Init(false, cipherParams); 
byte[] decrypted = cipher.DoFinal(ciphertext);

Сравнение второго подхода с вашим кодом показывает, что во-первых вы использовали неправильную деривацию ключа и не был указан размер IV.

работает как шарм, спасибо!! Я попытаюсь выяснить, что не так с моей реализацией, сравнив вашу

NiBE 01.04.2024 19:31

@NiBE — я добавил альтернативный подход, который упрощает сравнение с вашим кодом и устранение неполадок.

Topaco 01.04.2024 20:07

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