質問

I want to claculate the MAC(Message Authentication Code) CBC chiper(Ansi x9.9), i found a sample which calculates the MAC based on a cycle, in each round the encrypted reuslt must be XOR with next round plain Text block and the result should be encrepted to being used to next step and this cycle repeats for 4 times till the last encrypted value must be return as MAC.

Cryptographic Key = 0123456789abcdef

The text is the ASCII code for "7654321 Now is the time for ".

Text = 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

I tried to implement this sample. at the first step i got the same result as the sample but for the next step my Des encryption function returns the different resutl as the sample's 2th step. i used a hardware device to encrypt each Des input block, it returns the same DES output block as the sample return. either i found another DES implementation sample here it reutrns the correct encrption too. but my app which uses microsft example on msdn returns the incorrect result for steps 2,3 and 4 except step 1. here is my code:

    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;
        }
    }

and here where i have used that function

        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); 
        }
役に立ちましたか?

解決

You should reuse the cypher instead of reinitialising it with the key and IV each time.

The calling code:

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));

And the modified Encrypt part method:

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;
    }
}

And the results:

=============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

These values match the ones you specified, and those in this specification

他のヒント

The root cause of the error is from the hexadecimal string provided by the FIPS 113 document.

Text : "7654321 Now is the time for "
Hex(Wrong) : "37363534333231204e6f77206873207468652074696d6520666f7220"
Hex(Correct): "37363534333231204e6f77206973207468652074696d6520666f7220"

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top