Java 环境下使用 AES 加密的特殊问题处理
在 Java 环境下使用 AES 加密,在密钥长度和字节填充方面有一些比较特殊的处理。
1. 密钥长度问题
默认 Java 中仅支持 128 位密钥,当使用 256 位密钥的时候,会报告密钥长度错误
Invalid AES key length
你需要下载一个支持更长密钥的包。这个包叫做 Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6,可以从这里下载,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
下载之后,解压后,可以看到其中包含两个包:
local_policy.jar
US_export_policy.jar
看一下你的 JRE 环境,将 JRE 环境中 lib\lib\security 中的同名包替换掉。
2. Base64 问题
Apache 提供了 Base64 的实现,可以从这里下载。
下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
编码
// 编码
String asB64 = new Base64().encodeToString("some string".getBytes("utf-8"));
System.out.println(asB64); // 输出为: c29tZSBzdHJpbmc=
解码
// 解码
byte[] asBytes = new Base64().getDecoder().decode("c29tZSBzdHJpbmc=");
System.out.println(new String(asBytes, "utf-8")); // 输出为: some string
如果你已经使用 Java 8,那么就不需要再选用第三方的实现了,在 java.util 包中已经包含了 Base64 的处理。
编码的方式
// 编码
String asB64 = Base64.getEncoder().encodeToString("some string".getBytes("utf-8"));
System.out.println(asB64); // 输出为: c29tZSBzdHJpbmc=
解码处理
// 解码
byte[] asBytes = Base64.getDecoder().decode("c29tZSBzdHJpbmc=");
System.out.println(new String(asBytes, "utf-8")); // 输出为: some string
3. 关于 PKCS5 和 PKCS7 填充问题
PKCS #7 填充字符串由一个字节序列组成,每个字节填充该填充字节序列的长度。
假定块长度为 8,数据长度为 9,
数据: 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
简单地说, PKCS5, PKCS7和SSL3, 以及CMS(Cryptographic Message Syntax)
有如下相同的特点:
1)填充的字节都是一个相同的字节
2)该字节的值,就是要填充的字节的个数
如果要填充8个字节,那么填充的字节的值就是0×8;
要填充7个字节,那么填入的值就是0×7;
…
如果只填充1个字节,那么填入的值就是0×1;
这种填充方法也叫PKCS5, 恰好8个字节时还要补8个字节的0×08
正是这种即使恰好是8个字节也需要再补充字节的规定,可以让解密的数据很确定无误的移除多余的字节。

在PKCS# Padding中说:
- 因为恢复的明文的最后一个字节 告诉你 存在多少个填充字节, 用PKCS#5 填充 的加密方法, 即使在输入的明文长度 恰好是 块大小(Block Size)整数倍 , 也会增加一个完整的填充块. 否则,恢复出来的明文的最后一个字节可能是实际的消息字节.
- 因为第1个因素限制了 使用PKCS#填充的 对称加密算法的 输入块大小(Block Size, 注意不是输入的明文的总长度 total input length), 最大只能是256个字节. 因为大多数对称块加密算法 通常使用8字节或者16字节的块, 所以,这不是一个问题
- 使用ECB模式填充可能会有安全问题.
- 使用PKCS#5填充 可以很方便地检测明文中的错误.
标准
PKCS #7: Cryptographic Message Syntax
在 10.3节中讲到了上面提到的填充算法, 对Block Size并没有做规定
PKCS #5: Password-Based Cryptography Specification
在6.1.1 中对 填充做了说明
但是因为该标准 只讨论了 8字节(64位) 块的加密, 对其他块大小没有做说明
其 填充算法跟 PKCS7是一样的
后来 AES 等算法, 把BlockSize扩充到 16个字节
比如, Java中
Cipher.getInstance(“AES/CBC/PKCS5Padding”)
这个加密模式
跟C#中的
RijndaelManaged cipher = new RijndaelManaged();
cipher.KeySize = 128;
cipher.BlockSize = 128;
cipher.Mode = CipherMode.CBC;
cipher.Padding = PaddingMode.PKCS7;
的加密模式是一样的
因为AES并没有64位的块, 如果采用PKCS5, 那么实质上就是采用PKCS7
Java 环境下使用 AES 加密的特殊问题处理的更多相关文章
- Java环境下shiro的测试-认证与授权
Java环境下shiro的测试 1.导入依赖的核心jar包 <dependency> <groupId>org.apache.shiro</groupId> < ...
- NLPIR分词工具的使用(java环境下)
一.NLPIR是什么? NLPIR(汉语分词系统)由中科大张华平博士团队开发,主要功能包括:中文分词,词性标注,命名实体识别,用户词典功能,详情见官网:http://ictclas.nlpir.org ...
- linux环境下给文件加密/解密的方法
原文地址:linix环境下给文件加密/解密的方法 作者:oracunix 一. 利用 vim/vi 加密:优点:加密后,如果不知道密码,就看不到明文,包括root用户也看不了:缺点:很明显让别人知 ...
- 《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端
1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...
- 这是关于FastJson的一个使用Demo,在Java环境下验证的
public class User { private int id; private String name; public int getId() { return id; } public vo ...
- C#对接JAVA系统遇到的AES加密坑
起因对接合作伙伴的系统,需要对数据进行AES加密 默认的使用了已经写好的帮助类中加密算法,发现结果不对,各种尝试改变加密模式改变向量等等折腾快一下午.最后网上查了下AES在JAVA里面的实现完整代码如 ...
- java使用RSA与AES加密解密
首先了解下,什么是堆成加密,什么是非对称加密? 对称加密:加密与解密的密钥是相同的,加解密速度很快,比如AES 非对称加密:加密与解密的秘钥是不同的,速度较慢,比如RSA 先看代码(先会用在研究) 相 ...
- android开发 java与c# 兼容AES加密
由于android客户端采用的是AES加密,服务器用的是asp.net(c#),所以就造成了不一致的加密与解密问题,下面就贴出代码,已经试验过. using System; using System. ...
- C#基础:.NET环境下WebConfig的加密
在将ASP.NET项目部署到服务器上时,内网环境下Web.Config往往是直接复制过去.对于外网环境,则需要对Web.Config文件进行加密. .NET环境下一共提供了2种方式的加密功能,分别是D ...
随机推荐
- iOS之UI--通讯录的实例关键知识技术点积累
通讯录的实例关键知识技术点积累 效果展示: 作为博文笔记,既然是笔记,目的是为了能够以后做这个项目能够快速上手,如果这是我下一次阅览这个博文笔记,那么我应该先空手从零开始做,需求也就是这个项目的展示效 ...
- Modernizr的介绍和使用
传统浏览器目前不会被完全取代,令你难以将最新的 CSS3 或 HTML5 功能嵌入你的网站. Modernizr 正是为解决这一难题应运而生,作为一个开源的 JavaScript 库,Moderniz ...
- Memcache笔记05-Memcache安全性
Memcache服务器端都是直接通过客户端连接后直接操作,没有任何的验证过程,这样如果服务器是直接暴露在互联网上的话是比较危险,轻则数据泄露被其他无关人员查看,重则服务器被入侵,因为Mecache是以 ...
- MongoDB学习笔记——文档操作之增删改
插入文档 使用db.COLLECTION_NAME.insert() 或 db.COLLECTION_NAME.save() 方法向集合中插入文档 db.users.insert( { user_id ...
- 【mysql】一个关于order by排序的问题
I have a table CREATE TABLE `tableMain` ( `id` int(11) NOT NULL AUTO_INCREMENT, `value1` varchar(45) ...
- 设计模式C#实现(四)——迭代器模式
迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示. UML类图: 煎饼屋和餐厅合并了!但是有个小问题,虽然两家都同意实现相同的菜单项MenuItem,但是煎饼屋想使用A ...
- oracle向in语句传入参数查不出数据
在oracle字符串中使用了in,但是查不出数据 string getModel = "select * from TB_YBSH where ID in :ids"; Oracl ...
- C语言杂谈(一)scanf()、scanf_s()与错误 C4996
错误 C4996 初学C语言时,第一个接触到的I/O函数便是scanf()了.但在高版本的 Visual Studio (包括但不限于2015.2013.2012)编译代码时,却会出现意想不到的错误. ...
- TCP/IP详解--TCP首部选项中时间戳选项
一.简介 TCP时间戳选项会在TCP包头增加12个字节,以一种比重发超时更精确的方法来启用对RTT 的计算. 二.作用 ) TCP时间戳位于TCP选项中,kind=:lenth=:data由tim ...
- Swift学习笔记--变量与常量
1.Swift是一门强类型语言,不能为变量赋予其自身数据类型之外的值: 2.声明变量使用var关键字,声明常量使用let关键字: 3.声明变量或常量时没有对其指定类型且赋予了初值,则编译器会自动推断常 ...