正确使用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对称加密相关推荐

  1. RSA加密及AES对称加密代码实现

    最近老师布置了两个加密的作业,记录一下编码过程及遇到的问题. 对于RSA解密基本内容这里就不赘述,直接说一下编码过程把: 1:N = p*q(p.q互质,即公约数只有1)可以用辗转相除去判断 2:L是 ...

  2. 编写ATL工程实现ActiveX控件调用cryptoAPI接口(三)------------AES对称加密与解密

    注:下面的代码中用了Map,Base64,log,Result等都为自定义类型,太长就不一一贴出. [cpp]  view plain  copy  print ? /* * * * 文件名称:Enc ...

  3. Python代码实现MD5、AES对称加密和RSA非对称加密以及OpenSSl实践

    1.MD5加密算法 1.1 MD5加密的特点 不可逆运算 对不同的数据加密的结果是定长的32位和16位字符(不管文件多大都一样) 对相同的数据加密,得到的结果是一样的(也就是复制). 抗修改性 :信息 ...

  4. RSA(非对称)+AES(对称加密)前后台交互

    前言:    为了提高安全性采用了RSA,但是为了解决RSA加解密性能问题,所以采用了RSA(非对称)+AES(对称加密)方式,如果只考虑其中一种的,可以去看我前面两篇文章,专门单独写的demo,可以 ...

  5. Android+Java中使用Aes对称加密的工具类与使用

    场景 Android+Java中使用RSA加密实现接口调用时的校验功能: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/11146 ...

  6. 详解AES对称加密(python实现文件加密)

    一.对称加密 对称加密:需要对加密和解密使用相同密钥的加密算法. 优点:速度快,适合加密大量数据时使用. 缺点:不利于传送密钥.(后面文章在介绍非对称加密传输对称加密的密钥,此处应用是文件加密,密钥只 ...

  7. php实战 AES对称加密 第三章

    对称加密 对称加密 很好理解,就是指加密和解密的时候密钥都是同一个,是 对称 的.只要保证密钥的安全,那整个通信过程就可以说具有了机密性.接下来会以 AES加密算法来实战说明. AES AES 的意思 ...

  8. AES对称加密和解密算法以及Java的AES工具类

    参考资料:百度百科[高级加密标准] AES简介 1.密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块 ...

  9. 17.app后端如何保证通讯安全--aes对称加密

    在上文<16.app后端如何保证通讯安全--url签名>提到,url签名有两个缺点,这两个缺点,如果使用对称加密方法的话,则完全可以避免这两个缺点.在本文中,会介绍对称加密的具体原理,和详 ...

最新文章

  1. 混淆梯度(Obfuscated Gradients Give a False Sense of Security Circumventing Defense)
  2. 笑傲江湖霍建华版电子相册
  3. 07/11/08 资料整理
  4. 迎接.NET 6,《dotnet+Linux中文手册》完整PDF开放下载!
  5. sendencpac文件能删吗_“手机刷短视频”躺赚?安装自动阅读文件,开机就能挣钱?靠谱吗?...
  6. Java 数组的拷贝(复制一个相同数组)
  7. java静态构造函数_为什么不允许使用Java静态构造函数?
  8. 尝试一下sql server2016里面的json功能
  9. EAS 后台事务定时执行设置
  10. 分布式系统及其优缺点
  11. 粘贴板管理 android,复制粘贴神器(剪贴板管理)app
  12. 漫步者耳机打开网页媒体自动关机
  13. jsp+servelt+mysql+tomcat 四六级单词查询系统
  14. 网络安全--风险评估
  15. Mac软件推荐:Soulver原来这么好用
  16. Android 8.0 手机亮灭屏
  17. 纯CSS+HTML+JS实现的简易个人网站
  18. 重庆大学计算机类专业分数线,重庆大学录取分数线 2019年重庆大学各专业录取分数线...
  19. JAVA版B2B2C商城源码 拼团商城 分销商城 springboot商城多商家入驻商城系统
  20. 信捷原创程序,8个伺服轴。 PLC:信捷XDM-60T10 HMI:信捷TG765 总体I/O在200个点之内

热门文章

  1. 《古剑奇谭2》详细测评心得
  2. 如何在Outlook 2013中管理附件
  3. libreoffice_如何更改您在LibreOffice中可以撤消的操作数
  4. 1. ReactJS基础(开发环境搭建)
  5. c/c++ code JSON
  6. 基于SharePoint革命性的大型企业协同门户产品
  7. js数组去重,合集等操作
  8. 关于IIS服务启动失败的问题:“IIS提示‘另一个程序正在使用此文件,进程无法访问’”,的解决方法...
  9. Blazor University (7)组件 — 双向绑定
  10. XElement 和 XDocument 到底有什么区别?