Два метода Des Cryptography возвращают два разных результата?

Я хочу указать MAC (код аутентификации сообщения) CBC-чип (Ansi x9.9), я нашел образец, который вычисляет MAC на основе цикла, в каждом раунде зашифрованное повторение должно быть XOR с следующий раунд обычного текстового блока, и результат должен быть зашифрован для использования на следующем шаге, и этот цикл повторяется 4 раза, пока последнее зашифрованное значение не должно быть возвращено как MAC.

Криптографический ключ = 0123456789abcdef

Текст представляет собой код ASCII для «7654321 Сейчас самое время для».

Текст = 37363534333231204e6f77206873207468652074696d6520666f7220

TIME --- PLAIN TEXT---------------DES ​​INPUT BLOCK -------- DES OUTPUT BLOCK

1 ---- 3736353433323120 -------- 3736353433323120 -------- 21fb193693a16c28

2 ---- 4e6f772068732074 -------- 6f946e16fad24c5c -------- 6c463f0cb7167a6f

3 ---- 68652074696d6520 -------- 04231f78de7b1f4f -------- 956ee891e889d91e

4 ---- 666f722000000000 -------- f3019ab1e889d91e -------- f1d30f6849312ca4

Я попытался реализовать этот образец. на первом шаге я получил тот же результат, что и образец, но на следующем шаге моя функция шифрования Des возвращает другой результат, как на втором шаге образца. Я использовал аппаратное устройство для шифрования каждого входного блока Des, он возвращает тот же выходной блок DES, что и образец. либо я нашел другой пример реализации DES здесь он также возвращает правильное зашифрование. но мое приложение, которое использует пример microsft на msdn, возвращает неверный результат для шагов 2,3 и 4, кроме шага 1. вот мой код:

    public  byte[] EncryptPart(byte[] toEncrypt, byte[] Key, byte[] IV)
    {
        try
        {

            MemoryStream mStream = new MemoryStream();
            DES DESalg = DES.Create();
            DESalg.Mode = CipherMode.CBC;
            DESalg.Padding = PaddingMode.None;

            CryptoStream cStream = new CryptoStream(mStream,
                DESalg.CreateEncryptor(Key, IV),
                CryptoStreamMode.Write);
            cStream.Write(toEncrypt, 0, toEncrypt.Length);
            cStream.FlushFinalBlock();
            byte[] ret = mStream.ToArray();
            cStream.Close();
            mStream.Close();
            return ret;
        }
        catch (CryptographicException e)
        {
            Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
            return null;
        }
    }

и здесь, где я использовал эту функцию

        var IV = new byte[8];//empty byte array
        var key = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
        var result = new byte[8];
        int LoopCount = data.Length / 8;
        for (int i = 0; i < LoopCount; i++)
        {
            byte[] Part= new byte[8];

            Array.Copy(data, i * 8, Part, 0, 8);
            Part = XorArray(Part, result);
            result = EncryptPart(Part, key, IV);
        }
        int remain=data.Length % 8;
        if (remain != 0)
        {
            byte[] LastPart = new byte[8];//
            Array.Copy(data, data.Length - remain, LastPart, 0, remain);
            LastPart=XorArray(LastPart, result);
            result = EncryptPart(LastPart, key, IV); 
        }

person m-abdi    schedule 18.11.2012    source источник
comment
Пожалуйста, используйте встроенную функцию HMAC, а не эту.   -  person CodesInChaos    schedule 18.11.2012


Ответы (2)


Вы должны повторно использовать шифр вместо того, чтобы каждый раз повторно инициализировать его с помощью ключа и IV.

Код вызова:

var IV = new byte[8];//empty byte array
var key = new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };

var data = Encoding.ASCII.GetBytes("7654321 Now is the time for ");

DES DESalg = DES.Create();
DESalg.Mode = CipherMode.CBC;
DESalg.Padding = PaddingMode.None;
ICryptoTransform crypt = DESalg.CreateEncryptor(key, IV);


var result = new byte[8];
int LoopCount = data.Length / 8;
for (int i = 0; i < LoopCount; i++)
{
    Console.WriteLine("=============Round {0}==============", i + 1);
    byte[] part = new byte[8];

    Array.Copy(data, i * 8, part, 0, 8);
    Console.WriteLine("Plain text : {0}", ByteArrayToString(part));
    part = XorArray(part, result);
    Console.WriteLine("DES INPUT  : {0}", ByteArrayToString(part));
    result = EncryptPart(crypt, part);

}
int remain = data.Length % 8;
if (remain != 0)
{
    Console.WriteLine("===========Final Round==============");
    byte[] LastPart = new byte[8];//
    Array.Copy(data, data.Length - remain, LastPart, 0, remain);
    Console.WriteLine("Plain text : " + ByteArrayToString(LastPart));
    LastPart = XorArray(LastPart, result);
    Console.WriteLine("DES INPUT  : " + ByteArrayToString(LastPart));
    result = EncryptPart(crypt, LastPart);
}

Console.WriteLine("Result: {0}", ByteArrayToString(result));

И модифицированный метод части Encrypt:

public static byte[] EncryptPart(ICryptoTransform crypt, byte[] toEncrypt)
{
    try
    {

        MemoryStream mStream = new MemoryStream();

        CryptoStream cStream = new CryptoStream(mStream,
            crypt,
            CryptoStreamMode.Write);
        cStream.Write(toEncrypt, 0, toEncrypt.Length);
        cStream.FlushFinalBlock();
        byte[] ret = mStream.ToArray();
        cStream.Close();
        mStream.Close();

        Console.WriteLine("DES OUTPUT : " + ByteArrayToString(ret));
        return ret;
    }

    catch (CryptographicException e)
    {
        Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
        return null;
    }
}

И результаты:

=============Round 1============== 
Plain text : 3736353433323120 
DES INPUT  : 3736353433323120 
DES OUTPUT : 21fb193693a16c28
=============Round 2============== 
Plain text : 4e6f772069732074
DES INPUT  : 6f946e16fad24c5c 
DES OUTPUT : 6c463f0cb7167a6f
=============Round 3============== 
Plain text : 68652074696d6520 
DES INPUT  : 04231f78de7b1f4f 
DES OUTPUT : 956ee891e889d91e
===========Final Round============ 
Plain text : 666f722000000000 
DES INPUT  : f3019ab1e889d91e 
DES OUTPUT : f1d30f6849312ca4 
Result: f1d30f6849312ca4

Эти значения соответствуют указанным вами и указанным в этой спецификации.

person sga101    schedule 18.11.2012
comment
Спасибо sga101 за ответ. ваш код возвращает тот же результат, что и мой код. я обнаружил, что образец возвращает неверный результат XOR, как мы и хотели. результат XOR должен быть 6f946e16fbd24c5c, в то время как результат выборки был 6f946e16fad24c5c для шага 2. - person m-abdi; 19.11.2012
comment
Я добавил несколько операторов печати в опубликованный код, чтобы вы могли видеть результаты на каждом этапе. Я думаю, что они соответствуют значениям, которые вы указали. - person sga101; 20.11.2012
comment
Спасибо Sga101 за ответ. весь путь, который вы сделали, правильный. я, наконец, понял, что байты входного массива, которые дал мне образец, и я использовал его в качестве массива входных текстовых байтов, были неправильными. я видел, что вы использовали этот код: var data = Encoding.ASCII.GetBytes(7654321 Теперь пришло время); этот код возвращает другой массив байтов, как в примере. - person m-abdi; 26.11.2012
comment
Различия заключаются в простом тексте раунда 2, который основан на образце кодировки: 4e6f772068732074, а правильное преобразование, которое вы сделали: 4e6f772069732074 - - person m-abdi; 26.11.2012

Основной причиной ошибки является шестнадцатеричная строка, указанная в документе FIPS 113.

Текст : "7654321 Настало время для "
Hex (неверно): "37363534333231204e6f77206873207468652074696d6520666f7220"
Hex (правильно): "37363534333277312020e6f 73207468652074696d6520666f7220"

person JaLooNz    schedule 08.11.2013