AES加解密使用总结

AES加解密使用总结,第1张

AES, 高级加密标准, 是采用区块加密的一种标准, 又称Rijndael加密法 严格上来讲, AES和Rijndael又不是完全一样, AES的区块长度固定为128比特, 秘钥长度可以是128, 192或者256 Rijndael加密法可以支持更大范围的区块和密钥长度, Rijndael使用的密钥和区块长度均可以是128,192或256比特 AES是对称加密最流行的算法之一

我们不去讨论具体的AES的实现, 因为其中要运用到大量的高等数学知识, 单纯的了解AES流程其实也没什么意义(没有数学基础难以理解), 所以我们今天着重来总结一些使用过程中的小点

当然了分组密码的加密模式不仅仅是ECB和CBC这两种, 其他的我们暂不涉及

上面说的AES是一种区块加密的标准, 那加密模式其实可以理解为处理不同区块的方式和联系

ECB可以看做最简单的模式, 需要加密的数据按照区块的大小分为N个块, 并对每个块独立的进行加密

此种方法的缺点在于同样的明文块会被加密成相同的密文块, 因此, 在某些场合, 这种方法不能提供严格的数据保密性 通过下面图示例子大家就很容易明白了

我们的项目中使用的就是这种模式, 在CBC模式中, 每个明文块与前一个块的加密结果进行异或后, 在进行加密, 所以每个块的加密都依赖前面块的加密结果的, 同时为了保证第一个块的加密, 在第一个块中需要引入初始化向量iv

CBC是最常用的模式 他的缺点是加密过程只能是串行的, 无法并行, 因为每个块的加密要依赖到前一个块的加密结果, 同时在加密的时候明文中的细微改变, 会导致后面所有的密文块都发生变化 但此种模式也是有优点的, 在解密的过程中, 每个块的解密依赖上一个块的加密结果, 所以我们要解密一个块的时候, 只需要把他前面一个块也一起读取, 就可以完成本块的解密, 所以这个过程是可以并行 *** 作的

AES加密每个块blockSize是128比特, 那如果我们要加密的数据不是128比特的倍数, 就会存在最后一个分块不足128比特, 那这个块怎么处理, 就用到了填充模式 下面是常用的填充模式

PKCS7可用于填充的块大小为1-255比特, 填充方式也很容易理解, 使用需填充长度的数值paddingSize 所表示的ASCII码 paddingChar = chr(paddingSize)对数据进行冗余填充 (后面有解释)

PKCS5只能用来填充8字节的块

我们以AES(128)为例, 数据块长度为128比特, 16字节, 使用PKCS7填充时, 填充长度为1-16 注意, 当加密长度是16整数倍时, 反而填充长度是最大的, 要填充16字节 原因是 "PKCS7" 拆包时会按协议取最后一个字节所表征的数值长度作为数据填充长度, 如果因真实数据长度恰好为16的整数倍而不进行填充, 则拆包时会导致真实数据丢失

举一个blockSize为8字节的例子

第二个块中不足8字节, 差4个字节, 所以用4个4来填充

严格来讲 PKCS5不能用于AES, 因为AES最小是128比特(16字节), 只有在使用DES此类blockSize为64比特算法时, 考虑使用PKCS5

我们的项目最开始加解密库使用了CryptoSwift, 后来发现有性能问题, 就改为使用IDZSwiftCommonCrypto

这里咱们结合项目中边下边播边解密来提一个点, 具体的可以参考之前写的 边下边播的总结 因为播放器支持拖动, 所以我们在拖拽到一个点, 去网络拉取对应数据时, 应做好range的修正, 一般我们都会以range的start和end为基准, 向前后找到包含这个range的所有块范围 打比方说我们需要的range时10-20, 这是我们应该修正range为0-31, 因为起点10在0-15中, 20 在16-31中 这是常规的range修正(第一步 找16倍数点)

但是在实际中, 我们请求一段数据时, 还涉及到解密器的初始化问题, 如果我们是请求的0-31的数据, 因为是从0开始, 所以我们的解密器只需要用key和初始的iv来进行初始化, 那如果经过了第一步的基本range修正后, 我们请求的数据不是从0开始, 那我们则还需要继续往前读取16个字节的数据, 举个例子, 经过第一步修正后的range为16-31, 那我们应该再往前读取16字节, 应该是要0-31 这32个字节数据, 拿到数据后,使用前16个字节(上一个块的密文)当做iv来初始化解密器

还有一个要注意的点是, 数据解密的过程中, 还有可能会吞掉后面16个字节的数据, 我暂时没看源码, 不知道具体因为什么, 所以保险起见, 我们的range最好是再向后读取6个字节

感谢阅读

参考资料

>

JDK对DESede算法的支持

密钥长度:128位

工作模式:ECB/CBC/PCBC/CTR/CTS/CFB/CFB8 to CFB128/OFB/OBF8 to OFB128

填充方式:Nopadding/PKCS5Padding/ISO10126Padding/

AES加密解密的java实现:

package comkongxincaiencanddec;import javasecurityKey;import javasecurityNoSuchAlgorithmException;import javaxcryptoCipher;import javaxcryptoKeyGenerator;import javaxcryptoSecretKey;import javaxcryptospecSecretKeySpec;public class AESCoder {   private static final String KEY_ALGORITHM = "AES";   private static final String DEFAULT_CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//默认的加密算法

public static byte[] initSecretKey() {       //返回生成指定算法密钥生成器的 KeyGenerator 对象

KeyGenerator kg = null;       try {

kg = KeyGeneratorgetInstance(KEY_ALGORITHM);

} catch (NoSuchAlgorithmException e) {

eprintStackTrace();           return new byte[0];

}       //初始化此密钥生成器,使其具有确定的密钥大小       //AES 要求密钥长度为 128

kginit(128);       //生成一个密钥

SecretKey  secretKey = kggenerateKey();       return secretKeygetEncoded();

}   private static Key toKey(byte[] key){       //生成密钥

return new SecretKeySpec(key, KEY_ALGORITHM);

}   public static byte[] encrypt(byte[] data,Key key) throws Exception{       return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);

}   public static byte[] encrypt(byte[] data,byte[] key) throws Exception{       return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);

}   public static byte[] encrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{       //还原密钥

Key k = toKey(key);       return encrypt(data, k, cipherAlgorithm);

}   public static byte[] encrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{       //实例化

Cipher cipher = CiphergetInstance(cipherAlgorithm);       //使用密钥初始化,设置为加密模式       cipherinit(CipherENCRYPT_MODE, key);       //执行 *** 作

return cipherdoFinal(data);

}   public static byte[] decrypt(byte[] data,byte[] key) throws Exception{       return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);

}   public static byte[] decrypt(byte[] data,Key key) throws Exception{       return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);

}   public static byte[] decrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{       //还原密钥

Key k = toKey(key);       return decrypt(data, k, cipherAlgorithm);

}   public static byte[] decrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{       //实例化

Cipher cipher = CiphergetInstance(cipherAlgorithm);       //使用密钥初始化,设置为解密模式       cipherinit(CipherDECRYPT_MODE, key);       //执行 *** 作

return cipherdoFinal(data);

}   private static String  showByteArray(byte[] data){       if(null == data){           return null;

}

StringBuilder sb = new StringBuilder("{");       for(byte b:data){

sbappend(b)append(",");

}

sbdeleteCharAt(sblength()-1);

sbappend("}");       return sbtoString();

}   public static void main(String[] args) throws Exception {       byte[] key = initSecretKey();

Systemoutprintln("key:"+showByteArray(key));

Key k = toKey(key); //生成秘钥

String data ="AES数据";

Systemoutprintln("加密前数据: string:"+data);

Systemoutprintln("加密前数据: byte[]:"+showByteArray(datagetBytes()));

Systemoutprintln();       byte[] encryptData = encrypt(datagetBytes(), k);//数据加密

Systemoutprintln("加密后数据: byte[]:"+showByteArray(encryptData));//       Systemoutprintln("加密后数据: hexStr:"+HexencodeHexStr(encryptData));       Systemoutprintln();       byte[] decryptData = decrypt(encryptData, k);//数据解密

Systemoutprintln("解密后数据: byte[]:"+showByteArray(decryptData));

Systemoutprintln("解密后数据: string:"+new String(decryptData));

}

}

这个算法java SDK自带的额 参考代码如下:

/解密

 @param content  待解密内容

 @param password 解密密钥

 @return

/

public static byte[] decrypt(byte[] content, String password) {

try {

KeyGenerator kgen = KeyGeneratorgetInstance("AES");

kgeninit(128, new SecureRandom(passwordgetBytes()));

SecretKey secretKey = kgengenerateKey();

byte[] enCodeFormat = secretKeygetEncoded();

SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");

Cipher cipher = CiphergetInstance("AES");// 创建密码器

cipherinit(CipherDECRYPT_MODE, key);// 初始化

byte[] result = cipherdoFinal(content);

return result; // 加密

} catch (NoSuchAlgorithmException e) {

eprintStackTrace();

} catch (NoSuchPaddingException e) {

eprintStackTrace();

} catch (InvalidKeyException e) {

eprintStackTrace();

} catch (IllegalBlockSizeException e) {

eprintStackTrace();

} catch (BadPaddingException e) {

eprintStackTrace();

}

return null;

}

/

 加密

 @param content 需要加密的内容

 @param password  加密密码

 @return

/

public static byte[] encrypt(String content, String password) {

try {

KeyGenerator kgen = KeyGeneratorgetInstance("AES");

kgeninit(128, new SecureRandom(passwordgetBytes()));

SecretKey secretKey = kgengenerateKey();

byte[] enCodeFormat = secretKeygetEncoded();

SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");

Cipher cipher = CiphergetInstance("AES");// 创建密码器

byte[] byteContent = contentgetBytes("utf-8");

cipherinit(CipherENCRYPT_MODE, key);// 初始化

byte[] result = cipherdoFinal(byteContent);

return result; // 加密

} catch (NoSuchAlgorithmException e) {

eprintStackTrace();

} catch (NoSuchPaddingException e) {

eprintStackTrace();

} catch (InvalidKeyException e) {

eprintStackTrace();

} catch (UnsupportedEncodingException e) {

eprintStackTrace();

} catch (IllegalBlockSizeException e) {

eprintStackTrace();

} catch (BadPaddingException e) {

eprintStackTrace();

}

return null;

}

>

1 引言 随着因特网的发展,信息传输及存储的安全问题成为影响因特网应用发展的重要因素。信息安全技术也就成为了人们研究因特网应用的新热点。 信息安全的研究包括密码理论与技术、安全协议与技术、安全体系结构理论、信息对抗理论与技术、网络安全与安全产品等领域,其中密码算法的理论与实现研究是信息安全研究的基础。

2 AES加密标准

1977年1月公布的数据加密标准DES(Data Encrption Standard)经过20年的实践应用后,现在已被认为是不可靠的。1997年1月美国国家标准和技术研究所(NIST)发布了高级加密标准(AES- FIPS)的研发计划,并于同年9月正式发布了征集候选算法公告[1],NIST希望确定一种保护敏感信息的公开、免费并且全球通用的算法作为AES,以代替DES。NIST对算法的基本要求是:算法必须是私钥体制的分组密码,支持128位分组长度和129、192、256bits密钥长度。

3 AES的研究现状

从1997年NIST发布了高级加密标准AES的研发计划到现在,对AES的研究大致可以分成三个阶段。第一阶段是从1997到2000年,研究的主要方向是提出候选算法并对各候选算法的性能进行分析。在此期间共提出了十五个候选算法,最终Rijndael算法胜出并用于AES中。Rijndael算法是一种可变分组长度和密钥长度的迭代型分组密码,它的分组长度和密钥长度均可独立地指定为128bits、192bits、256bits,它以其多方面的优良性能,成为AES的最佳选择。Rijndael算法能抵抗现在的所有己知密码攻击,它的密钥建立时间极短且灵活性强,它极低的内存要求使其非常适合在存储器受限的环境中使用,并且表现出很好的性能。第二阶段是从2000年Rijndael算法胜出后到2001年NIST发布FIPS PUBS 197文件前。在此阶段对AES的研究转到了对Rijndael算法的研究和分析、设计AES的工作模式上。第三阶段是从FIPS PUBS 197发布到现在。在此阶段,研究的方向可以分成两个主要方向:一个是继续研究Rijndael算法本身的性能,特别是其安全性分析;另一个就是AES的实现和应用的研究。

算法设计主要研究算法设计遵循的原则和整体结构,为性能分析提供了一条途径。从算法的结构上分析算法性能是简单有效的,研究算法整体结构上的缺陷为提出新的密码分析方法提供新的手段。另一方面,研究AES的算法设计对研发新的分组密码提供了设计原则和参考。目前分组数据加密算法的整体结构有两大类:Feistel网络、非平衡Feistel网络和SP网络。

性能分析主要研究算法的各项特性,性能分析主要可以分为实现分析和密码分析两类。实现分析主要研究AES算法可实现的能力。当前实现性分析主要集中在AES的硬、软件实现的难易度和实现算法的效率等领域中。密码分析则是在理论上对现有加密算法进行研究的主要方向。密码分析主要研究AES算法抵抗现有己知密码攻击的能力,即算法的安全性分析。当前主要攻击手段有:强力攻击、差分密码分析[2][3]、 线性密码分析[4]、Square攻击和插值攻击等。

但是随着密码分析技术的不断发展,积分分析、功耗分析和代数攻击等新的密码分析手段陆续出现。它们己成为密码分析新的研究方向[5]。

4 AES的实现

对于AES实现的研究主要集中在软件实现和硬件实现两个领域中。AES标准所选择的Rijndael算法遵循了分组密码设计的实现性原则,十分方便在软、硬件上实现。从AES实现的角度上看,当前研究的主要方向在各个算法步骤的优化实现。算法步骤针对不同的实现环境进行优化后,在应用中能获取更好的实际数据加密效果。其主要的研究成果集中在S-盒的生成算法优化、轮变换过程优化和密钥扩展优化三个方面。下面就软件实现和硬件实现在这三个方面的研究现状做一个简单介绍:

(1) 在微机上通过软件实现。这是利用AES算法保障计算机信息安全,特别是网络中信息传输与存储安全的主要途径。在软件实现中,轮变换过程优化则是软件实现算法优化的主要研究方向。密钥扩展优化也是研究的重点之一。AES所提供的密钥扩展方案保证了密钥扩展过程中的雪崩效应,也保证了密钥扩展方案的易实现性。此外,将其他的理论研究应用到分组数据加密算法中,也是实现研究的一个重要方向。

(2) 通过硬件芯片实现。AES算法对于存储空间的要求较小,算法过程相对比较简单,特别是经过有针对性的实现算法优化和精简后很易于利用硬件电路实现,因此现在许多相关的商业产品都是基于密码芯片的。

5 AES研究意义

目前,DES加密标准正在逐渐淡出加密标准的舞台,新加密标准AES正在获得越来越多的重视及应用。面对未来的发展,对AES产品的需求是非常巨大的。因此,对AES实现的探讨和研究具有很大的理论意义和实践意义。

――――――――――

参考文献

[1]褚振勇,翁木云FPGA设计及应用西安电子科技大学出版社,2002,7

[2]李玉山,来新泉电子系统集成设计技术电子工业出版社,2002,10

[3]牛风举,刘元成,朱明程基于IP复用的数字IC设计技术,2003,9

[4]Joan Daemon, Vincent Rijmen高级加密标准(AES)算法:Rijndael的设计谷大武,徐胜波,译清华大学出版社,2003,3

[5]Bruce Schneie应用密码学:协议、算法与C源程序昊世忠,祝世雄,张文政,等,译机械工业出版社,2000,1

作者简介:李佳(1976-),女,河北唐山人,讲师,北京科技大学工程硕士,主要研究网络数据安全。

以上就是关于AES加解密使用总结全部的内容,包括:AES加解密使用总结、c/c++实现AES加密,支持cbc等加密模式,支持多种填充模式,不要openssl实现的、请教个关于Java实现AES加解密的问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zz/10071960.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-04
下一篇2023-05-04

发表评论

登录后才能评论

评论列表(0条)

    保存