crypto-js AES-CTR 实现密文前缀式局部解密细节 踩坑点

news2024/10/5 1:22:03

项目有需求,长明文经过AES-CTR模式加密后,在解密的时候,密文不能直接得到,每次通过某些方法尝试后,只能得到一块密文(按顺序),所以只能一块一块的拼接解密。在使用crypto-js这个库的时候,发送不能直接实现这种局部解密,踩了个大坑,最后经过调试源码,查看文档,花了大半天时间才解决,在此分享一下解决方案。


文章目录

  • 1.使用crypto-js 进行aes-ctr加密的流程
  • 2.尝试局部解密失败
  • 3.问题分析:padding
  • 4.正解:采用ZeroPadding方式
  • 参考


1.使用crypto-js 进行aes-ctr加密的流程

直接看代码:

import CryptoJS from 'crypto-js';

//参数定义
const key = CryptoJS.enc.Utf8.parse("hv9BbgGupxMIFjFB8hn4KPX9If5G8yw8");
const iv = CryptoJS.enc.Utf8.parse("eUGFebpHnoBov3Pz");
var msg = CryptoJS.enc.Utf8.parse("atfwus_test_test_____"); // 21bytes

//加密
const encrypted = CryptoJS.AES.encrypt(msg, key, { mode: CryptoJS.mode.CTR, iv: iv});
const cipher = encrypted.toString();
const decrypt = CryptoJS.AES.decrypt(cipher, key, { mode: CryptoJS.mode.CTR, iv: iv});

//解密
const deMsg = decrypt.toString(CryptoJS.enc.Utf8);
console.log(deMsg);

可以发现解密成功。

2.尝试局部解密失败

上面的明文加密后得到了两个16字节的密文块,理论上我只给出第一块明文,也是可以正常解密的。但是尝试后,发现并不可以:

//参数定义
const key = CryptoJS.enc.Utf8.parse("hv9BbgGupxMIFjFB8hn4KPX9If5G8yw8");
const iv = CryptoJS.enc.Utf8.parse("eUGFebpHnoBov3Pz");
var msg = CryptoJS.enc.Utf8.parse("atfwus_test_test_____"); // 21bytes

//加密
const encrypted = CryptoJS.AES.encrypt(msg, key, { mode: CryptoJS.mode.CTR, iv: iv});
var cipher = encrypted.toString();

//解密
var decrypt = CryptoJS.AES.decrypt(cipher, key, { mode: CryptoJS.mode.CTR, iv: iv});
var deMsg = decrypt.toString(CryptoJS.enc.Utf8);
console.log(deMsg);
		
// 尝试局部解密 解密第一个密文块
cipher = CryptoJS.enc.Base64.stringify(CryptoJS.lib.WordArray.create(encrypted.ciphertext.words.slice(0, 4)));
var decrypt = CryptoJS.AES.decrypt(cipher, key, { mode: CryptoJS.mode.CTR, iv: iv});
var deMsg = decrypt.toString(CryptoJS.enc.Utf8);
console.log(deMsg);

可以发现解密失败。

3.问题分析:padding

我们知道AES要求明文必须是16字节的整数倍,而上述的msg是21位,能正常加密,说明CryptoJS 有默认的padding策略。

查阅官方文档可以看出,默认使用的是Pkcs7这个策略。

在这里插入图片描述
Pkcs7 是一种常用的填充方式,也是默认的填充方式。它在数据块的末尾添加了几个字节,使得数据块的长度是加密算法所要求的整数倍。这些字节的值等于添加的字节数。特别需要注意的是,就算明文是16字节的整数倍,也会在后面填充16个字节的’\x10’。

这样牺牲了数据长度的做法是为了更为灵活透明的去解包数据,发送端和接收端不需要约定好blockSize,接收端总能通过数据包的最后一个字符得到填充的数据长度。

到这里,我们大概清楚了不能局部解密的原因了:

  • 我们加密和解密的时候并未指定padding方式,默认使用Pkcs7。
  • 而Pkcs7这种方式下,需要得到末尾的填充字符下才能确定填充数据长度。
  • 如果我们只给出第一块密文,那么无法确定填充数据长度。
  • 在crypto-js里面,这样解密的密文就不可用。

4.正解:采用ZeroPadding方式

ZeroPadding 是一种简单的填充方式,它在数据块的末尾添加零或多个字节 0x00,以使得数据块长度为加密算法所要求的整数倍。

只要业务里面不涉及数据末尾零字节的加解密,那么这种填充方式也是可行的,并且可以实现上述的局部解密。

代码如下:

//参数定义
const key = CryptoJS.enc.Utf8.parse("hv9BbgGupxMIFjFB8hn4KPX9If5G8yw8");
const iv = CryptoJS.enc.Utf8.parse("eUGFebpHnoBov3Pz");
var msg = CryptoJS.enc.Utf8.parse("atfwus_test_test_____"); // 21bytes

//加密
const encrypted = CryptoJS.AES.encrypt(msg, key, { mode: CryptoJS.mode.CTR, iv: iv, padding: CryptoJS.pad.ZeroPadding});
var cipher = encrypted.toString();

//解密
var decrypt = CryptoJS.AES.decrypt(cipher, key, { mode: CryptoJS.mode.CTR, iv: iv, padding: CryptoJS.pad.ZeroPadding});
var deMsg = decrypt.toString(CryptoJS.enc.Utf8);
console.log(deMsg);
		
// 尝试局部解密 解密第一个密文块
cipher = CryptoJS.enc.Base64.stringify(CryptoJS.lib.WordArray.create(encrypted.ciphertext.words.slice(0, 4)));
var decrypt = CryptoJS.AES.decrypt(cipher, key, { mode: CryptoJS.mode.CTR, iv: iv, padding: CryptoJS.pad.ZeroPadding});
var deMsg = decrypt.toString(CryptoJS.enc.Utf8);
console.log(deMsg);

可以发现,局部解密成功了。


参考

  • crypto-js官方文档:https://cryptojs.gitbook.io/docs/
  • pkcs7填充方式:http://eleaction01.spaces.eepw.com.cn/articles/article/item/212414

ATFWUS 2023-04-10

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/421649.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WooCommerce可扩展性:如何扩大您的WooCommerce商店

有了合适的人和技术,WooCommerce可扩展性绝对是很大的! 事实上,使用WooCommerce作为您的电子商务平台,您的在线商店的规模可以与您的目标和愿望一样大! 根据自定义模板开发高性能品牌电子商务网站 全球超500万个电商…

高效办公——Excel表格-02篇(if函数常见用法 + 条件格式的使用)

高效办公——Excel表格-02篇(if函数常见用法 条件格式的使用)1. if单条件简单用法1.1 简单需求1.2 实现方法2. if多条件使用(if-else的情况)3. if多条件使用(if(A && B)的情况)3.1 简单需求3.2 实现需求4. if多条件使用(if(A || B)的情况)5. 条…

亚马逊云科技“三步走”,实现区块链应用的快速开发

作为数字技术的代表之一,区块链技术正在被越来越多的企业所重视,并被引入到各行业的数字化转型中。根据中国通信院数据显示,目前中国区块链应用场景主要以金融和互联网为主,但应用范围呈现不断拓展的态势,政务数据共享…

day10_oop

今日内容 零、 复习昨日 一、面向对象的概念 二、面向对象编程 三、内存图 零、 复习昨日 晨考复习… 一、作业 package com.qf.homework;import java.util.Arrays;/*** --- 天道酬勤 ---** author QiuShiju* desc* ----------------* 引用数据类型的默认初始值null*/ public …

Nginx 正向代理、方向代理、端口转发

正向代理就是客户端代理,代理客户端,服务端不知道实际发起请求的客户端 正向代理中,proxy和client一般同一个lan或者网络可达,server与client一般不可达(缓存场景除外) 正向代理类似一个跳板机&#xff0c…

下一个“AI王炸”,别只盯着OpenAI,DeepMind也在憋大招

过去几个月,OpenAI风头无两,各大科技公司争先恐后地跟进大语言模型(LLM)这一技术路线。 对比之下,OpenAI的老对手DeepMind,显得有些低调和沉默。微软靠OpenAI打了一场胜仗,而谷歌推出的Bard翻了…

【c++初阶】命名空间的定义

命名空间的定义一.缺陷二.namespace和::三.访问namespace四.一些注意1.工程里标准库的展开2.命名域的小技巧一.缺陷 在c语言中,如果我们同时定义一个全局变量和一个局部变量并且使用同一个名称的话,是可以编过的(因为全局和局部是属于两个不同…

云原生_kubernetes(k8s)_pod介绍以及配置信息说明

目录 一、Pod介绍 1、Pod结构 2、Pod定义 二、Pod配置 1、基本配置 2、镜像拉取 3、启动命令 4、环境变量 5、端口设置 6、资源配额 一、Pod介绍 1、Pod结构 每个Pod中都可以包含一个或者多个容器,这些容器可以分为两类: 用户程序所在的容器&…

网络编程(第二章: TCPUDP基础模型)

TCP/UDP(服务器、客户端源码) [(12条消息) 网络编程(4.7作业)(TCP/UDP源代码)_m0_37565374的博客-CSDN博客]: 一. 套接字 socket 1.概念 最早的socket和消息队列、共享内存,管道一致只能实现一台主机中的多个进程间通信。后期加入了TCP/I…

云日记个人中心项目思路

验证昵称的唯一性 前台: 昵称文本框的失焦事件 blur 1. 获取昵称文本框的值 2. 判断值是否为空 如果为空,提示用户,禁用按钮,并return 3. 判断昵称是否做了修改…

一文详解:linux部署jenkins,一键构建并部署springboot至第三方服务器

目录 1、下载jenkins 2、 启动jenkins 3、访问jenkins 4、在当前Linux上安装maven 4.1、更新wget命令,支持https请求 4.2、下载maven 4.3、解压安装maven 4.4、配置maven环境变量 4.5、maven配置阿里云镜像 4.6、配置maven依赖下载的位置 5、Linux安装Gi…

Redis的使用【Redis】

一、缓存简介 缓存简介 二、缓存分类 缓存分类 三、常见缓存 常见缓存 四、Redis使用 Redis 有 5 ⼤基础数据类型: String——字符串类型Hash——字典类型List——列表类型Set——集合类型ZSet——有序集合类型 其中最常⽤的是字符串和字典类型。 1.字符…

Vulnhub靶场DC-1练习

目录0x00 准备0x01 主机信息收集0x02 站点信息收集0x03 漏洞查找与利用0x00 准备 下载链接:https://download.vulnhub.com/dc/DC-1.zip 介绍:There are five flags in total, but the ultimate goal is to find and read the flag in root’s home dir…

常见的DNS攻击与防御

DNS查询通常都是基于UDP的,这就导致了在查询过程中验证机制的缺失,黑客很容易利用该漏洞进行分析。DNS服务可能面临如下DNS攻击风险: 黑客伪造客户端源IP地址发送大量的DNS请求报文,造成DNS request flood攻击。黑客伪造成授权服…

Node.js安装与配置步骤

前言一、安装Node.js1.下载2.安装3.添加环境变量二、验证是否安装成功三、修改模块下载位置1.查看npm默认存放位置2.在 nodejs 安装目录下,创建 “node_global” 和 “node_cache” 两个文件夹3.修改默认文件夹4.测试默认位置是否更改成功四、设置淘宝镜像1.将npm默…

ARM Linux 内核启动2 ——C语言阶段

一、内核启动的C语言阶段 1 1、这一块的学习思路 (1) 抓大放小,不深究。 (2) 感兴趣可以就某个话题去网上搜索资料学习。 (3) 重点局部深入分析。 2、具体学习方法 (1) 顺着代码执行路径抓全。这是我们的学习主线。 (2) 对照内核启动的打印信息进行分析。 3、…

Ansible批量部署采集器

千台服务器部署采集器的时候用到了 Ansible,简单记录一下。 安装 Ansible pip install ansible yum install ansible –y在 /etc/ansible/hosts 中添加被管理组 ,比如图中[web] 是组的名字。 执行ansible命令测试,通过hosts中定义的web组执…

君子签「数据签」正式上线,推动企业电子合同实现高效安全签署

近年来,从政府机关到企事业单位,数字化转型步伐明显加快。 在数字化的驱动下,在各行业的服务过程中,君子签对产品部署有了更深的沉淀和经验,通过不断打磨、升级产品,「数据签」产品于近日正式上线&#xf…

Word这样用,提高效率不加班

Word这样用,提高效率不加班 今天给大家分享23条Word文档的应用小技巧。对于大家来说,掌握些技巧能够效率百倍,何乐不为? 这些技巧是本人通过整理一直在用并且使用频率较高的,也希望能帮到大家。有兴趣的小伙伴可以自己…

Python | 基于LendingClub数据的分类预测研究Part01——问题重述+特征选择+算法对比

欢迎交流学习~~ 专栏: 机器学习&深度学习 本文利用Python对数据集进行数据分析,并用多种机器学习算法进行分类预测。 具体文章和数据集可以见我所发布的资源:发布的资源 Python | 基于LendingClub数据的分类预测研究Part01——问题重述特…