2009-10-23 76 views
4

我想解密(使用DES算法)来自第三方的数据在C#代码中。这里和其他地方有很多例子帮助我。问题是,我不知道'初始化向量'使用什么。DES初始化矢量在C#

第三方提供了一个在命令行上使用的工具(DES.EXE,我认为它是libdes库v4.01的开箱即用版本),它只需要提供加密键。所以,我可以用这个工具解密。但是,我宁愿不生成一个从我的代码运行该工具的进程。

我的问题是我如何生成/发现初始化向量。我99.9%肯定可以通过查看其他帖子来完成,但我无法弄清楚。我和第三方交谈,他们说他们不支持这种方法。任何帮助将不胜感激。

+0

在回答下面的答案时,初始化向量是必需的。我相信第三方使用CBC模式。 – 2009-10-24 13:37:35

+0

好吧,正如我所说,如果他们使用IV,他们必须把它给你,因为你无法猜测它。 – svens 2009-10-24 21:26:06

+0

不知何故,它们不需要它们提供des.exe的命令行工具。你只需输入密钥。这就是为什么我相信这是可以推导出来的。感谢您的意见。 – 2009-10-24 23:24:21

回答

0

请参阅http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation了解分组密码中使用的不同操作模式的说明。如果您使用的ECB模式只是逐块加密消息,则不需要初始化向量(IV)。也许你必须检查你的DES库以设置ECB模式/禁用其他模式。

如果他们没有使用ECB模式,你需要IV,你不能“猜测”它。在大多数情况下IV并不一定是保密的,所以移动它不是问题。

1

我花了一些时间(〜2天)来解决同样的问题。将“des.exe”重写到C#中。最后,我得到了libdes资源,并对逻辑进行了逆向设计。

初始化向量都是(8)个零。即新的字节[8]应该做。

但是,诀窍可能是如何将字符串密码转换为8个字节长的密钥。如果您使用简单的DES(未三重DES),这个代码可以为你做的伎俩:

public class LibDesPasswordConvertor 
{ 
    public byte[] PasswordToKey(string password) 
    { 
     if (password == null) 
      throw new ArgumentNullException("password"); 
     if (password == "") 
      throw new ArgumentException("password"); 

     var key = new byte[8]; 

     for (int i = 0; i < password.Length; i++) 
     { 
      var c = (int)password[i]; 
      if ((i % 16) < 8) 
      { 
       key[i % 8] ^= (byte)(c << 1); 
      } 
      else 
      { 
       // reverse bits e.g. 11010010 -> 01001011 
       c = (((c << 4) & 0xf0) | ((c >> 4) & 0x0f)); 
       c = (((c << 2) & 0xcc) | ((c >> 2) & 0x33)); 
       c = (((c << 1) & 0xaa) | ((c >> 1) & 0x55)); 
       key[7 - (i % 8)] ^= (byte)c; 
      } 
     } 

     AddOddParity(key); 

     var target = new byte[8]; 
     var passwordBuffer = 
      Encoding.ASCII.GetBytes(password).Concat(new byte[8]).Take(password.Length + (8 - (password.Length % 8)) % 8).ToArray(); 

     var des = DES.Create(); 
     var encryptor = des.CreateEncryptor(key, key); 
     for (int x = 0; x < passwordBuffer.Length/8; ++x) 
     { 
      encryptor.TransformBlock(passwordBuffer, 8 * x, 8, target, 0); 
     } 

     AddOddParity(target); 

     return target; 
    } 


    private void AddOddParity(byte[] buffer) 
    { 
     for (int i = 0; i < buffer.Length; ++i) 
     { 
      buffer[i] = _oddParityTable[buffer[i]]; 
     } 
    } 

    private static byte[] _oddParityTable = { 
      1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14, 
     16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31, 
     32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47, 
     49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62, 
     64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79, 
     81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94, 
     97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110, 
     112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127, 
     128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143, 
     145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158, 
     161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174, 
     176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191, 
     193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206, 
     208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223, 
     224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239, 
     241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254}; 
} 

(重复使用的libdes一些代码块,虽然我不得不找出DES“校验”的一部分我自己)。

最后一个缺点是,libdes使用非标准的填充机制。它几乎和ISO一样,但最后一个字节不是添加的字节数,而是8 - 这个数字。我将Padding属性设置为None并自己处理填充。

+0

在Java中使用非常相似的东西时,您不知道您为填充备注留下了多少痛苦...... – kasoban 2015-10-21 15:37:02

+0

请编辑一个答案,我错误地投了票。我会投票。感谢您的解决方案。 – 2016-11-27 19:57:48

+0

我有Java和C#中的解决方案。如果有人需要它在这里发送消息,我会发布一个答案。 – 2016-11-28 12:31:31