探讨NET Core数据进行3DES加密或解密弱密钥问题
前言
之前写过一篇《探讨.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[];
Buffer.BlockCopy(byteKey, , allKey, , );
Buffer.BlockCopy(byteKey, , allKey, , );
tripleDES.Key = allKey;
tripleDES.Mode = CipherMode.ECB;
tripleDES.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tripleDES.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(inputArray, , inputArray.Length);
return Convert.ToBase64String(resultArray, , 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[];
Buffer.BlockCopy(byteKey, , allKey, , );
Buffer.BlockCopy(byteKey, , allKey, , );
tripleDES.Key = byteKey;
tripleDES.Mode = CipherMode.ECB;
tripleDES.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = tripleDES.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(inputArray, , inputArray.Length);
return Encoding.UTF8.GetString(resultArray);
}
接下来我们调用上述加密方法对数据进行加密,当然这里的密钥很简单为16位1,NET Framework中对弱密钥的具体判断逻辑这里不做深入分析,如下:
var desEncryptData = DesEncrypt("Jeffcky", "");
为解决这个问题我们下载BouncyCastle.NetCore包(https://github.com/chrishaly/bc-csharp),此包有针对基本所有加密算法实现,你会发现通过该包实现和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('/') >= )
{
algorithmName = cipMode.Substring(, 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()) >= )
{
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", ""); var decryptData = DecryptData(data, "");
那么问题来了,为何在C#中会抛出弱密钥异常,但是在这个包中却没能抛出异常呢?内置是基于Schneier pp281的弱和半弱键表进行查找可能与C#实现逻辑有所不同(个人猜测),如下:
public const int DesKeyLength = ; private const int N_DES_WEAK_KEYS = ; //基于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 = ; i < N_DES_WEAK_KEYS; i++)
{
bool unmatch = false;
for (int j = ; 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弱密钥问题,同时和第三方对接时实在懒得去理解各语言实现加密算法原理,可尝试采用上述包来进行互操作,看到有几位童鞋在文章下提出这个问题而苦于没找到解决方案,这里提供一种可选择的方案,都已封装好,拿去用吧。
探讨NET Core数据进行3DES加密或解密弱密钥问题的更多相关文章
- 探讨.NET Core数据进行3DES加密和解密问题
前言 一直困扰着我关于数据加密这一块,24号晚上用了接近3个小时去完成一项任务,本以为立马能解决,但是为了保证数据的安全性,我们开始去对数据进行加密,然后接下来3个小时专门去研究加密这一块,然而用着用 ...
- 探讨.NET Core中实现AES加密和解密以及.NET Core为我们提供了什么方便!
前言 对于数据加密和解密每次我都是从网上拷贝一份,无需有太多了解,由于在.net core中对加密和解密目前全部是统一了接口,只是做具体的实现,由于遇到过问题,所以将打算基本了解下其原理,知其然足矣, ...
- 探讨数据进行AES加密和解密以及.NET Core对加密和解密为我们提供了什么?
前言 对于数据加密和解密每次我都是从网上拷贝一份,无需有太多了解,由于在.net core中对加密和解密目前全部是统一了接口,只是做具体的实现,由于遇到过问题,所以将打算基本了解下其原理,知其然足矣, ...
- [Swift通天遁地]七、数据与安全-(17)使用Swift实现原生的3DES加密和解密
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 3DES加密及.NET弱密钥处理
背景 智能pos机开发项目需要指定Key加密某些关键字符串.商定采用3DES加密算法. 实践 网海中很多.NET C#编写3DES加密的函数.采集一段简明.成熟的代码,归置于常用程序集.但当指定Key ...
- 使用crypto-js对数据进行AES加密、解密
前段时间做项目有用到数据加密,前端加密,后端解密(前端也可以解密),话不多说进入正题: 第一步: npm i crypto-js -S 第二步: 在需要加密或解密的地方引入crypto-js: imp ...
- 对接https数据(3des加密)
private void checkThread() { Urls urls = new Urls(type);//根据唯一识别类型初始化参数,可根据实际情况修改此构造函数 //访问国家平台接口,取出 ...
- 探讨.NET Core数据加密和解密问题
前言 一直困扰着我关于数据加密这一块,24号晚上用了接近3个小时去完成一项任务,本以为立马能解决,但是为了保证数据的安全性,我们开始去对数据进行加密,然后接下来3个小时专门去研究加密这一块,然而用着用 ...
- JAVA和C# 3DES加密解密
最近 一个项目.net 要调用JAVA的WEB SERVICE,数据采用3DES加密,涉及到两种语言3DES一致性的问题, 下面分享一下, 这里的KEY采用Base64编码,便用分发,因为Java的B ...
随机推荐
- Java实现 LeetCode70 爬楼梯
70. 爬楼梯 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 输出: ...
- Java实现 LeetCode 47 全排列 II(二)
47. 全排列 II 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输入: [1,1,2] 输出: [ [1,1,2], [1,2,1], [2,1,1] ] class Solut ...
- Java实现第八届蓝桥杯字母组串
字母组串 由 A,B,C 这3个字母就可以组成许多串. 比如:"A","AB","ABC","ABA","AA ...
- java实现第四届蓝桥杯三部排序
三部排序 题目描述 一般的排序有许多经典算法,如快速排序.希尔排序等. 但实际应用时,经常会或多或少有一些特殊的要求.我们没必要套用那些经典算法,可以根据实际情况建立更好的解法. 比如,对一个整型数组 ...
- thinkphp5升级thinkphp6完整步骤
在php.ini文件中 打开 php_openssl扩展,去掉前面的;extension=php_openssl.dll 在phpstudy的WWW目录打开cmd,输入composer creat ...
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
- 解决:Error:java: 无效的源发行版: 12
一. spring cloud项目启动.遇到问题: 二. 解决,共两个地方. 第一个位置: Shift/Ctrl/Alt/S 快捷键一起按 Modules选择你的项目(以及父级项目,如果有的话)-&g ...
- HTML的简介和历史发展过程
HTML的简介和历史发展过程 前言 这次写一篇对于HTML以及CSS的简介,平常我们大家都知道的编程语言有很多种,比如Java.C++.Python等等,每种编程语言都有其独具的特色,不论是语法格式还 ...
- 容器编排工具之Docker-compose
前文我们聊了下docker私有仓库harbor的搭建,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13061984.html:在上一篇博客的末尾,我们简单聊了 ...
- Java对象转换Json的细节处理
一.fastJson 1.fastJson在转换java对象为json的时候,默认是不序列化null值对应的key的 也就是说当对象里面的属性为空的时候,在转换成json时,不序列化那些为null值的 ...