java加密解密AES笔记

来源:互联网 发布:c语言是高级语言 编辑:程序博客网 时间:2024/06/06 20:53

加密技术可以分为对称与非对称两种.
对称加密,解密,即加密与解密用的是同一把秘钥,常用的对称加密技术有DES,AES等
而非对称技术,加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA,ECDH等

为什么要有非对称加密,解密技术呢?
假设这样一种场景A要发送一段消息给B,但是又不想以明文发送,所以就需要对消息进行加密.如果采用对称加密技术,那么加密与解密用的是同一把秘钥.除非B事先就知道A的秘钥,并且保存好.这样才可以解密A发来的消息.
由于对称技术只有一把秘钥,所以秘钥的管理是一个很麻烦的问题.而非对称技术的诞生就解决了这个问题.非对称加密与解密使用的是不同的秘钥,并且秘钥对是一一对应的,即用A的私钥加密的密文只有用A的公钥才能解密.
这样的话,每个人都有两把秘钥,私钥和公钥,私钥是只有自己才知道的,不能告诉别人,而公钥是公开的,大家都可以知道.这样,当A想要发送消息给B的时候,只需要用B的公钥对消息进行加密就可以了,由于B的私钥只有B才拥有,所以A用B的公钥加密的消息只有B才能解开.而B想更换自己的秘要时也很方便,只须把公钥告诉大家就可以了.
那么,既然非对称加密如此之好,对称加密就没有存在的必要了啊,其实不然,由于非对称加密算法的开销很大,所以如果直接以非对称技术来加密发送的消息效率会很差.那么怎么办呢?解决的办法也很简单,就是把对称加密技术与非对称加密技术结合起来使用.

举个栗子--A要发送一条消息给B.
对于A:
一,A先生成一个对称秘钥,这个秘钥可以是随机生成的,
二,A用B的公钥对第一步生成的这个对称秘钥进行加密
三,A把这个加密过的对称秘钥发给B
四,A用第一步生成的对称秘钥加密实际要发送的消息
五,A把采用对称秘钥加密的消息发给B

对于B:
他先收到A发来的对称秘钥,这个秘钥是用B的公钥加密过的,所以B需要用自己的私钥来解密这个秘钥
然后B又收到A发来的密文,这时候用刚才解密出来的秘钥来解密密文

这样子的整个过程既保证了安全(B解密时的密钥是通过非对称加密的),又保证了效率(加密的数据是通过对称加密).



背景:加密算法由算法+模式+填充组成,故不同的填充算法会导致相同明文相同密钥加密后出现密文不一致的情况。

1、模式:
JCE中AES支持五中模式:CBC,CFB,ECB,OFB,PCBC;

  CBC(密码分组链接模式):是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。
  ECB(电码本模式):是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
  ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化向量。
CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。

2、填充方式
JCE支持三种填充:NoPadding,PKCS5Padding,ISO10126Padding。
不支持SSL3Padding。不支持“NONE”模式。
首先,不带模式和填充来获取AES算法的时候,其默认使用ECB/PKCS5Padding。

其次,java中原生是不支持采用AES加密算法PKCS7Padding来填充的,只支持PKCS5Padding。

如果要在在java端采用PKCS7Padding填充,需用到bouncycastle组件来实现,Bouncy Castle是一种用于java平台的开放源码的轻量级密码术包,支持大量的密码术算法。



AES各算法组合说明算法/模式/填充16字节加密后数据长度不满16字节加密后长度AES/CBC/NoPadding16不支持AES/CBC/PKCS5Padding3216AES/CBC/ISO10126Padding3216AES/CFB/NoPadding16原始数据长度AES/CFB/PKCS5Padding3216AES/CFB/ISO10126Padding3216AES/ECB/NoPadding16不支持AES/ECB/PKCS5Padding3216AES/ECB/ISO10126Padding3216AES/OFB/NoPadding16原始数据长度AES/OFB/PKCS5Padding3216AES/OFB/ISO10126Padding3216AES/PCBC/NoPadding16不支持AES/PCBC/PKCS5Padding3216AES/PCBC/ISO10126Padding3216

   

     可以看到,在原始数据长度为16的整数倍时,假如原始数据长度等于16*n,则使用NoPadding时加密后数据长度等于16*n,其它情况下加密数据长度等于16*(n+1)。在不足16的整数倍的情况下,假如原始数据长度等于16*n+m[其中m小于16],除了NoPadding填充之外的任何方式,加密数据长度都等于16*(n+1);NoPadding填充情况下,CBC、ECB和PCBC三种模式是不支持的,CFB、OFB两种模式下则加密数据长度等于原始数据长度。


关于AES加密中key的字节数

若出现类似 Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 6 bytes

原因:AES supports 128, 192 and 256 bit keys, so the number of bytes needs to be 16, 24, or 32. Note that the latter two may not be available in all circumstances (as the comment in the "kgen.init(128)" line mentions). 请检查密钥的长度是否为16,24,或者32


关于 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中说:

  1. 因为恢复的明文的最后一个字节 告诉你 存在多少个填充字节, 用PKCS#5 填充 的加密方法, 即使在输入的明文长度 恰好是 块大小(Block Size)整数倍 , 也会增加一个完整的填充块. 否则,恢复出来的明文的最后一个字节可能是实际的消息字节.
  2. 因为第1个因素限制了 使用PKCS#填充的 对称加密算法的 输入块大小(Block Size, 注意不是输入的明文的总长度 total input length), 最大只能是256个字节.   因为大多数对称块加密算法 通常使用8字节或者16字节的块, 所以,这不是一个问题
  3. 使用ECB模式填充可能会有安全问题.
  4. 使用PKCS#5填充 可以很方便地检测明文中的错误.


参考:对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB) :http://www.cnblogs.com/happyhippy/archive/2006/12/23/601353.html

0 0
原创粉丝点击