珍岛网站模板,推广普通话的内容简短,都匀网站制作公司,网页设计基础教程第七章课后习题前言知识#xff1a;
1.AES#xff08;Advanced Encryption Standard#xff09;高级加密标准#xff0c;作为分组密码#xff08;把明文分成一组一组的#xff0c;每组长度相等#xff0c;每次加密一组数据#xff0c;直到加密完整个明文#xff09;。
2.在AES标准…
前言知识
1.AESAdvanced Encryption Standard高级加密标准作为分组密码把明文分成一组一组的每组长度相等每次加密一组数据直到加密完整个明文。
2.在AES标准规范中分组长度只能是128位也就是说每个分组为16个字节每个字节8位8的倍数。密钥的长度可以使用128位、192位或256位分别对应的就是AES128AES192AES256密钥的长度不同推荐加密轮数也不同从安全性来看AES256安全性最高。从性能看AES128性能最高。本质原因就是它们的加密处理轮数不同
3.AES属于对称加密算法是因为加解密使用同一个秘钥
4.AES支持三种长度的密钥 128位192位256位一般有至少4种模式即ECB、CBC、CFB、OFB等 5.AES算法在对明文加密的时候并不是把整个明文一股脑的加密成一整段密文而是把明文拆分成一个个独立的明文块每一个明文块长度128bit。 这些明文块经过AES加密器复杂处理生成一个个独立的密文块这些密文块拼接在一起就是最终的AES加密的结果。 但这里涉及到一个问题假如一段明文长度是196bit如果按每128bit一个明文块来拆分的话第二个明文块只有64bit不足128bit。这时候怎么办呢就需要对明文块进行填充Padding 。 6.几种典型的填充方式 NoPadding 不做任何填充但是要求明文必须是16字节的整数倍。PKCS5PaddingJava默认 如果明文块少于16个字节128bit在明文块末尾补足相应数量的字符且每个字节的值等于缺少的字符数。 比如明文{1,2,3,4,5,a,b,c,d,e},缺少6个字节则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6 }ISO10126Padding如果明文块少于16个字节128bit在明文块末尾补足相应数量的字节最后一个字符值等于缺少的字符数其他字符填充随机数。比如明文{1,2,3,4,5,a,b,c,d,e},缺少6个字节则可能补全为{1,2,3,4,5,a,b,c,d,e,5,c,3,G,$,6}PKCS7Padding原理与PKCS5Padding相似区别是PKCS5Padding的blocksize为8字节而PKCS7Padding的blocksize可以为1到255字节 需要注意的是如果在AES加密的时候使用了某一种填充方式解密的时候也必须采用同样的填充方式ZeroPadding(C默认,java没有次填充方式):java操作的话明文不足16位则手动补零然后调用NoPadding AES四种工作模式原理
1、ECB模式
ECB 电子密码本模式是最简单的块密码加密模式,加密前根据数据块大小如AES为128位每组大小跟加密秘钥长度相同分成若干块之后将每块使用相同的密钥单独通过块加密器密器。这种加密模式的优点就是简单,不需要初始化向量IV 每个数据块独立进行加/解密利于并行计算加/解密效率很高。但这种模式中所有数据都采用相同密钥进行加/解密也没有经过任何逻辑运算相同明文得到相同的密文所以可能导致“选择明文攻击”的发生。最早采用和最简单的模式 优点: 1.简单 2.有利于并行计算 3.误差不会被扩散 缺点: 1.不能隐藏明文的模式 2.可能对明文进行主动攻击 因此此模式适于加密小消息 2、CBC模式 参考
CBC 密码分组链接模式是先将明文切分成若干小块然后每个小块与初始块或者上一段的密文段进行逻辑异或运算后再用密钥进行加密。第一个明文块与一个叫初始化向量的数据块进行逻辑异或运算。这样就有效的解决了ECB模式所暴露出来的问题即使两个明文块相同加密后得到的密文块也不相同。但是缺点也相当明显如加密过程复杂效率低等。 优点 不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。 缺点 1.不利于并行计算 2.误差传递 3.需要初始化向量IV 3、CFB模式
与ECB和CBC模式只能够加密块数据不同CFB模式能够将密文转化成为流密文。这种加密模式中由于加密流程和解密流程中被块加密器加密的数据是前块的密文因此即使本块明文数据的长度不是数据块大小的整数倍也是不需要填充的这保证了数据长度在加密前后是相同的。 优点 1.隐藏了明文模式; 2.分组密码转化为流模式; 3.可以及时加密传送小于分组的数据; 缺点: 1.不利于并行计算; 2.误差传送一个明文单元损坏影响多个单元; 3.唯一的IV; 4、OFB模式
不再直接加密明文块其加密过程是先使用块加密器生成密钥流然后再将密钥流和明文流进行逻辑异或运算得到密文流。 优点: 1.隐藏了明文模式; 2.分组密码转化为流模式; 3.可以及时加密传送小于分组的数据; 缺点: 1.不利于并行计算; 2.对明文的主动攻击是可能的; 3.误差传送一个明文单元损坏影响多个单元; AES的算法原理
加密算法的一般设计准则
混淆 (Confusion) 最大限度地复杂化密文、明文与密钥之间的关系通常用非线性变换算法达到最大化的混淆。
扩散 (Diffusion) 明文或密钥每变动一位将最大化地影响密文中的位数通常采用线性变换算法达到最大化的扩散。
对Rijndael算法来说解密过程就是加密过程的逆向过程。下图为AES加解密的流程从图中可以看出1)解密算法的每一步分别对应加密算法的逆操作2)加解密所有操作的顺序正好是相反的。正是由于这几点(再加上加密算法与解密算法每步的操作互逆)保证了算法的正确性。具体参考1 参考2 正文C中AES_cbc_encrypt加密对应java中的解密
//C中的加密方式
AES_cbc_encrypt((const unsigned char*)in.data(),(unsigned char*)out.data(),len,aes,(unsigned char*)ivec.data(),AES_ENCRYPT); AES_cbc_encrypt这是C中AES中的CBC加密方式可以对任意长度的输入数据进行加密若输入数据不为16字节整数倍时该函数内部会使用ZeroPadding自动对输入数据进行填充再进行加密。然后我查了一下java中没有ZeroPadding都是手动实现补零然后调用NoPadding的,我的具体实现
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;/*** ClassName AESCBCUtil* Description TODO* Author wanghaha* Date 2023/3/1**/
public class AESCBCUtil {/** Description: 满足pc的加密方式 生成128位* Author: wanghaha* Date: 2023/3/1* param: data* param: iv* return: java.lang.String**/public static String encrypt128(String data, String iv) {byte[] key new byte[16];for (int i 0; i 16; i) {key[i] (byte) (29 i * 3);}try {Cipher cipher Cipher.getInstance(AES/CBC/NoPadding);byte[] dataBytes data.getBytes();byte[] plaintext new byte[128];//填充System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);SecretKeySpec keySpec new SecretKeySpec(key, AES);//设置偏移量参数IvParameterSpec ivSpec new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);byte[] encryped cipher.doFinal(plaintext);return DatatypeConverter.printBase64Binary(encryped);} catch (Exception e) {e.printStackTrace();return null;}}/* 加密 正常长度* Description:* Author: wanghaha* Date: 2023/3/1* param: null* return: null**/public static String encrypt(String data, String iv) {byte[] key new byte[16];for (int i 0; i 16; i) {key[i] (byte) (29 i * 3);}try {Cipher cipher Cipher.getInstance(AES/CBC/NoPadding);byte[] dataBytes data.getBytes();int blockSize cipher.getBlockSize();int length dataBytes.length;//计算需填充长度if (length % blockSize ! 0) {length length (blockSize - (length % blockSize));}byte[] plaintext new byte[length];//填充System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);SecretKeySpec keySpec new SecretKeySpec(key, AES);//设置偏移量参数IvParameterSpec ivSpec new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);byte[] encryped cipher.doFinal(plaintext);return DatatypeConverter.printBase64Binary(encryped);} catch (Exception e) {e.printStackTrace();return null;}}//解密public static String desEncrypt(String data, String iv) {byte[] key new byte[16];for (int i 0; i 16; i) {key[i] (byte) (29 i * 3);}try {byte[] encryp DatatypeConverter.parseBase64Binary(data);Cipher cipher Cipher.getInstance(AES/CBC/NoPadding);SecretKeySpec keySpec new SecretKeySpec(key, AES);IvParameterSpec ivSpec new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);byte[] original cipher.doFinal(encryp);//因为pc端使用加密的是zeroPadding 后补0的Nopadding方式 且 都是字符unsigned限制的 char正数 可以通过判断第一个0的位置判断字符长度int end0;while(end original.length original[end] ! 0){end;}return new String(original,0, end);} catch (Exception e) {e.printStackTrace();}return null;}//测试public static void main(String[] args) {String data 232342342342342;String iv 2334022720230227;String encrypt encrypt(data ,iv);String desencrypt desEncrypt(encrypt,iv);System.out.println(长加密后:encrypt);System.out.println(长解密后:desencrypt);}
}遇到的bug解决方法
bug1:在做AES解密的时候碰到了Given final block not properly padded. Such issues can arise if a bad key is used during decryption报错意思就是加密和加密所所对应的秘钥不同
bug2:在使用java的Cipher类进行AES加密时报错IllegalBlockSizeException: Input length not multiple of 16 bytes
报错的代码 Cipher cipher Cipher.getInstance(AES/CBC/NoPadding)
填充方式如果是Nopadding,那么加密的明文就得是8的倍数或者是密钥必须是16位的 待加密内容的长度必须是16的倍数如果不是16的倍数 总结Java虽然支持AES的CBC模式但是填充方式不支持ZeroPadding。
原理ZeroPadding就是用\0将加密内容填充至BlockSize(CBC一般是16)的整数倍再用NoPadding方式填充即可。