通过OpenSSL工具用静态KEY和IV解密TripleDES密文
Decrypt a TripleDES ciphertext with static KEY and IV through the OpenSSL tool
我有以下片段可以解密用 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; hex string
is too long invalid hex iv value
我错过了什么?谢谢!
编辑:如果有帮助,这是加密字符串的函数:
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;
}
也在 ruby 上试过了,同样,我得到 'bad decrypt'
#!/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}"
IV 大小需要匹配块大小,而不是密钥大小。所以 3DES 需要 64 位 IV,而不是 192 位 IV。
我想您现有的代码只是忽略了前 64 位以外的所有内容。尝试在 rubu/OpenSSL.
中将其截断为 64 位(16 个十六进制字符)
您没有将它们正确地转换为十六进制。 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
C# 输出是 Base64 编码的。我在您的 ruby 代码中没有看到任何与 Base64 相关的内容。
- 我不知道 ruby 的默认填充是什么,但对于 C# 它是 PKCS#5 / PKCS#7 填充(它们是同一事物的两个名称)。
这不安全。使用静态 IV 错过了 IV 的要点,每条消息都应该不同。而且它缺少 MAC,因此它会遭受主动攻击,包括填充预言机。最后,64 位块密码不应使用单个密钥加密超过几 GB。
感谢 CodesInChaos,我解决了我的问题。
OpenSSL:
echo JDiLOoP3iIY= | openssl enc -d -des3 -a -K 251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8 -iv 2F6CEF472162B10D;
输出:
792
Ruby:
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}"
输出:
decrypted string: 792
我有以下片段可以解密用 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; hex string is too long invalid hex iv value
我错过了什么?谢谢!
编辑:如果有帮助,这是加密字符串的函数:
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;
}
也在 ruby 上试过了,同样,我得到 'bad decrypt'
#!/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}"
IV 大小需要匹配块大小,而不是密钥大小。所以 3DES 需要 64 位 IV,而不是 192 位 IV。
我想您现有的代码只是忽略了前 64 位以外的所有内容。尝试在 rubu/OpenSSL.
中将其截断为 64 位(16 个十六进制字符)
您没有将它们正确地转换为十六进制。 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
C# 输出是 Base64 编码的。我在您的 ruby 代码中没有看到任何与 Base64 相关的内容。
- 我不知道 ruby 的默认填充是什么,但对于 C# 它是 PKCS#5 / PKCS#7 填充(它们是同一事物的两个名称)。
这不安全。使用静态 IV 错过了 IV 的要点,每条消息都应该不同。而且它缺少 MAC,因此它会遭受主动攻击,包括填充预言机。最后,64 位块密码不应使用单个密钥加密超过几 GB。
感谢 CodesInChaos,我解决了我的问题。
OpenSSL:
echo JDiLOoP3iIY= | openssl enc -d -des3 -a -K 251358A44703E31E13AE2D5417FD956C0C6B10C06216B3C8 -iv 2F6CEF472162B10D;
输出:
792
Ruby:
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}"
输出:
decrypted string: 792