2012-11-18 67 views
0

我想分割MAC(消息认证码) CBC chiper(Ansi x9.9),我找到一个基于循环计算MAC的样本,在每一轮中,加密的reuslt必须与下一个圆形平面异或文本块和结果应该被用于下一步,并且该循环重复4次直到最后的加密值必须返回为MAC。Des Cryptography的两种方法返回两个不同的结果?

加密密钥=ABCDEF

的文本是ASCII码 “7654321现在是时候”。

文本= 37363534333231204e6f77206873207468652074696d6520666f7220

TIME ---纯文本--------------- DES输入闭锁-------- DES输出块

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

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

3 ---- 68652074696d6520 -------- 04231f78 de7b1f4f -------- 956ee891e889d91e

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

我试图实现这个样本。在第一步中,我得到了与样本相同的结果,但对于下一步,我的Des加密函数返回与样本的第二步不同的结果。我使用硬件设备来加密每个Des输入块,它将返回与样本返回相同的DES输出块。要么我发现另一个DES实现样本here它也会恢复正确的加密。但我的应用程序,其在MSDN使用的Microsft示例返回步骤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; 
     } 
    } 

和这里其中i已经使用该功能

 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); 
     } 
+2

请使用内置的HMAC功能,而不是这个。 – CodesInChaos

回答

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

而且修改后的加密部分的方法:

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 

这些值符合指定的人,而那些在此specification

+0

谢谢sga101的回复。您的代码返回与我的代码返回相同的结果。我发现样本按照我们的需要返回错误的异或结果。 XOR结果必须是6f946e16fbd24c5c,而步骤2的样本结果是6f946e16fad24c5c。 –

+0

我在发布的代码中添加了一些打印语句,以便您可以在每个阶段看到结果。我认为他们符合你提供的价值观。 – sga101

+0

谢谢Sga101给你回复。你所做的一切都是正确的。我终于明白,样本给我的输入数组字节,我用它作为输入文本字节数组是不正确的。我看到你已经使用了这个代码:“var data = Encoding.ASCII.GetBytes(”7654321现在是时间“);”此代码返回与示例birgs不同的字节数组:Text = 37363534333231204e6f77206873207468652074696d6520666f7220 –

0

错误的根本原因来自FIPS 113文档提供的十六进制字符串。

文字: “7654321现在是时候”
十六进制(错): “37363534333231204e6f7720 73207468652074696d6520666f7220”
十六进制(正确的): “37363534333231204e6f7720 73207468652074696d6520666f7220”

相关问题