Тип кодирования и проблема с ключом в шифровании Bouncy castle AES

#c# #encoding #bouncycastle

#c# #кодирование #bouncycastle

Вопрос:

Я использую криптографические библиотеки Bouncy Castle. У меня есть 13-символьный ключ, что-то вроде string key = «wergt543jusft»; Текст, подлежащий шифрованию: string plain = «435625241526373»;

Я конвертирую его в 128-битный ключ, используя следующий метод.

 public string getKeyMessageDigest(string key)
{
    byte[] ByteData = Encoding.ASCII.GetBytes(key);

    //MD5 creating MD5 object.
    MD5 oMd5 = MD5.Create();
    byte[] HashData = oMd5.ComputeHash(ByteData);

    //convert byte array to hex format
    StringBuilder oSb = new StringBuilder();
    for (int x = 0; x < HashData.Length; x  )
    {
        //hexadecimal string value
        oSb.Append(HashData[x].ToString("x2"));
    }
    return Convert.ToString(oSb);
}
  

Затем я создаю объект класса AESEncryption, который я определил

 AESEncryption aes = new AESEncryption(Encoding.ASCII, new Pkcs7Padding());
  

Класс AESEncryption имеет два метода:

 public string Encrypt(string plain, string key)
{
    string hashKey = getKeyMessageDigest(key);
    BCEngine bcEngine = new BCEngine(new AesEngine(), _encoding);
    bcEngine.SetPadding(_padding);
    return bcEngine.Encrypt(plain, hashKey);
}

public string Decrypt(string plain, string key)
{
    string hashKey = getKeyMessageDigest(key);
    BCEngine bcEngine = new BCEngine(new AesEngine(), _encoding);
    bcEngine.SetPadding(_padding);
    return bcEngine.Decrypt(plain, hashKey);
}
  

Все работает нормально.

Но, когда я меняю тип кодировки на что-либо другое, кроме ASCII, я получаю сообщение об ошибке «Длина ключа не 128/192/256 бит».. Я внес следующие изменения в свой код, чтобы изменить тип кодировки:

 public string getKeyMessageDigest(string key)
{
    byte[] ByteData = Encoding.UTF32.GetBytes(key);
    //MD5 creating MD5 object.
    MD5 oMd5 = MD5.Create();
    byte[] HashData = oMd5.ComputeHash(ByteData);

    //convert byte array to hex format
    StringBuilder oSb = new StringBuilder();
    for (int x = 0; x < HashData.Length; x  )
    {
        //hexadecimal string value
        oSb.Append(HashData[x].ToString("x2"));
    }
    return Convert.ToString(oSb);
}
  

И

 AESEncryption aes = new AESEncryption(Encoding.UTF32, new Pkcs7Padding());
  

Остальная часть кода остается прежней. Кто-нибудь может подсказать, пожалуйста?

Заранее спасибо…

Я перехожу по ссылке:http://elian.co.uk/post/2009/07/29/Bouncy-Castle-CSharp.aspx

Моя цель — сгенерировать зашифрованную строку для переменной plian = «435625241526373», используя все типы кодировки, такие как: ASCII, BigEndianUnicode, Unicode, UTF32, UTF7, UTF8

[Редактировать из комментариев]Исключение генерируется внутри этого метода:

 private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, string key)
{ 
    try 
    { 
        cipher = _padding == null ?
            new PaddedBufferedBlockCipher(_blockCipher) : 
            new PaddedBufferedBlockCipher(_blockCipher, _padding);

        byte[] keyByte = _encoding.GetBytes(key);
        _cipher.Init(forEncrypt, new KeyParameter(keyByte));
        return _cipher.DoFinal(input);

    }
    catch (Org.BouncyCastle.Crypto.CryptoException ex)
    {
        throw new CryptoException(ex.Message); 
    } 
} 
  

Комментарии:

1. В какой строке вы получаете эту ошибку? Длина хэша MD5 всегда будет составлять 128 бит, независимо от длины ключа или кодировки, поэтому неясно, как вы могли бы получить такую ошибку.

2. @Hari: в каком классе / методе это? Я не вижу _cipher поля в примере. Кроме того, AESEncryption это название этого класса, которое вы написали (содержащее методы Encrypt и Decrypt )?

3. Если вы ссылаетесь на ссылку Bouncy Castle (класс BCEngine), то это метод, называемый BouncyCastleCrypto (bool forEncrypt, ввод byte[], строковый ключ). Я получаю ошибку в строке => _cipher. Инициализация (для шифрования, новый ключевой параметр (keyByte));

4. Также хотел сказать вам, что я могу зашифровать / расшифровать строку для ASCII, UTF7 и UTF8. Это только в случае других типов кодировки, где я получаю эту ошибку.

5. @Hari: вы можете проверить мой ответ. Кодировку, используемую в данных сообщения, не следует использовать для кодирования ключа, поскольку это не гарантирует, что массив будет иметь постоянную длину для разных входных данных. Другими словами, хеширование ключа будет самым простым решением, поскольку оно дает постоянную длину хэша для любого ключа.

Ответ №1:

Вам нужно убедиться, что ваш ключ имеет длину 128/192/256 бит. Точно так же, как вы использовали методы getKeyMessageDigest inside Encrypt и Decrypt , вы можете использовать его внутри try/catch предложения для создания 128-битного хэш-значения вашего ключа:

 private byte[] BouncyCastleCrypto(bool forEncrypt, byte[] input, string key)
{ 
    try 
    { 
        cipher = _padding == null ?
            new PaddedBufferedBlockCipher(_blockCipher) : 
            new PaddedBufferedBlockCipher(_blockCipher, _padding);

        // this line will make sure keyByte is 16 bytes long
        byte[] keyByte = getKeyMessageDigest(key);

        _cipher.Init(forEncrypt, new KeyParameter(keyByte));

        return _cipher.DoFinal(input);          
    }
    catch (Org.BouncyCastle.Crypto.CryptoException ex)
    {
        throw new CryptoException(ex.Message); 
    } 
} 
  

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

Хэш MD5 всегда содержит 16 байт, независимо от размера ввода. Итак, единственная проблема заключается в том, используете ли вы Encoding.GetBytes для получения ключа, поскольку этот метод возвращает разную длину массива для разных кодировок.

Комментарии:

1. Привет, Груо, большое спасибо за своевременную помощь. Ваше предложение сделало свое дело. Я внес некоторые изменения в свой метод getKeyMessageDigest => общедоступный байт [] getKeyMessageDigest (строковый ключ) { byte[] ByteData = Encoding. Юникод. Получаем байты (ключ); //MD5 создаем объект MD5. MD5 oMd5 = MD5.Create(); byte[] HashData = oMd5.ComputeHash(байтовые данные); возвращает хэш-данные; }