将 OpenSSL 加密转换为原生 C#
Convert OpenSSL encryption into native C#
我有一个遗留应用程序,它使用 OpenSSL 使用 DES3
.
加密字符串
这些是为 OpenSSL 设置的参数:
OpenSSL enc -des3 -nosalt -a -A -iv 1234567890123456 -K 1234567890123456...48
密钥是 48 位数字 的 字符串 并且 iv 是前 16 位数字的子字符串 这个键。
现在,我正在尝试使用 C# 的 System.Cryptography
库复制此功能,并且尽可能不使用 OpenSSL。
我的目标是不必使用 OpenSSL 并在本机 C# 代码中完成加密。
这是我目前得到的:
public string Encrypt(string toEncrypt, bool useHashing)
{
var _key = "48...digits...";
byte[] keyArray;
var toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);
if (useHashing)
{
var hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(_key));
hashmd5.Clear();
}
else
{
keyArray = Encoding.UTF8.GetBytes(_key);
}
var tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
// Is this even the correct cipher mode?
tdes.Mode = CipherMode.CBC;
// Should the PaddingMode be None?
tdes.Padding = PaddingMode.PKCS7;
// THIS is the line where I am currently stuck on:
tdes.IV = Encoding.UTF8.GetBytes(_key.Substring(0, 16));
var cTransform = tdes.CreateEncryptor();
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
正如代码中的注释所写,我不太确定我是否使用了正确的密码,甚至可能填充模式不正确并且我的 iv 的长度为 16 bytes
但只有 8 bytes
是预期的。
此外,我确实已经尝试了我的运气,无论是否对 key/iv 进行哈希处理。
甚至可以将上述 OpenSSL 逻辑转换为纯 C# 吗?
密钥和 IV 必须为 openssl enc
指定 -K
和 -iv
作为 十六进制 值。这在 C# 代码中缺失,因此本质上是以下表达式
tdes.Key = Encoding.UTF8.GetBytes(_key);
tdes.IV = Encoding.UTF8.GetBytes(_key.Substring(0, 16));
必须替换为
tdes.Key = StringToByteArray(_key);
tdes.IV = StringToByteArray(_key.Substring(0, 16));
为useHashing == false
生成相同的密文。这里的StringToByteArray
是一个将十六进制字符串转换成对应字节数组的方法,例如here.
还需要注意的是,.NET 不接受太 weak 的密钥,例如:
123456789012345612345678901234561234567890123456
如果是这样的密钥,则会抛出 CryptographicException
(指定的密钥是 'TripleDES' 的已知弱密钥,无法使用 )。 OpenSSL 接受此密钥。
关于安全:
- 现在不应该使用 MD5 来生成密钥,更多 here。
- 此外,MD5 生成一个 16 字节的散列。因此,总是使用键控选项 2,它弱于键控选项 1 (Keying options)。
- 一般使用密钥作为IV是不安全的,更多here.
- 与今天的标准 AES 相比,TripleDES 更慢 here。
我有一个遗留应用程序,它使用 OpenSSL 使用 DES3
.
这些是为 OpenSSL 设置的参数:
OpenSSL enc -des3 -nosalt -a -A -iv 1234567890123456 -K 1234567890123456...48
密钥是 48 位数字 的 字符串 并且 iv 是前 16 位数字的子字符串 这个键。
现在,我正在尝试使用 C# 的 System.Cryptography
库复制此功能,并且尽可能不使用 OpenSSL。
我的目标是不必使用 OpenSSL 并在本机 C# 代码中完成加密。
这是我目前得到的:
public string Encrypt(string toEncrypt, bool useHashing)
{
var _key = "48...digits...";
byte[] keyArray;
var toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);
if (useHashing)
{
var hashmd5 = new MD5CryptoServiceProvider();
keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(_key));
hashmd5.Clear();
}
else
{
keyArray = Encoding.UTF8.GetBytes(_key);
}
var tdes = new TripleDESCryptoServiceProvider();
tdes.Key = keyArray;
// Is this even the correct cipher mode?
tdes.Mode = CipherMode.CBC;
// Should the PaddingMode be None?
tdes.Padding = PaddingMode.PKCS7;
// THIS is the line where I am currently stuck on:
tdes.IV = Encoding.UTF8.GetBytes(_key.Substring(0, 16));
var cTransform = tdes.CreateEncryptor();
var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
正如代码中的注释所写,我不太确定我是否使用了正确的密码,甚至可能填充模式不正确并且我的 iv 的长度为 16 bytes
但只有 8 bytes
是预期的。
此外,我确实已经尝试了我的运气,无论是否对 key/iv 进行哈希处理。
甚至可以将上述 OpenSSL 逻辑转换为纯 C# 吗?
密钥和 IV 必须为 openssl enc
指定 -K
和 -iv
作为 十六进制 值。这在 C# 代码中缺失,因此本质上是以下表达式
tdes.Key = Encoding.UTF8.GetBytes(_key);
tdes.IV = Encoding.UTF8.GetBytes(_key.Substring(0, 16));
必须替换为
tdes.Key = StringToByteArray(_key);
tdes.IV = StringToByteArray(_key.Substring(0, 16));
为useHashing == false
生成相同的密文。这里的StringToByteArray
是一个将十六进制字符串转换成对应字节数组的方法,例如here.
还需要注意的是,.NET 不接受太 weak 的密钥,例如:
123456789012345612345678901234561234567890123456
如果是这样的密钥,则会抛出 CryptographicException
(指定的密钥是 'TripleDES' 的已知弱密钥,无法使用 )。 OpenSSL 接受此密钥。
关于安全:
- 现在不应该使用 MD5 来生成密钥,更多 here。
- 此外,MD5 生成一个 16 字节的散列。因此,总是使用键控选项 2,它弱于键控选项 1 (Keying options)。
- 一般使用密钥作为IV是不安全的,更多here.
- 与今天的标准 AES 相比,TripleDES 更慢 here。