南昌建设厅网站,群晖配置wordpress 80端口,网页制作个人简历教程,免费做网站怎么做网站吗【导读】之前写过一篇《探讨.NET Core数据进行3DES加密和解密问题》#xff0c;最近看到有人提出弱密钥问题#xff0c;换个强密钥不就完了吗#xff0c;猜测可能是与第三方对接导致很无奈不能更换密钥#xff0c;所以产生本文解决.NET Core中3DES弱密钥问题#xff0c;写… 【导读】之前写过一篇《探讨.NET Core数据进行3DES加密和解密问题》最近看到有人提出弱密钥问题换个强密钥不就完了吗猜测可能是与第三方对接导致很无奈不能更换密钥所以产生本文解决.NET Core中3DES弱密钥问题写下本文希望对碰到此问题的童鞋有所帮助。3DES加密或解密弱密钥在基于.NET Framework中我们可以使用反射获取到TripleDESCryptoServiceProvider的“_NewEncryptor”私有方法从而规避判断弱秘钥问题但在.NET Core中没有这个方法我们首先来看看问题的产生如下为.NET Core中加密和解密的方法实现public static string DesEncrypt(string input, string key)
{byte[] inputArray Encoding.UTF8.GetBytes(input);var tripleDES TripleDES.Create();var byteKey Encoding.UTF8.GetBytes(key);byte[] allKey new byte[24];Buffer.BlockCopy(byteKey, 0, allKey, 0, 16);Buffer.BlockCopy(byteKey, 0, allKey, 16, 8);tripleDES.Key allKey;tripleDES.Mode CipherMode.ECB;tripleDES.Padding PaddingMode.PKCS7;ICryptoTransform cTransform tripleDES.CreateEncryptor();byte[] resultArray cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}public static string DesDecrypt(string input, string key)
{byte[] inputArray Convert.FromBase64String(input);var tripleDES TripleDES.Create();var byteKey Encoding.UTF8.GetBytes(key);byte[] allKey new byte[24];Buffer.BlockCopy(byteKey, 0, allKey, 0, 16);Buffer.BlockCopy(byteKey, 0, allKey, 16, 8);tripleDES.Key byteKey;tripleDES.Mode CipherMode.ECB;tripleDES.Padding PaddingMode.PKCS7;ICryptoTransform cTransform tripleDES.CreateDecryptor();byte[] resultArray cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);return Encoding.UTF8.GetString(resultArray);
}
接下来我们调用上述加密方法对数据进行加密当然这里的密钥很简单为16位1NET Framework中对弱密钥的具体判断逻辑这里不做深入分析如下var desEncryptData DesEncrypt(Jeffcky, 1111111111111111);
为解决这个问题我们下载BouncyCastle.NetCore包此包有针对基本所有加密算法实现你会发现通过该包实现和Java中加密算法实现非常相似若与第三方Java对接对方所传数据可能利用.NET Core无法解密或通过加密导致对方无法解密因为无论是C#还是Java对于算法的实现还是有所差异利用此包可以进行互操作。在C#中3DES名称定义为TripleDES而在Java中名称则是DESede同时C#中的填充模式PKCS7对应Java中的PKCS5Padding接下来你将看到如下C#代码几乎就是从Java中翻译过来如下static IBufferedCipher CreateCipher(bool forEncryption, string key,string cipMode DESede/ECB/PKCS5Padding)
{var algorithmName cipMode;if (cipMode.IndexOf(/) 0){algorithmName cipMode.Substring(0, cipMode.IndexOf(/));}var cipher CipherUtilities.GetCipher(cipMode);var keyBytes Encoding.UTF8.GetBytes(key);var keyParameter ParameterUtilities.CreateKeyParameter(algorithmName, keyBytes);cipher.Init(forEncryption, keyParameter);return cipher;
}
如上主要是创建加密算法接口默认为3DES若forEncryption为true表示加密否则解密具体细节这里就不再详细解释有兴趣的童鞋可自行研究。接下来我们实现加密和解密方法static string EncryptData(string input, string key)
{var inCipher CreateCipher(true, key);var inputArray Encoding.UTF8.GetBytes(input);byte[] cipherData inCipher.DoFinal(inputArray);return Convert.ToBase64String(cipherData);
}static string DecryptData(string input, string key)
{var inputArrary Convert.FromBase64String(input);var outCipher CreateCipher(false, key);var encryptedDataStream new MemoryStream(inputArrary, false);var dataStream new MemoryStream();var outCipherStream new CipherStream(dataStream, null, outCipher);int ch;while ((ch encryptedDataStream.ReadByte()) 0){outCipherStream.WriteByte((byte)ch);}outCipherStream.Close();encryptedDataStream.Close();var dataBytes dataStream.ToArray();return Encoding.UTF8.GetString(dataBytes);
}
虽然密钥是16位但在内置具体实现时也会如.NET Core中一样填充到24位接下来我们再来调用上述加密和解密方法看看数据加密和解密是否正确var data EncryptData(Jeffcky, 1111111111111111);var decryptData DecryptData(data, 1111111111111111);
那么问题来了为何在C#中会抛出弱密钥异常但是在这个包中却没能抛出异常呢内置是基于Schneier pp281的弱和半弱键表进行查找可能与C#实现逻辑有所不同个人猜测如下public const int DesKeyLength 8;private const int N_DES_WEAK_KEYS 16;//基于Schneier pp281的弱和半弱键表
private static readonly byte[] DES_weak_keys
{/* 弱键 */(byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,(byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,/* 半弱键 */(byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,(byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
};public static bool IsWeakKey(byte[] key, int offset)
{if (key.Length - offset DesKeyLength)throw new ArgumentException(key material too short.);//nextkey:for (int i 0; i N_DES_WEAK_KEYS; i){bool unmatch false;for (int j 0; j DesKeyLength; j){if (key[j offset] ! DES_weak_keys[i * DesKeyLength j]){//continue nextkey;unmatch true;break;}}if (!unmatch){return true;}}return false;
}
如果第三方为Java当利用.NET Core实在走投无路无法进行解密时那就使用上述提供的解密方法进行解密理论上都可以解密不能解密的情况大多出现于对C#和Java实现原理不了解导致如下本文重点在于解决.NET Core中3DES弱密钥问题同时和第三方对接时实在懒得去理解各语言实现加密算法原理可尝试采用上述包来进行互操作看到有几位童鞋在文章下提出这个问题而苦于没找到解决方案这里提供一种可选择的方案都已封装好拿去用吧。