AES加密解密的基本原理与Python爬取AES加密接口

AES加密解密的基本原理与Python爬取AES加密接口大家好 我是小小明 今天我要带大家学习 AES 加密的基本原理 并爬取一个经过 AES 加密的接口 一起来学习吧 AES 编码解码基础 AES 简介 AES AdvancedEncr 是取代其前任标准 DES 而成为新标准的一种对称加密算法 DES 因为应用时间较早 密文已经可以在短时间内被破译 所以现在已经基本不再使用 被选定为 AES 的 Rijndael 算法全世界的企业和密码学家提交了多个对称密码算法作为 AES 的候选 最终在 2000 年从这些候选算法中选出了一种名为 Rijndael

大家好,我是小小明,今天我要带大家学习AES加密的基本原理,并爬取一个经过AES加密的接口。一起来学习吧!

AES编码解码基础

AES简介

AES(Advanced Encryption Standard)是取代其前任标准(DES)而成为新标准的一种对称加密算法
DES因为应用时间较早,密文已经可以在短时间内被破译,所以现在已经基本不再使用。

被选定为AES的Rijndael算法

全世界的企业和密码学家提交了多个对称密码算法作为AES的候选,最终在2000年从这些候选算法中选出了一种名为 Rijndael的对称密码算法,并将其确定为了AES。

Rijndael分组密码算法,会多次重复以下4个步骤:SubBytesShiftRowsMixColumnsAddRoundkey

  1. SubBytes:将每一组16字节的明文数据以每个字节的值(0-255)为索引,从一张拥有256个值得表中查找对应值进行替换(类似Base64的查表替换)。
  2. ShiftRows:将以4字节为单位的行按照一定的规则向左平移,且每一行平移的字节数不同。
  3. MixColumns:对一个4字节的值进行位运算,将其变为另一个4字节的值。
  4. AddRoundkey:将MixColumns的输出与轮密钥进行xor异或。

Rijndael的分组长度和密钥长度可以分别以32比特为单位在128比特到256比特的范围内进行选择。不过在AES的规格中,分组长度固定为128比特,密钥长度只有128、192和256比特三种。

流密码与分组密码

对数据流进行连续处理的密码算法称为流密码,流密码一般以1bit、8bit、32bit等单位进行加密解密运算。
流密码需要对一串数据进行连续处理,因此需要保持内部状态。

分组密码则每次只处理特定长度的一块数据,一个分组的比特数(bit)就称为 分组长度。DES、AES等多数对称加密算法都属于分组密码。

AES的分组长度是128bit(16字节),因此一次可以加密128bit的明文,并生成128bit的密文。每次处理完一个分组就结束了,不需要通过内部状态来记录加密的进度。

分组密码算法只能加密固定长度的分组数据,对于一段很长的明文,需要不断迭代出固定的长度进行加密;对于最后不够固定长度的明文需要补齐至固定长度,最终全部加密。

AES常用的分组模式有:

  • ECB模式:Electronic CodeBook mode(电子密码本模式)
  • CBC模式:Cipher Block Chaining mode(密码分组链接模式)
  • CFB模式:Cipher FeedBack mode(密文反馈模式)
  • OFB模式:Output FeedBack mode(输出反馈模式)
  • CTR模式:Counter mode(计数器模式)

目前笔者只见过ECBCBC两种密码模式,下来针对这两种模式介绍:

ECB模式

ECB模式的全称是 Electronic CodeBook mode(电子密码本模式)。在ECB模式中,将明文分组加密之后的结果将直接成为密文分组。

加密:

image-20210630102059605

解密:

image-20210630102217830

使用ECB模式加密时,相同的明文分组会被转换为相同的密文分组。可以理解为是一个巨大的“明文分组→密文分组”的对应表,因此ECB模式也称为电子密码本模式

当最后一个明文分组的内容小于分组长度时,需要用一些特定的数据进行填充( padding)。

注意:ECB模式最简单的一种模式,明文分组与密文分组是一一对应的关系,只要观察一下密文,就可以知道明文中存在怎样的重复组合,并可以以此为线索来破译密码,因此ECB模式安全性也是最低的。

CBC模式

CBC模式的全称是Cipher Block Chaining(密文分组链接)模式,因为密文分组是像链条一样相互连接在一起的。

在CBC模式中,首先将密文分组与前一个密文分组进行XOR运算,然后再进行加密。

当加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个(长度为一个分组的随机数据)来代替“前一个密文分组”,这个随机数据就称为:初始化向量(IV)

加密:

image-20210630102909771

解密:

image-20210630102928856

CBC模式明文分组在加密之前一定会与“前一个密文分组”进行XOR运算,因此即便明文分组1和2的值是相等的,密文分组1和2的值也是不相等的。ECB模式的缺陷也就不存在了。

参考:《图解密码技术》

AES支持的填充方式

前面说到当最后一个明文分组的内容小于分组长度时,需要用一些特定的数据进行填充( padding)。

AES支持支持的填充方式:

  • NoPadding
  • ISO10126Padding
  • Zeros
  • PKCS7

简单介绍一下:

NoPadding:表示不填充。

ISO10126Padding:填充字节序列的最后一个字节填充字节序列的长度,其余字节填充随机数据。

示例(块长度为 8,数据长度为 9):

数据: FF FF FF FF FF FF FF FF FF

ISO10126 填充: FF FF FF FF FF FF FF FF FF 7D 2A 75 EF F8 EF 07

Zeros : 填充字符串由设置为零的字节组成。

PKCS7 :填充字节序列,每个字节填充该字节序列的长度。

示例(块长度为 8,数据长度为 9):

数据: FF FF FF FF FF FF FF FF FF

ISO10126 填充: FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07

PKCS5与PKCS7的区别

在PKCS5Padding中,明确定义Block的大小是8位,而在PKCS7Padding定义中,对于块的大小可以在1-255之间,填充值的算法都是一样的。PKCS7填充方式在设定块长度为 8时,与 PKCS5 填充方式等价。

Python爬取ECB加密数据示例

这次我们爬取的网站是:https://www.qkl123.com/data/market-ratio/

目的是抓取比特币市值占比数据:

image-20210630115826283

接口地址https://gate.8btc.com/w1/home/head_pair

发现一个需要校验的加密字段,现在我们需要对它进行JS逆向分析:

image-20210630115947722

根据参数名secretKeyVersion我们可以尝试全局搜索。

控制台全局搜索快捷键是:Ctrl+ Shift+ F

image-20210630134203035

由于并没有做很复杂的JavaScript混淆,直接搜索到了对应的加密代码。对于这种json数据,一般搜索JSON.stringify都能找到相应的加密入口。

下面我们为sign打上断点,游览器一步步跟踪。

image-20210630134727019

仅仅进入第一层,我们已经清楚了加密算法是AES,采用ECB模式,Pkcs7填充方式,密钥是WTAHAPPYACTIVITY。

被加密的文本包含appId、timestamp和serverCode三个参数。

理解这些我们就可以开始编码了,首先获取参数e:

import json import time e = json.dumps({ 
   "appId": "1", "timestamp": str( int(time.time())), "serverCode": "0"}, separators=(',', ':')) e 
'{"appId":"1","timestamp":"","serverCode":"0"}' 

加密后tostring方法通过简单的追踪未找到具体的实现,但根据最终结果可以推测是经过了base64加密,于是对上面的json参数加密并base64编码再进行相应的文本替换:

from Crypto.Cipher import AES from Crypto.Util.Padding import pad text_pad = pad(e.encode('utf-8'), AES.block_size, style='pkcs7') key = b'WTAHAPPYACTIVITY' aes = AES.new(key, AES.MODE_ECB) text = base64.encodebytes(aes.encrypt(text_pad)).decode('utf-8') text.replace("/", "_").replace("+", "-") 
'gDt1nQ3Ay458FG_Xj-Aum4u82nFPsLr55DMo8rUM2gslpKNcGY8DuHqxHUQB1nzxTWeDNrlOJiri\nmPSo2PO0DQ==\n' 

结果形式已经与前端的参数大致一致,但多了\n换行符。虽然不清楚具体机制,我们继续把它替换掉即可,最终代码为:

import requests import json import base64 from Crypto.Cipher import AES from Crypto.Util.Padding import pad import time import pandas as pd def encrypt(text): key = b'WTAHAPPYACTIVITY' aes = AES.new(key, AES.MODE_ECB) text_pad = pad(text.encode('utf-8'), AES.block_size, style='pkcs7') encrypt_aes = aes.encrypt(text_pad) encrypted_text = base64.encodebytes(encrypt_aes).decode('utf-8') return encrypted_text.replace("\n", "").replace("/", "_").replace("+", "-") def get_param(): return json.dumps({ 
   "appId": "1", "timestamp": str( int(time.time())), "serverCode": "0"}, separators=(',', ':')) text = get_param() print(text) print(encrypt(text)) 
{"appId":"1","timestamp":"","serverCode":"0"} gDt1nQ3Ay458FG_Xj-Aum4u82nFPsLr55DMo8rUM2gu7NrP6hBq4jYMFqd9lgylaTWeDNrlOJirimPSo2PO0DQ== 

然后我们就可以直接爬取接口的数据了:

header = { 
    "Accept-Encoding": "gzip", "Authorization": "", "Source-Site": "qkl123", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36", } sign = encrypt(get_param()) header["Authorization"] = json.dumps({ 
   "secretKeyVersion": 1, "sign": sign}) r = requests.get("https://gate.8btc.com/w1/home/head_pair", headers=header) df = pd.DataFrame(r.json()['pairs']) df 

image-20210630143729720

可以看到已经成功的抓取到了相应的数据。

对于pair_ext_info那列可以使用字典分列,扩展到当前表中:

df = pd.concat([df.drop(columns="pair_ext_info"), pd.json_normalize(df.pair_ext_info)], axis=1) 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220256.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午8:53
下一篇 2026年3月17日 下午8:53


相关推荐

  • 游戏框架(框架入门篇)

    游戏框架(框架入门篇)游戏框架 游戏框架 发布说明 游戏框架 还是 游戏架构 立钻哥哥还是以 游戏框架 来命名这个主题吧 游戏框架 作为整个游戏的框架 具有核心的地位 一个游戏的层次和后期维护性就取决于游戏框架 游戏框架 当然也是一个探索篇 作为这个分类的第一篇博文 还是先探索一段时间 后期根据需要再推出一个精品博文 gt 立钻哥哥带您学游戏框架 游戏框架 目录

    2026年3月19日
    1
  • RSA加密算法流程图

    RSA加密算法流程图RSA加密算法流程图

    2022年5月15日
    61
  • Windows 技术篇-LDSGameMaster文件夹有什么用,删除方法

    Windows 技术篇-LDSGameMaster文件夹有什么用,删除方法LDS是鲁大师的拼写,应该是用过鲁大师,偷偷给你安装的。分析:没什么用,流氓程序,还很大占地方,4个G,可以放心的卸掉。卸载方法:找到里面的卸载程序来卸载,卸载完后把文件夹删除就好了。

    2022年6月14日
    85
  • Java基准测试工具JMH使用

    Java基准测试工具JMH使用JMH,即JavaMicrobenchmarkHarness,这是专门用于进行代码的微基准测试的一套工具API。JMH由OpenJDK/Oracle里面那群开发了Java编译器的大牛们所开发。何谓MicroBenchmark呢?简单地说就是在方法层面上的benchmark,精度可以精确到微秒级。本文主要介绍了性能基准测试工具JMH,它可以通过一些功能来规避由JVM中的JIT或者其他优化对性能测试造成的影响。

    2022年7月27日
    8
  • 学习MAXScript

    学习MAXScriptMaxScript aComprehensi 基础语法 select Box selectanyobj 打开 MAXScript 侦听器窗口 开启宏录制器 这样 每当我们进行一个操作 比如创建一个 Box 那么宏录制器中会显示当前动作所对应的 MAXScript 命令

    2026年3月19日
    2
  • CocosCreator 制作微信小游戏排行榜,超越好友,分享功能

    CocosCreator 制作微信小游戏排行榜,超越好友,分享功能在每局游戏结束时 用来显示玩家在好友中的排行 这个需要在微信提供的开放数据域中完成 微信为防止数据外泄 特地提供了开放数据域 开发者只能在子域获取数据 不能上传到外部 微信开放数据域中计算好排行榜数据 并显示 渲染到主域的页面上 需要在主域画布下 创建一个和画布大小相同的空物体 挂载组件子域的画面就是通过该组件渲染到挂载该组件的物体上 有点类似 Unity 的 RawIm

    2026年3月16日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号