通过OpenSSL工具解密带有静态KEY和IV的TripleDES密文

时间:2015-10-18 08:19:25

标签: c# ruby encryption openssl 3des

我有以下代码片段解密用3DES加密的字符串:

private static byte[] KEY_192 = new byte[]
{
    37, 19, 88, 164, 71, 3, 227, 30, 19,
    174, 45, 84, 23, 253, 149, 108, 12,
    107, 16, 192, 98, 22, 179, 200
};

private static byte[] IV_192 = new byte[]
{
    47, 108, 239, 71, 33, 98, 177, 13,
    36, 51, 69, 88, 189, 17, 210, 14,
    174, 230, 20, 60, 174, 100, 12, 22
};

public static string DecryptTripleDES(string value)
{
    if (!string.IsNullOrEmpty(value))
    {
        System.Security.Cryptography.TripleDESCryptoServiceProvider cryptoProvider = new System.Security.Cryptography.TripleDESCryptoServiceProvider();
        byte[] buffer = System.Convert.FromBase64String(value);
        System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);
        System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(ms, cryptoProvider.CreateDecryptor(DataEncryptionEngine.KEY_192, DataEncryptionEngine.IV_192), System.Security.Cryptography.CryptoStreamMode.Read);
        System.IO.StreamReader sr = new System.IO.StreamReader(cs);
        return sr.ReadToEnd();
    }
    return null;
}

我试图用Openssl或Ruby复制它但没有运气,加密的base64编码字符串的例子是:

JDiLOoP3iIY=

在Linux下尝试此操作时,我收到以下错误。

  

$ echo JDiLOoP3iIY = | openssl enc -d -des3 -a -K   371988164713227301917445842325314910812107161929822179200 -iv   471082397133981771336516988189172101417423020601741001222;十六进制字符   太长的无效十六进制值

我错过了什么?谢谢!

编辑:如果有帮助,这是加密字符串的函数:

public static string EncryptTripleDES(string value)
{
    if (!string.IsNullOrEmpty(value))
    {
        System.Security.Cryptography.TripleDESCryptoServiceProvider cryptoProvider = new System.Security.Cryptography.TripleDESCryptoServiceProvider();
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(ms, cryptoProvider.CreateEncryptor(DataEncryptionEngine.KEY_192, DataEncryptionEngine.IV_192), System.Security.Cryptography.CryptoStreamMode.Write);
        System.IO.StreamWriter sw = new System.IO.StreamWriter(cs);
        sw.Write(value);
        sw.Flush();
        cs.FlushFinalBlock();
        ms.Flush();
        return System.Convert.ToBase64String(ms.GetBuffer(), 0, System.Convert.ToInt32(ms.Length));
    }
    return null;
}

在红宝石上也试过这个,同样,我得到了解密错误'

#!/usr/bin/env ruby

require 'openssl'
require 'base64'

string = 'JDiLOoP3iIY='

def decrypt(cpass)
  cipher = OpenSSL::Cipher::Cipher.new("des-ede-cbc")
  cipher.decrypt
  cipher.key = "251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8"
  cipher.iv = "2F6CEF472162B10D24334558BD11D20EAEE6143CAE640C16"
  return cipher.update(Base64.decode64(cpass)) + cipher.final
end

decrypted = decrypt(string)

puts "decrypted string: #{decrypted}"

2 个答案:

答案 0 :(得分:2)

  1. IV大小需要匹配块大小,而不是密钥大小。因此3DES需要64位IV,而不是192位IV。

    我猜你现有的代码只是忽略了前64位以外的所有内容。尝试在rubu / OpenSSL中将其截断为64位(16个十六进制字符)。

  2. 您没有正确地将这些转换为十六进制。 C#中的值是十进制的,您不能简单地将它们连接起来形成十六进制字符串。

    转换为十六进制我得到:

    Key = 25-13-58-A4-47-03-E3-1E-13-AE-2D-54-17-FD-95-6C-0C-6B-10-C0-62-16-B3-C8
    IV  = 2F-6C-EF-47-21-62-B1-0D-24-33-45-58-BD-11-D2-0E-AE-E6-14-3C-AE-64-0C-16
    

    所以我想你需要使用

    Key = 251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8
    IV  = 2F6CEF472162B10D
    
  3. C#输出是Base64编码的。我没有在您的红宝石代码中看到任何与Base64相关的内容。

  4. 我不知道ruby的默认填充是什么,但对于C#它的PKCS#5 / PKCS#7填充(这两个名称是相同的东西)。
  5. 这不安全。使用静态IV错过了IV的点,每个消息应该是不同的。并且它缺少MAC,因此它受到主动攻击,包括填充神谕。最后,64位分组密码不应该使用单个密钥加密几GB。

答案 1 :(得分:0)

感谢CodesInChaos,我解决了我的问题。

  1. OpenSSL的:

    echo JDiLOoP3iIY= | openssl enc -d -des3 -a -K 251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8 -iv 2F6CEF472162B10D;
    
  2. 输出:

      

    792

    1. 红宝石:

      require 'openssl'
      require 'base64'
      
      string = 'JDiLOoP3iIY='
      
      def decrypt(cpass)
        cipher = OpenSSL::Cipher::Cipher.new("des3")
        cipher.decrypt
        cipher.key = "37,19,88,164,71,3,227,30,19,174,45,84,23,253,149,108,12,107,16,192,98,22,179,200".split(',').map { |x| x.to_i }.pack('c*')
        cipher.iv = "47,108,239,71,33,98,177,13".split(',').map { |x| x.to_i }.pack('c*')
        return cipher.update(Base64.decode64(cpass)) + cipher.final
      end
      
      decrypted = decrypt(string)
      
      puts "decrypted string: #{decrypted}"
      
    2. 输出:

        

      解密字符串:792