首頁>技術>

概述

高階加密標準(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解密:你好

需要注意,後端輸出的金鑰和偏移量都要給前端,這樣解析出來的引數才是一致的,其中後端打印出的金鑰對應前端的key,後端打印出的便宜量對應前端的iv中的值!

22
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 超級好用的mybatis程式碼生成器