c# - .NET Core 中 DES 的弱键
问题描述
我需要使用零密钥执行 DES 加密和解密操作。我得到了这个例外:
Specified key is a known weak key for 'DES' and cannot be used.
这是我的代码:
public byte[] EncryptData(byte[] data, int offset, int length, byte[] key, byte[] iv)
{
try
{
using (var cryptoProvider = new DESCryptoServiceProvider())
{
cryptoProvider.Key = key;
cryptoProvider.IV = iv;
cryptoProvider.Mode = CipherMode.ECB;
cryptoProvider.Padding = PaddingMode.None;
ICryptoTransform encryptor = cryptoProvider.CreateEncryptor();
// Create MemoryStream
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
cs.Write(data, offset, length);
}
return ms.ToArray();
}
}
}
catch (Exception e)
{
return null;
}
}
我已经看到可以通过使用以下代码来克服这个问题:
MethodInfo mi = _des.GetType().GetMethod("_NewEncryptor", BindingFlags.NonPublic | BindingFlags.Instance);
object[] Par = { _k, _des.Mode, _des.IV, _des.FeedbackSize, 0 };
ICryptoTransform encryptor = mi.Invoke(_des, Par) as ICryptoTransform;
但这仅适用于.Net Framework
. 在 .NET Core 中没有_NewEncryptor
方法,因此它返回 null。
- 我无法覆盖 Key 属性行为,因为 DESCryptoServiceProvider 是密封的。
- 我无法扩展 DES,因为实际实现在 DESCryptoServiceProvider 类中
从源代码:
public override byte[] Key
{
get
{
byte[] key = base.Key;
while (IsWeakKey(key) || IsSemiWeakKey(key))
{
GenerateKey();
key = base.Key;
}
return key;
}
set
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (!(value.Length * 8).IsLegalSize(s_legalKeySizes))
throw new ArgumentException(SR.Cryptography_InvalidKeySize);
if (IsWeakKey(value))
throw new CryptographicException(SR.Cryptography_InvalidKey_Weak, "DES");
if (IsSemiWeakKey(value))
throw new CryptographicException(SR.Cryptography_InvalidKey_SemiWeak, "DES");
base.Key = value;
}
}
因为 get Key 这个代码的行为
var keyField = cryptoProvider.GetType().GetField("KeyValue", BindingFlags.NonPublic | BindingFlags.Instance);
keyField.SetValue(cryptoProvider, key);
也无能为力,我没有选择:|。还有另一种方法可以克服 .NET Core 中的弱键吗?
解决方案
我找到了一种通过使用库(BouncyCastle.NetCore)来克服弱键的方法。如果有人需要代码,这里是:
public byte[] EncryptData(byte[] data, int offset, int length, byte[] key, byte[] iv)
{
try
{
var desEngine = new DesEngine();
var cbcBlockCipher = new CbcBlockCipher(desEngine);
var bufferedBlockCipher = new BufferedBlockCipher(cbcBlockCipher);
bufferedBlockCipher.Init(true, new ParametersWithIV(new KeyParameter(key),iv));
var cipherData = new byte[bufferedBlockCipher.GetOutputSize(length - offset)];
var outputLength = bufferedBlockCipher.ProcessBytes(data, offset, length, cipherData, 0);
bufferedBlockCipher.DoFinal(cipherData, outputLength);
return cipherData;
}
catch (Exception e)
{
return null;
}
}
推荐阅读
- java - 为什么我的 Reference(URI "") 解析为 ds:Manifest,而不是根元素,因为它应该?
- ios - EventKit 崩溃:“冻结警报属于错误类别:EKPersistentAlarm”
- azure-devops - 构建工件保留设置被忽略
- r - 使用 tibble/as_tibble 显示所有更改的名称
- elasticsearch - Elastic Search 的 Java 堆空间问题
- php - 当用户单击折叠侧边栏按钮时,仅在侧边栏上显示图标
- ios - iOS 开发/分发证书,缺少私钥
- python - 对python函数具有相同参数的多次调用输出不同的返回值
- wpf - TaskbarItemInfo.Overlay 绑定到 DrawingImage 实例通过代码停止图像更新
- prestashop-1.7 - 如何向客户地址表单 prestashop 1.7.5 添加其他字段