Atitit.加密算法 des aes 各个语言不同的原理与解决方案java php c#
1. 加密算法的参数::算法/模式/填充 1
2. 标准加密api使用流程 1
2.1. Md5——16bit 填充key,使其长度达到128(或其他规定的长度) 2
2.2. 生成key 2
2.3. 运算 2
3. Aes加密原理架构图 2
4. Key的算法不一致 4
5. 加密模式 4
5.1. Ecb 4
5.2. 3.2 CBC模式: 5
5.3. OFB模式: 6
5.4. 3.3 CFB模式: 7
6. padding方式 8
6.1.1. Padding方式架构图 9
7. 算法/模式/填充 对比表 9
8. 16字节加密后数据长度 不满16字节加密后长度 10
9. Java中的加密系列 11
9.1. 安全提供者体系结构 11
9.1.1. 引擎和算法。引擎可以理解为操作,如加密、解密等 11
9.2. 3.2.12 SecureRandom类 12
9.3. Key接口 12
9.4. 3.4.3 SecretKeySpec类 14
10. Aes算法的常见问题解决 14
11. 参考 15
1. 加密算法的参数::算法/模式/填充
/* 模型化密钥的概念。由于密钥必须在不同实体之间传输,因此所有的密钥都必须是可以序列化的*/
还有字符编码方式,特别是以中文做密钥的时候。
2. 标准加密api使用流程
2.1. Md5——16bit 填充key,使其长度达到128(或其他规定的长度)
key=MD5.getMD5_16bit(key,"utf-8");
byte[] bytes = key.getBytes();
SecretKeySpec keySpec = new SecretKeySpec(bytes, "AES");
return keySpec;
2.2. 生成key
2.3. 运算
作者:: 老哇的爪子 Attilax 艾龙, EMAIL:1466519819@qq.com
转载请注明来源: http://blog.csdn.net/attilax
3. Aes加密原理架构图
AES对称加密:
4. Key的算法不一致
原来是我指定key的方式不对, 直接将字符串做为参数, 想当然的以为这就是key, 其实不然, CryptoJS会根据这个字符串算出真正的key和IV(各种新鲜名词不解释, 问我也没用, 我也不懂 -_-")
5. 加密模式
五中模式:CBC,CFB,ECB,OFB,PCBC
不带模式和填充来获取AES算法的时候,其默认使用ECB/PKCS5Padding。
模式 更安全,不同的模式可能安全性更高点。。。
5.1. Ecb
ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。
优点:
1.简单;
2.有利于并行计算;
3.误差不会被传送;
缺点:
1.不能隐藏明文的模式;
2.可能对明文进行主动攻击;
5.2. 3.2 CBC模式:
优点:
1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
缺点:
1.不利于并行计算;
2.误差传递;
3.需要初始化向量IV
5.3. OFB模式:
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.对明文的主动攻击是可能的;
3.误差传送:一个明文单元损坏影响多个单元;
5.4. 3.3 CFB模式:
优点:
1.隐藏了明文模式;
2.分组密码转化为流模式;
3.可以及时加密传送小于分组的数据;
缺点:
1.不利于并行计算;
2.误差传送:一个明文单元损坏影响多个单元;
3.唯一的IV;
6. padding方式
AES一般是16个字节为一块,然后对这一整块进行加密,如果输入的字符串不够16个字节,就需要补位,
PKCS5Padding:填充的原则是,如果长度少于16个字节,需要补满16个字节,补(16-len)个(16-len)例如:
123这个节符串是3个字节,16-3= 13,补满后如:123+13个十进制的13,
如果字符串长度正好是16字节,则需要再补16个字节的十进制的16。
CryptoJS进行DES加密时, 默认的模式和padding方式和Java默认的不一样造成的, 必须使用ECB mode和PKCS5Padding, 但是CryptoJS中只有Pkcs7, 不管了, 试试看...
支持三种填充:NoPadding,PKCS5Padding,ISO10126Padding。不支持SSL3Padding。不支持“NONE”模式。
6.0.1. Padding方式架构图
7. 算法/模式/填充 对比表
8. 16字节加密后数据长度 不满16字节加密后长度
AES/CBC/NoPadding 16 不支持
AES/CBC/PKCS5Padding 32 16
AES/CBC/ISO10126Padding 32 16
AES/CFB/NoPadding 16 原始数据长度
AES/CFB/PKCS5Padding 32 16
AES/CFB/ISO10126Padding 32 16
AES/ECB/NoPadding 16 不支持
AES/ECB/PKCS5Padding 32 16
AES/ECB/ISO10126Padding 32 16
AES/OFB/NoPadding 16 原始数据长度
AES/OFB/PKCS5Padding 32 16
AES/OFB/ISO10126Padding 32 16
AES/PCBC/NoPadding 16 不支持
AES/PCBC/PKCS5Padding 32 16
AES/PCBC/ISO10126Padding 32 16
9. Java中的加密系列
9.1. 安全提供者体系结构
Java安全体系结构通过扩展的方式,加入了更多的算法实现及相应的安全机制。我们把这些提供者称为安全提供者(以下简称“提供者”)。以下内容是JDK 1.7所提供的安全提供者的配置信息。
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=sun.security.ec.SunEC
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI
9.1.1. 引擎和算法。引擎可以理解为操作,如加密、解密等
安全提供者实现了两个概念的抽象:引擎和算法。引擎可以理解为操作,如加密、解密等。算法则定义了操作如何执行,如一个算法可以理解为一个引擎的具体实现。当然,一个算法可以有多种实现方式,这就意味着同一个算法可能与多个引擎的具体实现相对应。
安全提供者接口的目的就是提供一个简单的机制,从而可以很方便地改变或替换算法及其实现。在实际开发中,程序员只需要用引擎类实现特定的操作,而不需要关心实际进行运算的类是哪一个。
Provider类和Security类(java.security.Security)共同构成了安全提供者的概念。我们将在本章中介绍这两个类的Java API。
9.2. 3.2.12 SecureRandom类
SecureRandom类继承于Random类(java.util.Random),它起到强加密随机数生成器(Random Number Generator,RNG)的作用,我们称之为安全随机数生成器,它同样是一个引擎类。
// 提供安全随机数
publicclass SecureRandom
extends Random
9.3. Key接口
/* 模型化密钥的概念。由于密钥必须在不同实体之间传输,因此所有的密钥都必须是可以序列化的*/
所有的密钥都具有三个特征:
算法。这里指的是密钥的算法,如DES和DSA等,通过getAlgorithm()方法可获得算法名。
编码形式。这里指的是密钥的外部编码形式,密钥根据标准格式(如X.509 SubjectPublicKeyInfo或 PKCS#8)编码,使用getEncoded()方法可获得编码格式。
格式。这里指的是已编码密钥的格式的名称,使用getFormat()方法可获得格式。
对应上述三个特征,Key接口提供如下三个方法:
// 返回此密钥的标准算法名称
public String getAlgorithm()
/* 返回基本编码格式的密钥,通常为二进制格式,如果此密钥不支持编码,则返回 null*/
public byte[] getEncoded()
// 返回此密钥的基本编码格式,如果此密钥不支持编码,则返回 null
public String getFormat()
SecretKey、PublicKey、PrivateKey三大接口继承于Key接口,定义了对称密钥和非对称密钥接口。
(1)SecretKey
public abstract interface SecretKey extends Key {
public static final long serialVersionUID = -4795878709595146952L;
}
SecretKey(javax.crypto.SecretKey)接口是对称密钥顶层接口。DES、AES等多种对称密码算法密钥均可通过该接口提供,PBE(javax.crypto.interfaces.PBE)接口提供PEB算法定义并继承了该接口。Mac算法实现过程中,通过SecretKey接口提供秘密密钥。通常使用的是SecretKey接口的实现类SecretKeySpec(javax.crypto.spec.SecretKeySpec)。
public abstract interface Key extends Serializable {
public static final long serialVersionUID = 6603384152749567654L;
public abstract String getAlgorithm();
public abstract String getFormat();
public abstract byte[] getEncoded();
}
9.4. 3.4.3 SecretKeySpec类
SecretKeySpec类是KeySpec接口的实现类,用于构建秘密密钥规范。可根据一个字节数组构造一个SecretKey,而无须通过一个(基于provider的)SecretKeyFactory。
// 此类以与provider无关的方式指定一个密钥
public class SecretKeySpec
extends Object
implements KeySpec, SecretKey
此类仅对能表示为一个字节数组并且没有任何与之相关联的密钥参数的原始密钥有用,如DES或Triple DES密钥。
10. Aes算法的常见问题解决
java.security.InvalidKeyException: Invalid AES key length: 8 bytes”,
解决方法,填充key字符串
SecretKeySpec aesKey = new SecretKeySpec("1234567812345678".getBytes(), "AES"); //Key要16位的
因为AES是128\192\256。。。
DES的密钥必须是24位的byte数组
随便拿一个String.getBytes()是不行的,会报如下错误
java.security.InvalidKeyException: Invalid key length: 59 bytes
解决方法有很多,①按密钥固定长度重新定义字符串; 麻烦
②先把字符串用Base64或者MD5加密,然后截取固定长度的字符转成byte数组;
推荐
③字符串转成Byte数组,针对该数组进行修改,若长度过长则只截取一部分,若长度不够则补零
这个也不好,可能脚本语言对bite操作能力弱。。而且不是唯一。
11. 参考
为什么 CryptoJS DES 加密的结果和 Java DES 不一样_.html
JCE中支持AES,支持的模式和填充方式-gh_aiyz-ChinaUnix博客.html
C++和Java用AES_ECB_PKCS5Padding算法加解密互通 - 独孤小孩的日志 - 网易博客.html
paip.提升安全性----Des加密 java php python的实现总结 - attilax的专栏 - 博客频道 - CSDN.NET.html
(detail) 分组对称加密模式_ECB_CBC_CFB_OFB - aaaaatiger--寻路 - 博客频道 - CSDN.NET.html
(detail)3.2.12 SecureRandom类_Java加密与解密的艺术_红黑联盟读书频道.html
【推荐】JAVA基础◆浅谈3DES加密解密 - 孤剑之家 - 博客频道 - CSDN.NET.html
AES加密时抛出java.security.InvalidKeyException_ Illegal key size or default parameter - ksgimi - ITeye技术网站.html