zoukankan      html  css  js  c++  java
  • 小程序登录的AES加密解释

    前情回顾

    通过wx.getUserInfo()的success回调得到的加密数据( encryptedData )
    对加密数据( encryptedData )解密后可得到openId和unionId。

    如何解密,官方文档是这样解释的!

    在这里插入图片描述

    首次看到如上解密说明时,我只知道encryptedData和session_key获得方式。

    session_key在上篇有介绍,如下:
    获得session_key和openId(加解密、签名系列)

    产生的疑问:
    1:AES是什么?
    2:128是什么?
    3:CBC是什么?
    4:初始向量iv是做什么用的?
    5:数据采用PKCS#7填充什么意思?
    6:1,2,3,4条分别说明的算法,密文,密钥,初始向量iv如何组合使用?
    7:Base64_Decode又是什么?


    1. AES是什么?

    美国国家标准技术研究所在2001年发布了高级加密标准(AES)Advanced Encryption Standard。
    AES是基于数据块的加密方式,
    即,每次处理的数据是一块(16字节),当数据不是16字节的倍数时填充,
    这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度。

    AES是一个对称分组密码算法。
    
    • 1

    在这里简单介绍下对称加密算法与非对称加密算法的区别。

    对称加密算法
    加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

    非对称加密算法
    加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。

    实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。

    AES加密函数
    设AES加密函数为E,则 C = E(K, P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。

    AES解密函数
    设AES解密函数为D,则 P = D(K, C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

    参数

    • 明文P:没有经过加密的数据。

    • 密钥K:用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

    • 密文C:经加密函数处理后的数据
      在这里插入图片描述


    2. 128是什么?

    AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:

    AES密钥长度(32位比特字)分组长度(32位比特字)加密轮数
    AES-128 4 4 10
    AES-192 6 4 12
    AES-256 8 4 14

    微信小程序使用的是AES-128。


    3. CBC是什么?

    AES是基于数据块的加密方式,也就是说,每次处理的数据是一块(16字节),
    当数据不是16字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度。

    即,AES把看的见的信息(明文),分成很多相同组(明文块),一般为128位(16字节)。
    对每组进行单独加密,然后再把各加密块拼接成一条密文。

    分组加密的几种方式

    • ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。

    • CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。

    • CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。

    ECB模式(基础加密)
    处理方式:
    密文快[0…n] = 加密算法(明文块[0…n],密钥)

    特点:
    1:相同的输入产生相同的输出。
    2:不能隐藏明文的模式,可能对明文进行主动攻击;

    AES默认的,最简单,但安全性不够,所以微信用了改良版CBC。

    在这里插入图片描述

    CBC模式(小程序采用)
    处理方式:
    密文快[0] = 加密算法(初始向量IV,明文块0,密钥)

    其他密文块[1…n]=加密算法(之前的密文块,明文快,密钥)

    这个模式是链式的,后一块需要前一块做基础,第一块需要一个需要初始化向量IV做基础。
    相同的输入产生不同的输出。
    能看到的数据是“明文+IV”或“明文+前一个密文”的乱码,所以能隐藏明文。

    总结:
    安全性比第一种好,所以微信小程序用AES-CBC模式,所以需要IV向量。
    密文 =AES(明文、密钥、初始向量参数)
    明文=AES(密文、密钥、初始向量参数)
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    4. PKCS#7填充是什么

    因为AES的算法是把明文分组再处理的,他要求每个分组(16字节)是“满”的,即明文长度必须被16字节整除。

    所以明文最后不足的16字节的要先进行数据填充,把不足16字节的最后一组补成16字节。

    所以可知:明文先填充,再AES加密。

    例如:明文171字节,最后一节为11个字节,需要填充5个字节(16-11)

    在这里插入图片描述
    上边是填充的原理,具体来说,填充方式有很多,PKCS#7是其中一种。
    PKCS #7 字符串由一个字节序列组成,每个字节填充该字节序列的长度。

    在这里插入图片描述
    下面的示例演示这些模式的工作原理。

    假定块长度为 8,数据长度为 9,则填充用八位字节数等于 7,
    数据:
    FF FF FF FF FF FF FF FF FF
    PKCS7 填充:
    FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07

    5. Base64_Decode

    Base64是网络上最常见的用于字节代码的编码方式之一(一个字母就是一字节byte)
    采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。
    Base64编码非常适合HTTP环境下传递较长的标识信息(传输8Bit字节代码)

    其他应用程序中,也常常需要把二进制数据编码为适合放在URL中的形式

    其实迅雷的“专用地址”也是用Base64”加密”的,其过程如下:
    1、在http://地址的前后分别添加AA和ZZ
    2、对新的字符串进行Base64编码
    把迅雷地址还原为http地址,只需要用Base64解码,然后去掉头尾的AA和ZZ即可。

    迅雷地址Base编码案例,详见此文:
    http://www.wxappclub.com/topic/711

    微信服务器的操作是:

    Base64_Encode(目标密文)=encryptedData(wx.getUserInfo得到的)
    Base64_Encode(AES密钥)=session_key
    Base64_Encode(初始向量)=iv

    所以:

    目标密文和密钥aeskey要用Base64解密:

    即目标密文=Base64_Decode(encryptedData)
    即密钥aeskey=Base64_Decode(session_key)
    即初始向量=Base64_Decode(iv)

    在这里插入图片描述

    注意:通过如下官方提供的代码demo可知,iv也进行了Base64的解码。
    文档上并未说明
    在这里插入图片描述

    6. 理解官方文档

    在这里插入图片描述

    通过上边的分析,我们知道:
    微信小程序用的AES加密算法、AES-128的方案、CBC的分组加密模式(此模式需要IV初始化向量)
    AES加密敏感数据之前,先用 PKCS#7 填充“用户敏感数据”最后不足16字节的部分。
    AES对密文解密后,需用 PKCS#7 去除填充才能得到真正“用户敏感数据”

    知道:
    openId,union等敏感数据 = AES-128-CBC(密文,密钥,初始向量iv)

    第1条:描述的是加密算法和数据填充方式
    第2条:描述的是如何得到密文(目标密文=Base64_Decode(encryptedData))
    第3条:描述的是如何得到密钥(密钥aeskey=Base64_Decode(session_key))
    第4条:描述的是如何得到初始向量iv

    上述涉及的数据:
    encryptedData(来自第2条)
    通过wx.getUserInfo()的success回调得到的

    iv(来自第4条)
    通过wx.getUserInfo()的success回调得到的

    session_key (来自第3条)
    1:通过wx.login()的success回调得到的js_code
    2:通过js_code、appid、secret得到session_key

    7. 加密解密的全过程

    微信服务器:加密
    1:对敏感用户信息“目标明文”用psck#7号填充得到“填充文”
    2:AES-128-CBC(填充文,密钥,初始向量)=>目标密文
    3:Base64_Encode(目标密文)=>encryptedData
    4:Base64_Encode(初始向量)=>iv
    5:Base64_Encode(密钥)=session_key

    后台服务器:解密
    1:通过wx.getUserInfo()获得密文crypteddata,iv
    2:通过wx.login()得到的js_code和http接口得到session_key(详情请看)
    3:Base64_Decode(encryptedData)=>目标密文
    4:Base64_Decode(session_key)=>即密钥aeskey
    5:Base64_Decode(iv)=>初始向量
    6:AES-128-CBC(目标密文,密钥,初始向量)=>填充文
    7:用psck#7对填充文去除填充得到敏感的用户信息“目标明文”

  • 相关阅读:
    69期-Java SE-046_JSP-3
    69期-Java SE-045_JSP-2
    69期-Java SE-044_JSP-1
    69期-Java SE-043_Servlet-1
    69期-Java SE-042_Tomcat-1
    Sublime Text3快捷键
    http协议与https协议的前世今生
    解决并发问题,数据库常用的两把锁——悲观锁,乐观锁
    springboot解决文件上传大小限制
    docker基本操作
  • 原文地址:https://www.cnblogs.com/htybky/p/11609907.html
Copyright © 2011-2022 走看看