正确使用AES对称加密
正确使用AES对称加密
经常我看到项目中有人使用了对称加密算法,用来加密客户或项目传输中的部分数据。但我注意到开发 人员由于不熟悉原理,或者简单复制网上的代码示例,有导致代码存在安全风险。
我经常遇到的问题,有如下:
如使用了过时的加密算法(如DES)
设置了不安全的加密模式(ECB)
不正确地处理初始向量(IV)
对称加密算法
算法 | 位长 | 建议 |
---|---|---|
RC4 | 40 | ❌ |
DES | 56 | ❌ |
3DES | 112 | ❌ |
AES | 128 | ✔ |
TL;DR:
RC4/DES/3DES都 不符合 加密/破解的安全性要求。
DES是56位加密,听起来感觉3DES应该是168位,但实际上其有效加密位长只有112位。
其它更长的加密算法,如AES 192位/AES 256位也符合要求。
加密模式
TL;DR: 不要使用ECB。
ECB不需要初始向量(IV),这个“惊人”的发现常常让开发简单粗暴地设计为ECB。ECB的问题在于输入和输出存在非常明显的关联,攻击者可以从输出轻松地猜出输入数据。
C#的AES算法默认模式为CBC,该算法没有上述的安全问题,而且最为通用,可以使用该模式。
初始向量
TL;DR:
初始向量 必须 为完全随机数,完全随机数应该使用RandomNumberGenerator
进行加密。
回想这个问题,数据加密完后,该发送什么给接收方?仅数据?那么初始向量(IV)怎么办?
大多数开发选择的办法是,写一个固定的初始向量(IV)用于加密,然后解密时,也使用相同的初始向量。这样就导致相同的输入会产生相同的输出。
为什么相同的输入应该产生不同的输出?因为根据历史经验,攻击者可以获取一些信息,知道某个确定输入的含义。一旦再次捕获到相同的加密数据,就能轻易破解。
所以,发送数据应该包含:版本+初始向量+数据。
面向字符串
加密是面向字节还是字符串?我认为应该面向字节。如果面向字符串,那么很多问题很难受到重视。
试着回答这个问题:
用户的密码是什么样子的?
是长度为固定32位的HEX字符吗?如
1C8F7B2C9759209C6ACC3C105D39BBAC
?还是用户想输入什么就输入什么?如
My-Super-Str0ng-Password!!
?
我认为加密算法应该面向字节流/字节数据,而不是字符串。将字符串发送给客户、放在JSON中进行端对端传输,是没什么毛病的做法。但基于以下原因,我强烈建议加密/解密算法要基于字节数据:
避免密码太长或太短的问题
来回转换为字符串效率低下
字符串转换为字节数组容易,其它数据序列化为字节数据也容易
我的加密/解密方法
// 代码按原样提供,可随意使用,但不对其安全性作任何保证。string Encrypt(string password, string purpose, byte[] plainBytes){ byte[] key = PasswordToKey(password, purpose); using (var aes = Aes.Create()) { aes.Key = key; using (ICryptoTransform encryptor = aes.CreateEncryptor()) { byte[] cipherBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length); byte[] packedBytes = Pack( version: 1, iv: aes.IV, cipherBytes: cipherBytes); return Base64UrlEncode(packedBytes); } }}byte[] Decrypt(string packedString, string password, string purpose){ byte[] key = PasswordToKey(password, purpose); byte[] packedBytes = Base64UrlDecode(packedString); (byte version, byte[] iv, byte[] cipherBytes) = Unpack(packedBytes); using (var aes = Aes.Create()) { using (ICryptoTransform decryptor = aes.CreateDecryptor(key, iv)) { return decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length); } }}
其中公共方法:
// 代码按原样提供,可随意使用,但不对其安全性作任何保证。byte[] PasswordToKey(string password, string purpose){ using (var hmac = new HMACMD5(Encoding.UTF8.GetBytes(purpose))) { return hmac.ComputeHash(Encoding.UTF8.GetBytes(password)); }}string Base64UrlEncode(byte[] bytes){ return Convert.ToBase64String(bytes) .Replace("/", "_") .Replace("+", "-") .Replace("=", "");}byte[] Base64UrlDecode(string base64Url){ return Convert.FromBase64String(base64Url .Replace("_", "/") .Replace("-", "+"));}(byte version, byte[] iv, byte[] cipherBytes) Unpack(byte[] packedBytes){ if (packedBytes[0] == 1) { // version 1 return (1, packedBytes[1..1 + 16], packedBytes[1 + 16..]); } else { throw new NotImplementedException("unknown version"); }}byte[] Pack(byte version, byte[] iv, byte[] cipherBytes){ return new[] { version }.Concat(iv).Concat(cipherBytes).ToArray();}
解释:
Base64UrlEncode/Decode:用于将字符串在Url上传输,将
+/=
转换成:-_
Pack/Unpack:将版本/初始向量/密文打包/解包
PasswordToKey:将长度不一样密码,加上
purpose
,转换为长度一样的key
,其中改成HMACSHA256可以使用256位的AES算法。
测试代码:
// 代码按原样提供,可随意使用,但不对其安全性作任何保证。string purpose = "这个算法是用来搞SSO的";// 返回:AcfCe3AQcmNkeNThv-u09H_HyGKy_iRy-7uGiW0IZOHIEncrypt("密码here", purpose, Encoding.UTF8.GetBytes("Hello World"));// 返回:Hello WorldEncoding.UTF8.GetString(Decrypt("AcfCe3AQcmNkeNThv-u09H_HyGKy_iRy-7uGiW0IZOHI", "密码here", purpose));
正确使用AES对称加密相关推荐
- RSA加密及AES对称加密代码实现
最近老师布置了两个加密的作业,记录一下编码过程及遇到的问题. 对于RSA解密基本内容这里就不赘述,直接说一下编码过程把: 1:N = p*q(p.q互质,即公约数只有1)可以用辗转相除去判断 2:L是 ...
- 编写ATL工程实现ActiveX控件调用cryptoAPI接口(三)------------AES对称加密与解密
注:下面的代码中用了Map,Base64,log,Result等都为自定义类型,太长就不一一贴出. [cpp] view plain copy print ? /* * * * 文件名称:Enc ...
- Python代码实现MD5、AES对称加密和RSA非对称加密以及OpenSSl实践
1.MD5加密算法 1.1 MD5加密的特点 不可逆运算 对不同的数据加密的结果是定长的32位和16位字符(不管文件多大都一样) 对相同的数据加密,得到的结果是一样的(也就是复制). 抗修改性 :信息 ...
- RSA(非对称)+AES(对称加密)前后台交互
前言: 为了提高安全性采用了RSA,但是为了解决RSA加解密性能问题,所以采用了RSA(非对称)+AES(对称加密)方式,如果只考虑其中一种的,可以去看我前面两篇文章,专门单独写的demo,可以 ...
- Android+Java中使用Aes对称加密的工具类与使用
场景 Android+Java中使用RSA加密实现接口调用时的校验功能: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/11146 ...
- 详解AES对称加密(python实现文件加密)
一.对称加密 对称加密:需要对加密和解密使用相同密钥的加密算法. 优点:速度快,适合加密大量数据时使用. 缺点:不利于传送密钥.(后面文章在介绍非对称加密传输对称加密的密钥,此处应用是文件加密,密钥只 ...
- php实战 AES对称加密 第三章
对称加密 对称加密 很好理解,就是指加密和解密的时候密钥都是同一个,是 对称 的.只要保证密钥的安全,那整个通信过程就可以说具有了机密性.接下来会以 AES加密算法来实战说明. AES AES 的意思 ...
- AES对称加密和解密算法以及Java的AES工具类
参考资料:百度百科[高级加密标准] AES简介 1.密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块 ...
- 17.app后端如何保证通讯安全--aes对称加密
在上文<16.app后端如何保证通讯安全--url签名>提到,url签名有两个缺点,这两个缺点,如果使用对称加密方法的话,则完全可以避免这两个缺点.在本文中,会介绍对称加密的具体原理,和详 ...
最新文章
- 混淆梯度(Obfuscated Gradients Give a False Sense of Security Circumventing Defense)
- 笑傲江湖霍建华版电子相册
- 07/11/08 资料整理
- 迎接.NET 6,《dotnet+Linux中文手册》完整PDF开放下载!
- sendencpac文件能删吗_“手机刷短视频”躺赚?安装自动阅读文件,开机就能挣钱?靠谱吗?...
- Java 数组的拷贝(复制一个相同数组)
- java静态构造函数_为什么不允许使用Java静态构造函数?
- 尝试一下sql server2016里面的json功能
- EAS 后台事务定时执行设置
- 分布式系统及其优缺点
- 粘贴板管理 android,复制粘贴神器(剪贴板管理)app
- 漫步者耳机打开网页媒体自动关机
- jsp+servelt+mysql+tomcat 四六级单词查询系统
- 网络安全--风险评估
- Mac软件推荐:Soulver原来这么好用
- Android 8.0 手机亮灭屏
- 纯CSS+HTML+JS实现的简易个人网站
- 重庆大学计算机类专业分数线,重庆大学录取分数线 2019年重庆大学各专业录取分数线...
- JAVA版B2B2C商城源码 拼团商城 分销商城 springboot商城多商家入驻商城系统
- 信捷原创程序,8个伺服轴。 PLC:信捷XDM-60T10 HMI:信捷TG765 总体I/O在200个点之内
热门文章
- 《古剑奇谭2》详细测评心得
- 如何在Outlook 2013中管理附件
- libreoffice_如何更改您在LibreOffice中可以撤消的操作数
- 1. ReactJS基础(开发环境搭建)
- c/c++ code JSON
- 基于SharePoint革命性的大型企业协同门户产品
- js数组去重,合集等操作
- 关于IIS服务启动失败的问题:“IIS提示‘另一个程序正在使用此文件,进程无法访问’”,的解决方法...
- Blazor University (7)组件 — 双向绑定
- XElement 和 XDocument 到底有什么区别?