简体   繁体   English

如何在 C# 中解密由 des.exe 加密的文件?

[英]How can I decrypt a file in C# which has been encrypted by des.exe?

I have a file which has been encrypted by des.exe .我有一个由des.exe加密的文件

A file can be encrypted and decrypted using the following commands:可以使用以下命令加密和解密文件:

des -E -k "foo" sample.txt sample.txt.enc
des -D -k "foo" sample.txt.enc sample.txt.dec

I have attempted to decrypt using the following:我尝试使用以下方法解密:

public byte[] Decrypt(FileInfo file, string key)
{
  byte[] keyAsBytes = LibDesPasswordConvertor.PasswordToKey(key);
  byte[] initializationVector = keyAsBytes;

  var cryptoProvider = new DESCryptoServiceProvider();  
  cryptoProvider.Mode = CipherMode.CBC;
  cryptoProvider.Padding = PaddingMode.None;  

  using (FileStream fs = file.OpenRead())
  using (var memStream = new MemoryStream())
  using (var decryptor = cryptoProvider.CreateDecryptor(keyAsBytes, initializationVector))
  using (var cryptoStream = new CryptoStream(memStream, decryptor, CryptoStreamMode.Write))
  {
    fs.CopyTo(cryptoStream);
    fs.Flush();
    cryptoStream.FlushFinalBlock();

    return memStream.ToArray();
  }
}

public static class LibDesPasswordConvertor
{
  public static byte[] PasswordToKey(string password)
  {
    if (string.IsNullOrWhiteSpace(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();

    using(var des = DES.Create())
    using(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 static 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};
}

But when I execute:但是当我执行时:

const string KEY = "foo";  
var utf8Bytes = Decrypt(new FileInfo(@"PATH-TO\sample.txt.enc"), KEY);

I get:我得到:

�1D���z+�a Sample.y���0F�01

Original text:原文:

This is a Sample.

Encrypted:加密:

ñGYjl¦ûg†¼64©‹Bø
é¯Kœ|

To my surprise you've already derived the key correctly.令我惊讶的是,您已经正确地导出了密钥。 That was the meat of the problem, so Kudos for solving that part already.这就是问题的核心,所以已经解决了那部分问题。 That the key is correct becomes clear when you see that part of the plaintext is present in the decryption - it wouldn't if the key was wrong.当您看到解密中存在那部分明文时,密钥是正确的就很清楚了 - 如果密钥错误,则不会。


Looking into the source and some docs from times past, I found a likely IV of all zeros instead of reusing the key bytes (both are very wrong, in cryptographic terms).查看过去的源代码和一些文档,我发现可能是全零的 IV,而不是重用密钥字节(在密码学术语中,两者都是非常错误的)。

Furthermore, as always for SSLeay, the ECB and CBC modes use PKCS#7 compatible padding, rather than no padding.此外,与 SSLeay 一样,ECB 和 CBC 模式使用 PKCS#7 兼容填充,而不是无填充。


Finally, FlushFinalBlock will be automatically called if you close the stream, eg by exiting the try-with-resources.最后,如果您关闭流,例如通过退出 try-with-resources, FlushFinalBlock将被自动调用。 So if you get the array afterwards then you should get the right values - after you unpad correctly, of course.因此,如果您之后获得数组,那么您应该获得正确的值 - 当然,在您正确取消填充之后。 If you call Flush then FlushFinalBlock will already be called, and calling it twice will make a mess out of things.如果你调用Flush那么FlushFinalBlock将已经被调用,并且调用它两次会使事情变得一团糟。

Simply removing the flush calls and retrieving the array after the CryptoStream is closed is the way to go.CryptoStream关闭简单地删除刷新调用并检索数组是要走的路。


Both DES and the key derivation ( des_string_to_key and des_string_to_2keys ) that Young copied from MIT are completely insecure. Young 从 MIT 复制的 DES 和密钥派生( des_string_to_keydes_string_to_2keys )都是完全不安全的。 Using an all zero IV is wrong.使用全零 IV 是错误的。

If you use this as transport mode than padding oracles will apply, and decryption is not even necessary for an attacker.如果您将其用作传输模式,则填充预言机将适用,并且攻击者甚至不需要解密 The ciphertext is not integrity protected.密文不受完整性保护。

If you use the above routines to keep anything confidential or secure you're fooling yourself.如果您使用上述例程来保持任何机密或安全,那么您就是在自欺欺人。 This is 80s technology, and I think that real cryptographers wouldn't find it secure back then either.这是 80 年代的技术,我认为当时真正的密码学家也不会发现它是安全的。

Basically if your attacker is over 8 years old, you're in trouble.基本上,如果你的攻击者超过 8 岁,你就有麻烦了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM