С# AES-256 Шифрование

Я использую RijndaelManaged для создания простой утилиты шифрования/дешифрования. Это работает нормально, но я пытаюсь интегрировать его с другой программой, созданной в Unix (Oracle). Моя проблема в том, что для всех меньших входных строк я получаю точно такой же зашифрованный шестнадцатеричный код, как и код Unix, но для более длинных строк половина моего зашифрованного шестнадцатеричного кода такая же, но другая половина отличается:

Вывод Unix:

012345678901234 - 00984BBED076541E051A239C02D97117 
0123456789012345678 - A0ACE158AD8CF70CEAE8F76AA27F62A30EA409ECE2F7FF84F1A9AF50817FC0C4

Вывод Windows (мой код):

012345678901234 - 00984BBED076541E051A239C02D97117 (same as above)
0123456789012345678 - A0ACE158AD8CF70CEAE8F76AA27F62A3D9A1B396A614DA2C1281AA1F48BC3EBB (half exactly same as above)

Мой код Windows:

public string Encrypt(byte[] PlainTextBytes, byte[] KeyBytes, string InitialVector)
        {
            byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
            RijndaelManaged SymmetricKey = new RijndaelManaged();
            SymmetricKey.Mode = CipherMode.ECB;
            SymmetricKey.Padding = PaddingMode.PKCS7;
            ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
            MemoryStream MemStream = new MemoryStream();
            CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
            CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
            CryptoStream.FlushFinalBlock();
            byte[] CipherTextBytes = MemStream.ToArray();
            MemStream.Close();
            CryptoStream.Close();
            return ByteToHexConversion(CipherTextBytes);
        }

Код Unix (PL/SQL):

FUNCTION Encrypt_Card (plain_card_id  VARCHAR2)
    RETURN RAW AS
        num_key_bytes      NUMBER := 256/8;        -- key length 256 bits (32 bytes)
        encrypted_raw      RAW (2000);             -- stores encrypted binary text
        encryption_type    PLS_INTEGER :=          -- total encryption type
                        DBMS_CRYPTO.ENCRYPT_AES256
                      + DBMS_CRYPTO.CHAIN_CBC
                      + DBMS_CRYPTO.PAD_PKCS5;

        key_bytes_raw  RAW(64) :=my_hex_key;
    BEGIN



     encrypted_raw := DBMS_CRYPTO.ENCRYPT
           (
              src => UTL_I18N.STRING_TO_RAW (plain_card_id, 'AL32UTF8'),
              typ => encryption_type,
              key => key_bytes_raw
           );


      RETURN encrypted_raw;
    EXCEPTION
    WHEN OTHERS THEN
    dbms_output.put_line (plain_card_id || ' - ' || SUBSTR(SQLERRM,1,100) );
    RETURN HEXTORAW ('EEEEEE');

Единственная разница, которую я вижу, это использование PKCS5 и PCKS7. Но в .NET нет PCKS5.


person Bhaskar    schedule 03.07.2009    source источник


Ответы (2)


Что сказал abc, а также у вас, похоже, вообще нет IV (вектора инициализации) в вашем коде PL/SQL.

То, что первая часть одинакова, связано с разными режимами (ECB и CBC). ECB шифрует каждый блок отдельно, тогда как CBC использует предыдущий блок при шифровании следующего.

Здесь происходит то, что, поскольку вы используете CBC и не устанавливаете IV, IV состоит из нулей.
Это означает, что первый блок шифрования ECB и шифрования CBC будут одинаковыми.
(Поскольку A XOR 0 = А).

Вам нужно убедиться, что вы используете один и тот же режим шифрования в обеих системах, и если вы решите использовать CBC, убедитесь, что вы используете один и тот же IV.

person Sani Singh Huttunen    schedule 03.07.2009
comment
Спасибо, это многое объясняет. Но тогда, когда я использую CBC, почему мой выходной зашифрованный шестнадцатеричный код отличается от зашифрованного шестнадцатеричного кода, созданного кодом Unix, даже для меньших входных строк. Логически это должно быть таким же, поскольку используется тот же ключ, IV и режим (т.е. CBC). - person Bhaskar; 03.07.2009
comment
Если вы используете IV в .NET и не устанавливаете IV в Unix, IV не совпадают. Как я уже упоминал, я не вижу, чтобы вы установили IV где-нибудь в коде Unix. - person Sani Singh Huttunen; 03.07.2009
comment
Использование IV в коде PL/SQL (Unix): mcs.csueastbay.edu/support/oracle/doc/10.2/appdev.102/b14258/ - person Adam Paynter; 03.07.2009

Вы используете ECB в одном случае и CBC в другом случае.

person abc    schedule 03.07.2009
comment
Если я использую CBC в своем коде .NET, это дает совершенно другой результат для всех входных строк (маленьких и больших). - person Bhaskar; 03.07.2009
comment
Да, конечно. CBC использует случайно сгенерированный IV. Зашифруйте дважды с разными IV, и вы получите разные результаты. Это не ошибка. Именно так должен работать ЦБ. - person abc; 03.07.2009
comment
На самом деле CBC не использует случайный IV. ЕЦБ вообще не использует IV. Разница в том, что в CBC предыдущий зашифрованный блок перед шифрованием подвергается операции XOR со следующим блоком открытого текста. Поэтому CBC требуется IV для XOR с первым блоком открытого текста, поскольку перед первым блоком нет. - person Sani Singh Huttunen; 03.07.2009
comment
О, я понял. Вы ДОЛЖНЫ генерировать случайный IV. Истинный. (Думал, вы имели в виду, что CBC использует внутренне сгенерированный случайный IV). IV должен, как всегда, храниться/передаваться дешифратору и не является секретом. - person Sani Singh Huttunen; 03.07.2009
comment
Конечно, это так. Использование фиксированного IV неверно и приводит к небезопасному шифрованию. - person abc; 03.07.2009
comment
Ах. Я написал комментарий, не увидев вашего ответа - person abc; 03.07.2009
comment
Просто тупой вопрос... предположим, я делаю шифрование, используя сгенерированный случайный IV, и отправляю свою выходную шестнадцатеричную строку (вместе с ключом) кому-то одному. Он использует свой собственный API для расшифровки, так как его случайный IV будет отличаться от моего, и расшифровка не вызовет проблем. Чтобы смягчить это, нам придется использовать фиксированный IV и делиться им !!! - person Bhaskar; 03.07.2009
comment
Нет... вы должны отправить IV вместе с зашифрованными данными. Нет необходимости держать IV в секрете. Однако важно то, что вы не используете один и тот же IV для шифрования разных данных одним и тем же ключом. - person Sani Singh Huttunen; 03.07.2009
comment
Еще одно замечание по твоему дурацкому вопросу: ключ и есть секрет. Вы НЕ должны отправлять его вместе с зашифрованными данными. Вы должны реализовать схему совместного использования ключей (например, Диффи-Хеллмана) для передачи симметричного ключа (ключ AES). При этом вы можете безопасно передавать IV вместе с зашифрованными данными, пока вы создаете новый IV для каждого передаваемого сообщения. - person Sani Singh Huttunen; 06.07.2009