AES前后端对称加密

概述

高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法,对称加密算法即加密和解密的过程使用同一个秘钥进行加密。本文从实用的角度去描述前后端使用AES对称加密。

需求分析

前端请求数据传递参数时,需要对其进行加密,而不是使用明文进行传输,防止http请求被人截获而获取到信息,AES对称加密就是一种方式,前端对密码进行加密,传输给后端,后端获取之后使用和前端约定好的秘钥进行解密。

前端AES加解密

前端加密需要引入crypto-js的js文件,crypto-js是加密标准的JavaScript库,实现了各种加密算法,下载地址:https://www.yuque.com/docs/share/a764ecd9-3f47-4d40-8ec6-b80aca710d38?# 《前后端加密crypto-js.js文件》

实操,demo如下

前端AES加解密代码:

// 密钥 var key = '38373134313330303030333134313738';  key = CryptoJS.enc.Hex.parse(key)  var iv = CryptoJS.enc.Hex.parse("303132333435233454243444546")   var src = mobile_phone;  console.log('原字符串:', src);                     var enc = CryptoJS.AES.encrypt(src ,key,{                         iv:iv,                         mode: CryptoJS.mode.CBC,                         padding: CryptoJS.pad.Pkcs7                     })                      console.log('加密:',enc.toString());                     var enced = enc.ciphertext.toString()                      console.log("加密:", enced);                      var dec = CryptoJS.AES.decrypt(CryptoJS.format.Hex.parse(enced), key,{                         iv:iv,                         mode: CryptoJS.mode.CBC,                         padding: CryptoJS.pad.Pkcs7                     })                     console.log('解密:',CryptoJS.enc.Utf8.stringify(dec));                    

其中key和iv的值并不是随意填写的,这个是需要后端加解密生成后给到前端使用

后端AES加解密:

package unis.cloud.data.tool;  import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException;  import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec;  public class AesTool {  	 	private static String iv = "0123456789ABCDEF";//偏移量字符串必须是16位 当模式是CBC的时候必须设置偏移量 	    private static String Algorithm = "AES"; 	    private static String AlgorithmProvider = "AES/CBC/PKCS5Padding"; //算法/模式/补码方式  	    public static byte[] generatorKey() throws NoSuchAlgorithmException { 	        KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm); 	        keyGenerator.init(256);//默认128,获得无政策权限后可为192或256 	        SecretKey secretKey = keyGenerator.generateKey(); 	        return secretKey.getEncoded(); 	    }  	    public static IvParameterSpec getIv() throws UnsupportedEncodingException { 	        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8")); 	        System.out.println("偏移量:"+byteToHexString(ivParameterSpec.getIV())); 	        return ivParameterSpec; 	    }  	    public static byte[] encrypt(String src) throws NoSuchAlgorithmException, NoSuchPaddingException, 	            InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException { 	    	byte key[] = "87000078".getBytes("utf-8"); 	    	SecretKey secretKey = new SecretKeySpec(key, Algorithm); 	        IvParameterSpec ivParameterSpec = getIv(); 	        Cipher cipher = Cipher.getInstance(AlgorithmProvider); 	        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec); 	        byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8"))); 	        return cipherBytes; 	    }  	    public static byte[] decrypt(String src) throws Exception { 	    	byte key[] = "87000078".getBytes("utf-8"); 	    	SecretKey secretKey = new SecretKeySpec(key, Algorithm);  	        IvParameterSpec ivParameterSpec = getIv(); 	        Cipher cipher = Cipher.getInstance(AlgorithmProvider); 	        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec); 	        byte[] hexBytes = hexStringToBytes(src); 	        byte[] plainBytes = cipher.doFinal(hexBytes); 	        return plainBytes; 	    }  	    /** 	     * 将byte转换为16进制字符串 	     * @param src 	     * @return 	     */ 	    public static String byteToHexString(byte[] src) { 	        StringBuilder sb = new StringBuilder(); 	        for (int i = 0; i < src.length; i++) { 	            int v = src[i] & 0xff; 	            String hv = Integer.toHexString(v); 	            if (hv.length() < 2) { 	                sb.append("0"); 	            } 	            sb.append(hv); 	        } 	        return sb.toString(); 	    }  	    /** 	     * 将16进制字符串装换为byte数组 	     * @param hexString 	     * @return 	     */ 	    public static byte[] hexStringToBytes(String hexString) { 	        hexString = hexString.toUpperCase(); 	        int length = hexString.length() / 2; 	        char[] hexChars = hexString.toCharArray(); 	        byte[] b = new byte[length]; 	        for (int i = 0; i < length; i++) { 	            int pos = i * 2; 	            b[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); 	        } 	        return b; 	    }  	    private static byte charToByte(char c) { 	        return (byte) "0123456789ABCDEF".indexOf(c); 	    }  	    public static void main(String[] args) { 	        try { 	            // 密钥必须是16的倍数 	            byte key[] = "8711110000222278".getBytes("utf-8"); 	            String src = "183222222222"; 	            System.out.println("密钥:"+byteToHexString(key)); 	            System.out.println("原字符串:"+src);  	            String enc = byteToHexString(encrypt(src)); 	            System.out.println("加密:"+enc); 	            System.out.println("解密:"+new String(decrypt(enc), "utf-8")); 	        } catch (InvalidKeyException e) { 	            e.printStackTrace(); 	        } catch (NoSuchAlgorithmException e) { 	            e.printStackTrace(); 	        } catch (NoSuchPaddingException e) { 	            e.printStackTrace(); 	        } catch (IllegalBlockSizeException e) { 	            e.printStackTrace(); 	        } catch (BadPaddingException e) { 	            e.printStackTrace(); 	        } catch (UnsupportedEncodingException e) { 	            e.printStackTrace(); 	        } catch (Exception e) { 	            e.printStackTrace(); 	        } 	    } 	 } 

后端输出结果:

密钥:38373134313330303030333134313738 原字符串:你好 偏移量:30313233343536373839414243444546 加密:08e56adf28a16558631aa0914d04bd0c 偏移量:30313233343536373839414243444546 解密:你好


AES前后端对称加密

需要注意,后端输出的密钥和偏移量都要给前端,这样解析出来的参数才是一致的,其中后端打印出的密钥对应前端的key,后端打印出的便宜量对应前端的iv中的值!

表达可能不太清楚,调试中有问题可私信我!

您可能还会对下面的文章感兴趣: