探讨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[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位1,NET 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弱密钥问题,同时和第三方对接时实在懒得去理解各语言实现加密算法原理,可尝试采用上述包来进行互操作,看到有几位童鞋在文章下提出这个问题而苦于没找到解决方案,这里提供一种可选择的方案,都已封装好,拿去用吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/308970.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法导论第三版第十一章11.1-4

算法导论第三版第十一章11.1-4 我们希望在一个非常大的数组上&#xff0c;通过利用直接寻址的方式来实现一个字典。开始时&#xff0c;该数组中可能包含一些无用信息&#xff0c;但要堆整个数组进行初始化时不太实际的&#xff0c;因为该数组的规模太大。请给出在大数组上实现…

C++实现表达式树

代码如下: #include <iostream> #include <string> #include <stack> #include <queue> using namespace std;class Tree { private:class Node{public:char val;Node * left;Node *right;Node(char val):val(val),left(nullptr),right(nullptr){}Nod…

Hash-table(用除法散列法实现)

Hash-table&#xff08;用除法散列法实现&#xff09; 关键字只支持int型&#xff0c;初学者版本 用链表解决冲突问题 #ifndef C11LEARN_HASHDIVISION_H #define C11LEARN_HASHDIVISION_H #include "Chain.h" template<typename T> class HashDivision { prot…

redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作

前段时间在做用户画像的时候&#xff0c;遇到了这样的一个问题&#xff0c;记录某一个商品的用户购买群&#xff0c;刚好这种需求就可以用到Redis中的Set&#xff0c;key作为productID&#xff0c;value就是具体的customerid集合&#xff0c;后续的话&#xff0c;我就可以通过p…

IDEA如何在包下建立子包

idea如何在包下建立子包 第一次在包下建立子包时候出现了问题 在java > springmvc包下再new上一个package controller的时候就会出现这个样子 如何解决 在IDEA2019 中的Show Options Menu下有一个Compacket Middle Packages将它关闭即可 解决成功

辅助类Chain

辅助类Chain #ifndef C11LEARN_CHAIN_H #define C11LEARN_CHAIN_H template<typename T> class Chain { public:int key;T value;Chain<T> *prev;Chain<T> *next; public:Chain(){}Chain(int key,const T value):key(key),value(value){} }; #endif //C11LEA…

.NET Core微服务开发选项

微服务开发的关注点有哪些&#xff1f;微服务构最终的目标是实现业务的价值&#xff0c;交付&#xff0c;为了让开发人员更加关注业务开发和交付&#xff0c;微服务需要一些比较底层的基础设置&#xff0c;我们也称为微服务公共关注点。配置管理&#xff1a;对微服务可变参数进…

常见的HTTP状态码(HTTP Status Code)说明

作为一个互联网开发人员对于一些服务器返回的HTTP状态的意思都必须是了如指掌的&#xff0c;只有将这些状态码一一弄清楚&#xff0c;工作中遇到的各种问题才能够处理的得心应手。好了&#xff0c;下面就让我们来了解一下比较常见的HTTP状态码吧&#xff01; 2开头 &#xff0…

.NET 开源项目 StreamJsonRpc 介绍[上篇]

StreamJsonRpc 是一个实现了 JSON-RPC 通信协议的开源 .NET 库&#xff0c;在介绍 StreamJsonRpc 之前&#xff0c;我们先来了解一下 JSON-RPC。JSON-RPC 介绍JSON-RPC 是一个无状态且轻量级的远程过程调用&#xff08;RPC&#xff09;协议&#xff0c;其使用 JSON&#xff08;…

hash table(用乘法散列法实现)

hash table(用乘法散列法实现&#xff09; #ifndef C11LEARN_HASHMULTI_H #define C11LEARN_HASHMULTI_H #include "HashDivision.h" template<typename T> class HashMulti:public HashDivision<T> { private:long w;long p;long long s;long long two_…

gRPC真要取代WebApi了,你还学得过来吗?

今年1月份微软曾宣布要实验性的对.NET支持 gRPC-Web&#xff0c;然后在6月份已经正式发布了。这些天尝试了下&#xff0c;真的很强大&#xff0c;不负责任的预言下&#xff0c;RESTful的时代即将过去&#xff0c;而gRPC要成为革命者&#xff01;先别急眼&#xff0c;下面我来详…

hash table(开放寻址法-线性探查实现的哈希表)

hash table(开放寻址法-线性探查实现的哈希表&#xff09; // // Created by 许加权 on 2021/7/17. //#ifndef C11LEARN_HASHLINER_H #define C11LEARN_HASHLINER_H #include "KeyNode.h" template<typename T> class HashLiner { public:HashLiner();HashLin…

Spring5 jar包下载

下载地址 https://repo.spring.io/simple/libs-release-local/org/springframework/spring/ Spring5最新版本的下载 选择最新版本5.2.3 下载前两项&#xff0c;解压放入文件夹中 项目中导包 ps&#xff1a;我使用的开发工具是idea 第一步&#xff1a;在file中选择project st…

hash table(开放寻址法-二次探查实现的哈希表)

hash table(开放寻址法-二次探查实现的哈希表&#xff09; #ifndef C11LEARN_HASHQUADRATIC_H #define C11LEARN_HASHQUADRATIC_H #include "HashLiner.h" template<typename T> class HashQuadratic:public HashLiner<T> { public:HashQuadratic(int c1…

优化 Azure 成本,实现财务目标

点击上方蓝字关注“汪宇杰博客”原文&#xff1a;Omar Khan General Manager, Microsoft Azure翻译&#xff1a;汪宇杰导语我们的许多客户都面临着如何满足关键 IT 项目的资金需求的困难决策。我们在此共同帮助您实现财务目标。确保 Azure 工作负载的成本得到优化有助于释放资金…

集合的定义与并查操作(C语言)

代码如下&#xff1a; #define MAXN 1000 /* 集合最大元素个数 */ typedef int ElementType; /* 默认元素可以用非负整数表示 */ typedef int SetName; /* 默认用根结点的下标作为集合名称 */ typedef ElementType SetType[MAXN]; /…

采用config方式灵活配置我们的Quarz.net中的Job,Trigger

经常在项目中遇到定时任务的时候&#xff0c;通常第一个想到的是Timer定时器&#xff0c;但是这玩意功能太弱鸡&#xff0c;实际上通常采用的是专业化的第三方调度框架&#xff0c;比如说Quartz&#xff0c;它具有功能强大和应用的灵活性&#xff0c;我想使用过的人都非常了解&…

hash table(开放寻址法-双重散列实现的哈希表)

hash table(开放寻址法-双重散列实现的哈希表&#xff09; #ifndef C11LEARN_HASHDOUBLE_H #define C11LEARN_HASHDOUBLE_H #include "HashLiner.h" template<typename T> class HashDouble:public HashLiner<T>{ protected:virtual int hashing(int key…

对于任给的一张无向带权连通图,求出其最小生成树(C++)

对于任给的一张无向带权连通图&#xff0c;求出其最小生成树。 题目要求: (1)编程创建一幅图 (2)输出创建的图 (3)编写Prim算法代码&#xff0c;实现图的最小生成树求解&#xff0c;且输出最小生成树 (4)编写Kruskal算法代码&#xff0c;实现图的最小生成树求解&#xff0c;且…