博客的文章详情页面传递参数是使用AES加密过得,如下图所示:
这个AES加密是通用的加密方式,使用同一套算法,前端和后端都可以对加密之后的字符串进行加密解密操作。
目前线上正在使用的是前端javascript进行加密操作,将加密之后的字符串再传递到后端,PHP再进行解密操作。
现在我们将后端换成了SpringBoot,就需要使用java来实现后端解密操作。
一:javascript使用AES加密解密
需要引入加密文件库
https://s3.pstatp.com/cdn/expire-1-M/crypto-js/3.1.9/crypto-js.min.js
加密解密方法如下所示:
/*** @name:crypto-js 加密* @author: camellia* @email: guanchao_gc@qq.com* @date: 2021-01-22*/
export function encryptCode(param)
{var text = JSON.stringify(param);var key = CryptoJS.enc.Latin1.parse(‘1234567890789456’); //为了避免补位,直接用16位的秘钥var iv = CryptoJS.enc.Latin1.parse(‘1234567890789456’); //16位初始向量var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding}).toString();return encrypted;
}
/*** @name:crypto-js 解密* @author: camellia* @email: guanchao_gc@qq.com* @date: 2021-01-22*/
export function decryptCode(param)
{var key = CryptoJS.enc.Latin1.parse(‘1234567890789456’); //为了避免补位,直接用16位的秘钥var iv = CryptoJS.enc.Latin1.parse(‘1234567890789456’); //16位初始向量const decrypt = CryptoJS.AES.decrypt(param, key, {iv: iv,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.ZeroPadding}).toString(CryptoJS.enc.Utf8);return decrypt;
}
通过观察上方代码,我们可以发现,我使用的是AES-128算法加密,加解密模式为CBC,ZeroPadding是填充方法。
我的key和iv都是标准的16位,理论上来说,这个填充模式直接选择NoPadding就可以了,因为我不需要补位。
二:java使用AES加密解密
protected String key = "1234567890789456";protected String iv = "1234567890789456";/*** @Description AES算法加密明文* @param data 明文* @param key 密钥,长度16* @param iv 偏移量,长度16* @return 密文*/public String encryptAES(String data,String key,String iv) throws Exception{try{// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");// Cipher cipher = Cipher.getInstance("AES/CBC/ZeroPadding"); java中没有实现这个方法// 声明加密算法 / 加密方式 / 填充方式Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");int blockSize = cipher.getBlockSize();byte[] dataBytes = data.getBytes();int plaintextLength = dataBytes.length;if (plaintextLength % blockSize != 0){plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));}byte[] plaintext = new byte[plaintextLength];System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); // CBC模式,需要一个向量iv,可增加加密算法的强度cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);byte[] encrypted = cipher.doFinal(plaintext);return encode(encrypted).trim(); // BASE64做转码。}catch (Exception e){e.printStackTrace();return null;}}/*** @Description AES算法解密密文* @param data 密文* @param key 密钥,长度16* @param iv 偏移量,长度16* @return 明文*/public String decryptAES(String data,String key,String iv) throws Exception{try{byte[] encrypted1 = decode(data);//先用base64解密Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);byte[] original = cipher.doFinal(encrypted1);String originalString = new String(original,"UTF-8");return originalString.trim();}catch (Exception e){e.printStackTrace();return null;}}/*** 编码* @param byteArray* @return*/public String encode(byte[] byteArray){return new String(new Base64().encode(byteArray));}/*** 解码* @param base64EncodedString* @return*/public byte[] decode(String base64EncodedString){return new Base64().decode(base64EncodedString);}
这里注意一下,我使用的是java11,他是没有实现ZeroPadding这个填充方式的,但是,由于我的key和iv都是16位,不需要补位,因此我这里直接使用NoPadding即可。如果我的上述条件您不满足,可能您就需要换一个填充方式了。
三:AES加密简单介绍
AES加密又分成AES-128、AES-196、AES-256,其中128、196、256是针对加解密密钥长度的要求,即128位(16字节),196位(24字节),256位(32字节);
关于加解密模式和填充方式
针对待加解密明文、密文,长度有严格要求,即必须为16字节的整数倍(所以针对不同长度的数据,需要对齐,不够16位的需要填充数据,由此产生了不同的填充方式)。整个加解密的过程是对所有分割成16个字节长度的数据块进行循环加解密,最后合并起来形成最终结果集(加解密过程的不同产生了不同的加解密模式)。
常见加密模式:
常见填充方式:
以上大概就是java中AES加密和解密的使用。
有好的建议,请在下方输入你的评论。