1.什么是AES?高级加密标准(英文:AdvancedEncryptionStandard,缩写:AES),是一种块加密标准。该标准用于替代原来的DES,经过多方分析,在世界范围内得到广泛应用。那么为什么原来的DES会被替换掉呢,原因就是它使用了56位的密钥,比较容易被破解。但是AES可以使用128位、192位和256位的密钥,使用128位的块对数据进行加解密,相对安全。一个完美的加密算法在理论上是牢不可破的,除非使用穷举法。用穷举法破解密钥长度超过128位的加密数据是不现实的,只有理论上的可能。统计表明,即使使用世界上最快的计算机,也需要数十亿年才能耗尽128位密钥,更不用说破解256位密钥长度的AES算法了。目前,世界上仍有机构在研究如何破解AES的厚墙,但由于破解时间太长,AES是有保障的,只是耗时在不断缩减。随着计算机运算速度的提高和新算法的出现,对AES的攻击只会越来越猛烈,不会停止。AES现在广泛应用于金融、在线交易、无线通信、数字存储等领域,经受了最严苛的考验,但也许有一天它会步DES的后尘。2、AES加密方法简析AES加密是对称加密128、192、256分别代表密钥的长度。AES加密方式会将明文拆分成不同的块进行加密。例如,256位数据使用128位密钥加密。分为明文1(128位)、明文2(128位)、加密密文1(128位)、密文2(128位)padding: 如果明文不是128位(16字节),padding是必需的,即在明文某处补充长度为16字节的整数倍。加密和解密时需要使用相同的填充方式,否则无法解密成功。以下是几种填充方式**NoPadding不进行填充,但是这里的明文必须是16字节的整数倍,这个可以由用户自己填充。除此模式外的其他填充模式,如果已经有16个字节的数据,则再填充16个字节的数据**PKCS5Padding(默认)在明文末尾进行填充,填充数据为当前与明文的差值16字节,例如:unfilledplaintext1,2,3,4,5,6,7,8,9,10,11Paddingplaintext(缺5个满足16字节)1,2,3,4,5,6,7,8,9,10,11,5,5,5,5,5 由于使用了PKCS7Padding/PKCS5Paddingpadding,所以最后一个字节必须是paddingdata的长度,所以paddingdata可以解密后准确删除**ISO10126Padding是在明文末尾填充,当前和16字节的差值在末尾补上,其余字节补随机数,例如:Unfilledplaintext1,2,3,4,5,6,7,8,9,10,11填充明文(缺5个满足16个字节)1,2,3,4,5,6,7,8,9,10,11,c,b、4、1、5模式 模式是需要AES加密明文时使用的模式t(这里不涉及具体的加密方法,只是加密步骤中的一种不同模式。加密和解密也需要相同的模式,否则无法成功),一共提供了五种模式。这些模式的基本原理是近似的,但在细节上会有一些变化,如下:**ECB模式(默认)ElectronicCodebookBook模式是默认模式。它只是根据密钥位数将数据分成不同的块进行加密。加密完成后,将加密后的数据拼接在一起。过程如下:Plaintext(64bytes)Key(16bytes)Plaintext1(16bytes)Plaintext2(16bytes)Plaintext3(16bytes)Plaintext4(16bytes)Ciphertext1(16bytes)Festival)密文2(16字节)密文3(16字节)密文4(16字节)密文(64字节)优点:简单、快速、并行缺点:如果明文块相同,生成的密文块也相同,这将导致安全性下降**CBC模式密码块链接模式CipherBlockChaining为了解决ECB模式中密文块同样的缺点,CBC模式引入了一个初始向量的概念,它必须是一个对于等于密钥长度的数据,在第一次加密之前,会使用初始化向量与第一块数据进行异或运算,生成的新数据会被再次加密。在加密第二个块之前,将对第一个块进行加密。将文本数据与第二明文进行异或运算,然后加密,依此类推。解密时,解密后还要进行异或运算,最终明文生成过程如下:Plaintext(63bytes)Key(16charactersSection)Initialvectoriv(16bytes)Plaintext1(16bytes)Plaintext2(16bytes)Plaintext3(16bytes)Plaintext4+a0(16bytes)XOR+initialvector+ciphertext1+Ciphertext2+Ciphertext3Ciphertext1(16bytes)Ciphertext2(16bytes)Ciphertext3(16bytes)Ciphertext4(16bytes)Ciphertext(64bytes)这里要注意以下几点:1.vector必须是一个等于key长度的数据2.由于加密前和解密后都会进行XOR运算,所以我们的明文不需要待补全,且不是16字节的倍数,CBC会自动完成与0的异或运算。3.解密时,解密后会进行异或运算,确保数据解密成功。4.由于是自动补全,解密后的数据也会在后面填0,所以在获取数据的时候需要去掉末尾的0,或者根据长度截取解密后的数据源数据。优点:每个加密密钥都不同,加强了安全性。CBC方法解决了EBC的缺点,但也有其缺点:1.加密不能并行操作,但解密可以并行进行。前一个block加密后,下一个block必须加密,后面也需要补0,所以不适合做流式数据(不适合的原因)可能是128位的数据需要加密后才能加密,这样后面就没有0的补全了)2、如果前面的数据加密错了,那么后面的数据也会出错。3.两端需要同时约定初始向量iv**CFB模式:密码反馈模式CipherFeedBack这种模式只使用加密的方式,原理是先使用一次数值异或运算再进行一次异或运算,并且该值不会改变。而在加密的时候,如果数据不满足key的字节数,那么就只保存,满足key的字节数后再进行加密过程:加密:plaintext(260bytes)iv(128bytes)plaintext1(128字节)明文2(128字节)明文3(4字节)(iv+key)XOR明文1(密文1+key)XOR明文1(加密Text1+key)XOR明文3密文1(128字节)密文2(128字节)密文3(4字节)解密:密文(260字节)iv(128字节)密钥(128字节)密文1(128字节)密文2(128字节)密文3(4字节)(iv+key)异或密文1(密文1+key)异或密文2(密文1+key)异或密文3明文1(128字节)明文2(128字节)明文3(4字节)这里需要注意以下几点Points:1.加解密的时候,会返回一个num。这个num表示需要多少个数字才使用之前的密文进行加密,否则一直使用之前的密文。2.加解密的时候还需要传入字符串的长度3.因为解密是用密文而不是上次解密的明文,所以解密也可以并行进行。基于第三点,适用于流式数据传输。5、CFB模式不仅有CFB128(即与密钥长度相同),还有CFB1和CFB8,即加解密1位或8位后,再次调用加密器生成新值,即可以使加密更加安全,但是会处理更多的计算,CFB1的计算时间是CFB8的8倍,是CFB128的128倍。6、使用CFB128或CFB8时,传入的长度单位为byte,CFB1为长度单位为bit。7、使用CFB1和CFB8时,num值会一直为0。优点:可以同步解密,可以传入不是16字节倍数的数据。适用于流数据CFB模式。当然,也有缺点。解密的时候可以并行解密,但是加密的时候不能并行加密。并且还需要选择iv**OFB模式:OutputFeedbackModeOutputFeedBack这个模式和CFB类似,但是它加密的是iv或者前面iv加密的数据,生成的密钥和明文异或,解密方法是同样的方法利用异或运算的对称性进行加密和解密。除了这一点,其余按照CFB加密/解密:CFB:(iv+key)XORplaintext1(ciphertext1+key)XORplaintext1(ciphertext1+key)XORplaintext3OFB(iv+key)XORplaintext1((iv+key)+key)XORplaintext1(((iv+key)+key)+key)XORplaintext3优点:和CFB一样,方便传输流式数据。缺点:因为依赖上次的加密结果,所以不能并行处理。特点是解密步骤完全一样,所以使用上不会有区别。**CTR模式:CounterOFB在计算器模式下不能并行化的原因是需要最后一个iv加密后的结果,所以在CTR中我们将(iv+key)+key替换为(iv+1)+key,这样我们就不需要依赖上次的加密结果了。比较如下:OFB(iv+key)XORplaintext1((iv+key)+key)XORplaintext1((iv+key)+key)+key)XORplaintext3CTR(iv+key)XORPlaintext1((iv+1)+key)XORplaintext1(((iv+1)+1)+key)XORplaintext3优点:由于可以并行加解密,所以CTR方式的加解密速度也很快缺点:iv+1的获取比较负责,需要获取瞬时iv。3.提供两个例子1.javamysql通用AES加密算法通用AES加密,使用场景,插入数据时,使用java加密数据,查询时,通过sql进行解密,不需要取出来再遍历解密注意:to_base64只适用于mysql5.6及以后版本,之前的没有这个功能,不适用,可以用HEX,UNHEX,当然java必须用对应的方法解密importjavax.crypto.Cipher;importjavax.crypto.spec.SecretKeySpec;importsun.misc.BASE64Decoder;importsun.misc.BASE64Encoder;/**java使用AES加解密AES-128-ECB加密和mysql数据库aes加密算法通用数据库aes加解密--加密SELECTto_base64(AES_ENCRYPT('www.gowhere.so','jkl;POIU1234++=='));--解密SELECTAES_DECRYPT(from_base64('Oa1NPBSarXrPH8wqSRhh3g=='),'jkl;POIU1234++==');@author836508**/publicclassMyAESUtil{//加密publicstaticStringEncrypt(StringsSrc,StringsKey)throwsException{if(sKey==null){System.out.print("Keyisemptynull");返回空值;}//判断Key是否为16位if(sKey.length()!=16){System.out.print("Keylength}byte[]raw=sKey.getBytes("utf-8");SecretKeySpecskeySpec=newSecretKeySpec(raw,"AES");Ciphercipher=Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码"cipher.init(Cipher.ENCRYPT_MODE,skeySpec);byte[]encrypted=cipher.doFinal(sSrc.getBytes("utf-8"));returnnewBASE64Encoder().encode(encrypted);//这里使用BASE64进行转码功能,可以同时起到两种加密的作用}//DecryptpublicstaticStringDecrypt(StringsSrc,StringsKey)throwsException{try{//判断Key是否正确if(sKey==null){System.out.print("Keyisnull");返回空值;}//判断Key是否为16位if(sKey.length()!=16){System.out.print("Keylengthisnot16-bit");返回空值;}byte[]raw=sKey.getBytes("utf-8");SecretKeySpecskeySpec=newSecretKeySpec(raw,"AES");密码cipher=Cipher.getInstance("AES/ECB/PKCS5Padding");cipher.init(Cipher.DECRYPT_MODE,skeySpec);byte[]encrypted1=newBASE64Decoder().decodeBuffer(sSrc);//先用base64解密try{byte[]original=cipher.doFinal(encrypted1);StringoriginalString=newString(original,"utf-8");返回原始字符串;}catch(Exceptione){System.out.println(e.toString());返回空值;}}赶上(异常前){System.out.println(ex.toString());返回空值;}}publicstaticvoidmain(String[]args)throwsException{/**这里使用AES-128-ECB加密方式,密钥需要16位*/StringcKey="jkl;POIU1234++==";//待加密的字符串StringcSrc="www.gowhere.so";System.out.println(cSrc);//加密字符串enString=MyAESUtil.Encrypt(cSrc,cKey);System.out.println("加密后的字符串为:"+enString);//解密字符串DeString=MyAESUtil.Decrypt(enString,cKey);System.out.println("解密后的字符串Thestringis:"+DeString);}}2、javaAES-128-CBC加密方式包com.zhongzhi.utils;importjavax.crypto.Cipher;importjavax.crypto.spec.IvParameterSpec;导入javax.crypto.spec。SecretKeySpec;importorg.apache.commons.codec.binary.Base64;/**@ClassnameZzSecurityHelper@DescriptionTODO@Date2019/6/2416:50@whd创建*/publicclassZzSecurityHelper{/**用于加密密钥可以由26个字母和数字组成,采用AES-128-CBC加密方式,密钥需要为16位。*/privatestaticfinalStringkey="hj7x89H$yuBI0456";privatestaticfinalStringiv="NIfb&95GUY86Gfgh";/***@authormiracle.qu*@DescriptionAES算法加密明文*@paramdataplaintext*@paramkeysecretkey,length16*@paramivoffset,length16*@returnciphertext*/publicstaticStringencryptAES(Stringdata)throwsException{try{Ciphercipher=Cipher.getInstance("AES/CBC/NoPadding");}intblockSize=cipher.getBlockSize();byte[]dataBytes=data.getBytes();intplaintextLength=dataBytes.length;if(plaintextLength%blockSize!=0){plaintextLength=plaintextLength+(blockSize-(plaintextLength%blockSize));}byte[]plaintext=newbyte[plaintextLength];System.arraycopy(dataBytes,0,plaintext,0,dataBytes.length);SecretKeySpeckeyspec=newSecretKeySpec(key.getBytes(),"AES");IvParameterSpecivspec=newIvParameterSpec(iv.getBytes());//CBC模式需要一个向量iv,可以增加加密算法ciph的强度er.init(Cipher.ENCRYPT_MODE,keyspec,ivspec);byte[]encrypted=cipher.doFinal(明文);返回ZzSecurityHelper.encode(encrypted).trim();//BASE64做转码}catch(Exceptione){e.printStackTrace();返回空值;}}/***@authormiracle.qu*@DescriptionAES算法解密密文*@paramdataciphertext*@paramkey密钥,长度16*@paramivoffset,长度16*@returnplaintext*/publicstaticStringdecryptAES(Stringdata)throwsException{try{byte[]encrypted1=ZzSecurityHelper.decode(data);//用base64解密密码firstcipher=Cipher.getInstance("AES/CBC/NoPadding");SecretKeySpeckeyspec=newSecretKeySpec(key.getBytes(),"AES");IvParameterSpecivspec=newIvParameterSpec(iv.getBytes());cipher.init(Cipher.DECRYPT_MODE,keyspec,ivspec);byte[]original=cipher.doFinal(encrypted1);StringoriginalString=newString(原始);返回originalString.trim();}catch(Exceptione){e.printStackTrace();返回空值;}}/***编码*@parambyteArray*@return*/publicstaticStringencode(byte[]byteArray){returnnewString(newBase64().encode(byteArray));}/***密码*@parambase64EncodedString*@return*/publicstaticbyte[]decode(Stringbase64EncodedString){returnnewBase64().decode(base64EncodedString);}}
