Как получить совместимость между C# и Шифрованием AES SQL2k8?

У меня есть Шифрование AES, сделанное на двух столбцах: один из этих столбцов хранится в базе данных SQL Server 2000; другой хранится в базе данных SQL Server 2008.

Поскольку база данных первого столбца (2000) не имеет стандартной функциональности для шифрования / дешифрование, мы решили сделать логику криптографии на прикладном уровне, с классами.NET, для обоих.

Но как база данных второго столбца (2008) позволяют этот вид функциональности, мы хотели бы сделать миграцию данных с помощью функций базы данных, чтобы быть быстрее, так как миграция данных в SQL 2k намного меньше, чем эта секунда, и это продлится больше чем 50 часов из-за того, чтобы быть сделанным на прикладном уровне.

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

Ниже у нас есть вся логика в обеих сторонах.. Конечно, я не показываю ключ, но все остальное - то же:

private byte[] RijndaelEncrypt(byte[] clearData, byte[] Key)
{
    var memoryStream = new MemoryStream();

    Rijndael algorithm = Rijndael.Create();

    algorithm.Key = Key;
    algorithm.IV = InitializationVector;

    var criptoStream = new CryptoStream(memoryStream, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
    criptoStream.Write(clearData, 0, clearData.Length);
    criptoStream.Close();

    byte[] encryptedData = memoryStream.ToArray();
    return encryptedData;
}

private byte[] RijndaelDecrypt(byte[] cipherData, byte[] Key)
{
    var memoryStream = new MemoryStream();

    Rijndael algorithm = Rijndael.Create();

    algorithm.Key = Key;
    algorithm.IV = InitializationVector;

    var criptoStream = new CryptoStream(memoryStream, algorithm.CreateDecryptor(), CryptoStreamMode.Write);

    criptoStream.Write(cipherData, 0, cipherData.Length);

    criptoStream.Close();

    byte[] decryptedData = memoryStream.ToArray();

    return decryptedData;
}

Это - образец кода SQL:

open symmetric key columnKey decryption by password = N'{pwd!!i_ll_not_show_it_here}'

declare @enc varchar(max)

set @enc = dbo.VarBinarytoBase64(EncryptByKey(Key_GUID('columnKey'), 'blablabla'))

select LEN(@enc), @enc

Этот varbinaryToBase64 является протестированной функцией sql, которую мы используем для преобразования varbinary в тот же формат, который мы используем для хранения строк в приложении .NET.

Результат в C#: eg0wgTeR3noWYgvdmpzTKijkdtTsdvnvKzh+uhyN3Lo =

Тот же результат в SQL2k8: AI0zI7D77EmqgTQrdgMBHAEAAACyACXb+P3HvctA0yBduAuwPS4Ah3AB4Dbdj2KBGC1Dk4b8GEbtXs5fINzvusp8FRBknF15Br2xI1CqP0Qb/M4w

Я просто еще не получил, что я делаю неправильно.

У Вас есть какие-либо идеи?

Править: Один момент я думаю, является критическим: у Меня есть один Вектор инициализации в моем коде C#, 16 байтов. Этот IV не установлен в симметричном ключе SQL, я мог сделать это?

Но даже не заполняя IV в C#, я получаю совсем другие результаты, и в содержании и в длине.

11
задан Victor Rodrigues 12 May 2010 в 20:55
поделиться

2 ответа

Есть пара вещей, на которые я хотел бы обратить внимание:

  1. Убедитесь, что открытый текст идентичен по содержанию и кодировке. IIRC, по умолчанию для потоков используется UTF-8, тогда как если ваша функция VarBinaryToBase64 принимает параметр nvarchar, это будет Unicode.

  2. Убедитесь, что оба алгоритма шифрования используют одинаковый размер блока. В SQL вы определяете алгоритм, когда вызываете CREATE SYMMETRIC KEY . Если вы не укажете алгоритм, он будет использовать AES256. В .NET, использующем RijndaelManaged , я считаю, что размер блока по умолчанию равен 128, но вы можете установить его равным 256 (вы не можете, если используете класс Aes ).

  3. Последнее, что я бы искал, - это то, как SQL Server работает с векторами инициализации, как вы упомянули в своем измененном сообщении. Я хочу сказать, что для этого используется параметр Authenticator , но это дикая догадка.

РЕДАКТИРОВАТЬ

Я был далеко. Учитывая то, что я обнаружил, вы не можете использовать класс .NET для расшифровки текста, зашифрованного встроенным шифрованием SQL Server, потому что SQL Server добавляет к тому, что зашифровано, кучу слизи, включая случайный вектор инициализации. Из книги Майкла Коула «Руководство программиста Pro T-SQL 2005» (хотя в 2008 году это делается точно так же):

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

  • Первые 16 байтов зашифрованного результата представляют собой GUID симметричного ключа , используемого для шифрования данных.
  • Следующие 4 байта представляют номер версии, в настоящее время жестко закодированный как «01000000».
  • Следующие 8 байтов для шифрования DES (16 байтов для шифрования AES) представляют собой случайно сгенерированный вектор инициализации .
  • Следующие 8 байтов представляют собой информацию заголовка, представляющую параметры , используемые для шифрования данных. Если используется опция аутентификатора , эта информация заголовка включает 20-байтовый хэш SHA1 аутентификатора, что делает информацию заголовка 28 байтами в {{ 1}} длина.
  • Последняя часть зашифрованных данных - это фактические данные и сами заполнители. Для алгоритмов DES длина этих зашифрованных данных будет кратна 8 байтам. Для алгоритмов AES длина будет кратной 16 байтам.
6
ответ дан 3 December 2019 в 11:03
поделиться

Не совсем ответ, но слишком большой для комментария. Возможно, это поможет кому-то еще разобраться :)
SQL Server, похоже, делает большое количество прокладок. Когда я пробовал ваш пример, я получал разные результаты, хотя первые 18 символов, похоже, каждый раз были одинаковыми. Однако это пока не имеет для меня смысла...

Вы не показываете, как вызывается RijndaelEncrypt, но из-за разной длины данных я подумал о различиях между кодовыми страницами unicode и ANSI. Однако, похоже, вы не используете юникод в SQL Server, так что разница в длине будет наоборот, если что.

1
ответ дан 3 December 2019 в 11:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: