探讨.NET Core数据加密和解密问题
前言
一直困扰着我关于数据加密这一块,24号晚上用了接近3个小时去完成一项任务,本以为立马能解决,但是为了保证数据的安全性,我们开始去对数据进行加密,然后接下来3个小时专门去研究加密这一块,然而用着用着却发现了一点问题,于是下班回来到写这篇博客到深夜才正式解决,请往下看。
3DES数据加密
由于数据需要获取出来并显示于是只能使用对称加密,关于加密这一块网上对于.NET Framework的实现数不胜数,好像对于.NET Core这一块比较少,于是就开始进行研究。这个时候就利用DES或者Triple DES也称作3DES,全名为Triple Data Encryption Algorithm (TDEA or Triple DEA),也就是对称密码块密码,3DES对数据的每个数据块利用算法进行3次加密,最初开始设计该算法时,位数只有56位也就是7个字节,设计者认为已经足够用,但是随着计算机的高速发展,暴露破解已经使得该算法呈现的问题日益突出,而3DES算法的出现提供了一种比较简单的方法来增加密钥的大小从而防止攻击,而不是重新设计一套全新的分组密码算法。
3DES加密算法命名
定义算法最早期的标准被放在ANS X9.52中并在1998年发布并将其描述为三重数据加密算法(简称TDEA),在ANSI X3.92中定义了该算法的三个操作但是并没有使用DES或者3DES,直到1999年发布的FIPS PUB 46-3在正式命名三重数据加密算法,大概在2004到2005的样子才正式引入三重数据加密算法,之前一直以TDEA存在着,也就是说TDEA就是3DES,但是没有使用3DES作为标准术语。
3DES算法逻辑
三重数据加密算法使用包括密钥K1,密钥K2和密钥约束K3,每一个包含56位不包含奇偶校验,算法实现公式如下:
- ciphertext = EK3(DK2(EK1(plaintext)))
即
- 密文 = EK3(DK2(EK1(平文)))
用K1对数据进行加密,用K2对数据进行解密,用K3对数据再加密。
解密公式为如下:
- plaintext = DK1(EK2(DK3(ciphertext)))
即
- 平文 = DK1(EK2(DK3(密文)))
用K3j对数据进行解密,用K2对数据进行加密,用K1对数据进行加密。每次加密都处理64位数据并形成一块。
3DES加密选项
定义了三种密钥选项。
(1)三个密钥相互独立。
(2)K1和K2密钥独立,但K1 = K3。
(3)三个密钥相等。
密钥选项1的强度最高,拥有3 x 56 = 168个独立的密钥位。
密钥选项2的安全性稍低,拥有2 x 56 = 112个独立的密钥位。该选项比简单的应用DES两次的强度较高,即使用K1和K2,因为它可以防御中途相遇攻击。
密钥选项3等同与DES,只有56个密钥位。这个选项提供了与DES的兼容性,因为第1和第2次DES操作相互抵消了。该选项不再为国家标准科技协会(NIST)所推荐,亦不为ISO/IEC 18033-3所支持。
利用3DES在.NET Framework中实现加密和解密
我们看下在.NET Framework中对于3DES的具体实现,如下:
- public static string DesEncrypt(string input, string key)
- {
- byte[] inputArray = Encoding.UTF8.GetBytes(input);
- TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
- tripleDES.Key = Encoding.UTF8.GetBytes(key);
- tripleDES.Mode = CipherMode.ECB;
- tripleDES.Padding = PaddingMode.PKCS7;
- ICryptoTransform cTransform = tripleDES.CreateEncryptor();
- byte[] resultArray = cTransform.TransformFinalBlock(inputArray, , inputArray.Length);
- tripleDES.Clear();
- return Convert.ToBase64String(resultArray, , resultArray.Length);
- }
- public static string DesDecrypt(string input, string key)
- {
- byte[] inputArray = Convert.FromBase64String(input);
- TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
- tripleDES.Key = Encoding.UTF8.GetBytes(key);
- tripleDES.Mode = CipherMode.ECB;
- tripleDES.Padding = PaddingMode.PKCS7;
- ICryptoTransform cTransform = tripleDES.CreateDecryptor();
- byte[] resultArray = cTransform.TransformFinalBlock(inputArray, , inputArray.Length);
- tripleDES.Clear();
- return Encoding.UTF8.GetString(resultArray);
- }
我们给出一个16位的加密密钥,然后对相应数据进行加密和解密
- var name = "Jeffcky";
- var encryptStr = DesEncrypt(name, "sblw-3hn8-sqoy19");
- Console.WriteLine(name);
- var decryptStr = DesDecrypt(encryptStr, "sblw-3hn8-sqoy19");
- Console.WriteLine(decryptStr);
我们定义密钥为16个字节,即此时应该是有两个密钥,但是此时密钥却不同,所以猜测内部实现的3DES密码选项中的第二项,因为密钥3和密钥1相等,既然没出错,内部应该会去拿密钥1中的位数作为密钥3的位数。接下里我们再来看在.NET Core中的情况。
利用3DES在.NET Core实现加密和解密
由于在.NET Core中不存在 TripleDESCryptoServiceProvider 取而代之的是 TripleDES ,所以此时我们的代码需要稍作修改,如下:
- public static string DesEncrypt(string input, string key)
- {
- byte[] inputArray = Encoding.UTF8.GetBytes(input);
- var tripleDES = TripleDES.Create();
- var byteKey = Encoding.UTF8.GetBytes(key);
- tripleDES.Key = byteKey;
- 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);
- 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);
- }
接着进行调用:
- var name = "Jeffcky";
- var encryptStr = DesEncrypt(name, "sblw-3hn8-sqoy19");
- Console.WriteLine(name);
- var decryptStr = DesDecrypt(encryptStr, "sblw-3hn8-sqoy19");
- Console.WriteLine(decryptStr);
结果出错了详细信息如下:
- System.Security.Cryptography.CryptographicException:“Specified key is not a valid size for this algorithm.”
由上说明我们给出密钥的大小对于3DES对称加密算法时无效的,为何呢,在.NET Framework是好使的呀,当我们调试时将鼠标放在3DES中密钥时你会发现它实际需要的字节为24个字节,而我们只提供了16个字节,如下:
所以到这里我们应该知道问题出在什么地方了,根据我们对3DES的介绍内部实现的选项应该是密钥选项2,将密钥1和密钥2独立开来,而密钥3和密钥相同,在.NET Framework中我们只要两个密钥即可,因为第三个密钥和第一个相同,既然没出错肯定是内部重用了密钥1,但是在.NET Core需要我们给出24个字节,说明即使密钥1和密钥3相同也要我们提供密钥的字节,所以我们只要将密钥1中的八个字节拷贝到密钥3中,这样就有了24个字节,实现如下:
- 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, 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, , 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, 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.CreateDecryptor();
- byte[] resultArray = cTransform.TransformFinalBlock(inputArray, , inputArray.Length);
- return Encoding.UTF8.GetString(resultArray);
- }
此时我们再来看下打印结果:
- var name = "Jeffcky";
- Console.WriteLine($"加密字符串为{name}");
- var encryptStr = DesEncrypt(name, "sblw-3hn8-sqoy19");
- Console.WriteLine($"加密后结果为:{encryptStr}");
- var decryptStr = DesDecrypt(encryptStr, "sblw-3hn8-sqoy19");
- Console.WriteLine($"解密后字符串为{decryptStr}");
总结
当时遇到这个问题我就处在崩溃的边缘,结果去查找了资料发现有人遇到过问题,然后就去了解下3DES基本原理就解决了问题。
记住:在.NET Core中利用3DES加密和解密必须要给出3个密钥即24个字节即使密钥3和密钥1相等,它不会像.NET Framework中会重用密钥1中的位数。
参考资料:http://stackoverflow.com/questions/39013264/tripledes-16-byte-not-working
探讨.NET Core数据加密和解密问题的更多相关文章
- 探讨NET Core数据进行3DES加密或解密弱密钥问题
前言 之前写过一篇<探讨.NET Core数据进行3DES加密和解密问题>,最近看到有人提出弱密钥问题,换个强密钥不就完了吗,猜测可能是与第三方对接导致很无奈不能更换密钥,所以产生本文解决 ...
- 探讨.NET Core中实现AES加密和解密以及.NET Core为我们提供了什么方便!
前言 对于数据加密和解密每次我都是从网上拷贝一份,无需有太多了解,由于在.net core中对加密和解密目前全部是统一了接口,只是做具体的实现,由于遇到过问题,所以将打算基本了解下其原理,知其然足矣, ...
- ASP.NET(C#)常用数据加密和解密方法汇总
一. 数据加密的概念 1. 基本概念 2. 基本功能 3. 加密形式 二. 数据加密的项目应用和学习 1. 媒体加密:DRM 2. 文件加密:文本 ...
- php接口数据加密、解密、验证签名代码实例
php接口数据加密.解密.验证签名 代码非常easy,这里就不多废话了,直接奉上代码 <?php /** * 数据加密.解密.验证签名 * @edit http://www.lai18.com ...
- Python之数据加密与解密及相关操作(hashlib模块、hmac模块、random模块、base64模块、pycrypto模块)
本文内容 数据加密概述 Python中实现数据加密的模块简介 hashlib与hmac模块介绍 random与secrets模块介绍 base64模块介绍 pycrypto模块介绍 总结 参考文档 提 ...
- Python之数据加密与解密及相关操作(hashlib、hmac、random、base64、pycrypto)
本文内容 数据加密概述 Python中实现数据加密的模块简介 hashlib与hmac模块介绍 random与secrets模块介绍 base64模块介绍 pycrypto模块介绍 总结 参考文档 提 ...
- .Net Core DES加密解密
一.DES说明 1.加密的密钥必须是16位,因为是通过AES处理的Create,AES内置的位数为16位. 2.加密结果返回Base64字符格式 二.加密方法整理 //默认密钥向量 private s ...
- .Net Core AES加密解密
一.AES说明 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替 ...
- php接口数据加密、解密、验证签名【转】
<?php/** * 数据加密,解密,验证签名 * @edit http://www.lai18.com * @date 2015-07-08 **///header('Content-Type ...
随机推荐
- jQuery获取Select选择的Text和Value
jQuery获取Select选择的Text和Value:语法解释:1. $("#select_id").change(function(){//code...}); //为S ...
- Redis-port安装使用实现redis迁移codis,以及简单redis pipe实现将mysql迁移redis
(0)Redis-port原理: 首先是看到下面这篇文档开始研究的redis-port http://www.itnpc.com/news/web/146085373656602.html 简要截图 ...
- iOS网络编程笔记——编写自己的网络客户端
编写网络客户端主要有四个步骤: (1)项目中引入Accounts和Social框架 Accounts框架中有进行用户账户认证所需类,Social框架提供了我们所需要的SLRequest类. (2)用户 ...
- cassandra高级操作之索引、排序以及分页
本次就给大家讲讲cassandra的高级操作:索引.排序和分页:处于性能的考虑,cassandra对这些支持都比较简单,所以我们不能希望cassandra完全适用于我们的逻辑,而是应该将我们的逻辑设计 ...
- Grunt usemin
yeoman/grunt-usemin 用来将 HTML 文件中(或者 templates/views)中没有优化的 script 和 stylesheets 替换为优化过的版本. usemin 暴露 ...
- 填坑实录 Android Studio 利用 ADB WIFI 插件实现真机无线调试
总是用模拟器,小破本的渣内存无法承受,同时模拟器的版本大多停在4.4,无法体现Android 5.0.6.0 的版本特性,因此决定利用 Android Studio 的插件实现真机无线调试. 步骤如下 ...
- 手机自动化测试:appium源码分析之bootstrap十
手机自动化测试:appium源码分析之bootstrap十 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣, ...
- 性能调优:mysql之left join
poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...
- 老李分享:Android性能优化之内存泄漏1
老李分享:Android性能优化之内存泄漏 前言 对于内存泄漏,我想大家在开发中肯定都遇到过,只不过内存泄漏对我们来说并不是可见的,因为它是在堆中活动,而要想检测程序中是否有内存泄漏的产生,通常我 ...
- Android敏感词过滤主要类
package com.tradeaider.app.utils; import com.tradeaider.app.activity.MyApplication;import java.util. ...