java前後端加密通信 / AES / DES等算法

1. 加密解密

1.1 前端js加密概述

對系統安全性要求比較高,那麼需要選擇https協議來傳輸數據。當然很多情況下一般的web網站,如果安全要求不是很高的話,用http協議就可以了。在這種情況下,密碼的明文傳輸顯然是不合適的,因爲如果請求在傳輸過程中被截了,就可以直接拿明文密碼登錄網站了。
HTTPS(443)在HTTP(80)的基礎上加入了SSL(Secure Sockets Layer 安全套接層)協議,SSL依靠證書來驗證服務器的身份,併爲瀏覽器和服務器之間的通信加密。傳輸前用公鑰加密,服務器端用私鑰解密。

常用的對稱加密算法有DES、3DES(TripleDES)、AES、RC2、RC4、RC5和Blowfis。可以參考:常用加密算法的Java實現總結
這裏採用js端與java端互通的AES加密算法。

1.2 前後端加密解密

爲了保證通信過程中的保密性能,我們使用如下來進行前段加密後端解密。

1.2.1 引用的js加密庫

Cryptojs下載: 點擊下載
【如果沒有積分的可以下面留下郵箱,我發送到郵箱】
在頁面中引入如下文件:

<script src=".../jquery-2.2.4.min.js"></script>
<script src=".../aes.js"></script>
<script src=".../mode-ecb-min.js"></script>

1.2.2 js加密解密

var data = "my name is xx";
var srcs  = CryptoJS.enc.Utf8.parse(data);
var key  = CryptoJS.enc.Utf8.parse('o7H8uIM2O5qv65l2');//Latin1 w8m31+Yy/Nw6thPsMpO5fg==
function Encrypt(word){  
    var srcs = CryptoJS.enc.Utf8.parse(word);  
    var encrypted = CryptoJS.AES.encrypt(srcs, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});  
    return encrypted.toString();  
}  
function Decrypt(word){  
    var decrypt = CryptoJS.AES.decrypt(word, key, {mode:CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});  
    return CryptoJS.enc.Utf8.stringify(decrypt).toString();  
}

1.2.3 Java端加密解密(PKCS5Padding與js的Pkcs7一致)

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

import sun.misc.BASE64Decoder;

public class EncryptUtil {
    private static final String KEY = "abcdefgabcdefg12";  
    private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";  
    public static String base64Encode(byte[] bytes){  
        return Base64.encodeBase64String(bytes);  
    }  
    public static byte[] base64Decode(String base64Code) throws Exception{  
        return new BASE64Decoder().decodeBuffer(base64Code);  
    }  
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {  
        KeyGenerator kgen = KeyGenerator.getInstance("AES");  
        kgen.init(128);  
        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);  
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));  

        return cipher.doFinal(content.getBytes("utf-8"));  
    }  
    public static String aesEncrypt(String content, String encryptKey) throws Exception {  
        return base64Encode(aesEncryptToBytes(content, encryptKey));  
    }  
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {  
        KeyGenerator kgen = KeyGenerator.getInstance("AES");  
        kgen.init(128);  

        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);  
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));  
        byte[] decryptBytes = cipher.doFinal(encryptBytes);  

        return new String(decryptBytes);  
    }  
    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {  
        return aesDecryptByBytes(base64Decode(encryptStr), decryptKey);  
    }  
    
    public static void main(String[] args) throws Exception {
        String content = "my name is";  
        System.out.println("加密前:" + content);  
        System.out.println("加密密鑰和解密密鑰:" + KEY);  
        String encrypt = aesEncrypt(content, KEY);  
        System.out.println(encrypt.length()+":加密後:" + encrypt);  
        String decrypt = aesDecrypt(encrypt, KEY);  
        System.out.println("解密後:" + decrypt);  
    }
}

1.2.4 後端解密前端使用如下方法

當我們直接在後端解密上述前端拿過來的密文時,發現密文是一個16進制的數,及經過base64的。 所以上述方法就行不通,就需要做一個轉換,使用如下解密方法:

//解密函數
public static String Decrypt(String src) throws Exception {
		String key = KEY; // 與js的密鑰保持一致
		try {
			byte[] data = key.getBytes("utf-8");
			byte[] raw = new byte[16];
			byte[] plusbyte = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
					0x0e, 0x0f };
			for (int i = 0; i < 16; i++) {
				if (data.length > i)
					raw[i] = data[i];
				else
					raw[i] = plusbyte[0];
			}
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
			cipher.init(Cipher.DECRYPT_MODE, skeySpec);

			// byte[] encrypted1 = new Base64().decode(src);//base64
			byte[] encrypted1 = toByteArray(src);// 十六進制

			try {
				byte[] original = cipher.doFinal(encrypted1);
				String originalString = new String(original, "utf-8");
				return originalString;
			} catch (Exception e) {
				System.out.println(e.toString());
				return null;
			}
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}
    
    public static byte[] toByteArray(String hexString) {
		if (hexString.isEmpty())
			throw new IllegalArgumentException("this hexString must not be empty");
	
		hexString = hexString.toLowerCase();
		final byte[] byteArray = new byte[hexString.length() / 2];
		int k = 0;
		for (int i = 0; i < byteArray.length; i++) {// 因爲是16進制,最多隻會佔用4位,轉換成字節需要兩個16進制的字符,高位在先
			byte high = (byte) (Character.digit(hexString.charAt(k), 16) & 0xff);
			byte low = (byte) (Character.digit(hexString.charAt(k + 1), 16) & 0xff);
			byteArray[i] = (byte) (high << 4 | low);
			k += 2;
		}
		return byteArray;
	}

2. 隨機數生成器

import java.util.Random;  
public class RandomUtil {  
    public static final String ALLCHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";  
    public static final String LETTERCHAR = "abcdefghijkllmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";  
    public static final String NUMBERCHAR = "0123456789";  

    /** 
     * 返回一個定長的隨機字符串(只包含大小寫字母、數字) 
     * @param length    隨機字符串長度 
     * @return 隨機字符串 
     */  
    public static String generateString(int length) {  
        StringBuffer sb = new StringBuffer();  
        Random random = new Random();  
        for (int i = 0; i < length; i++) {  
            sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));  
        }  
        return sb.toString();  
    }  

    /** 
     * 返回一個定長的隨機純字母字符串(只包含大小寫字母) 
     * @param length   隨機字符串長度 
     * @return 隨機字符串 
     */  
    public static String generateMixString(int length) {  
        StringBuffer sb = new StringBuffer();  
        Random random = new Random();  
        for (int i = 0; i < length; i++) {  
            sb.append(LETTERCHAR.charAt(random.nextInt(LETTERCHAR.length())));  
        }  
        return sb.toString();  
    }  

    /** 
     * 返回一個定長的隨機純大寫字母字符串(只包含大小寫字母) 
     *  
     * @param length 
     *            隨機字符串長度 
     * @return 隨機字符串 
     */  
    public static String generateLowerString(int length) {  
        return generateMixString(length).toLowerCase();  
    }  

    /** 
     * 返回一個定長的隨機純小寫字母字符串(只包含大小寫字母) 
     *  
     * @param length 
     *            隨機字符串長度 
     * @return 隨機字符串 
     */  
    public static String generateUpperString(int length) {  
        return generateMixString(length).toUpperCase();  
    }  

    /** 
     * 生成一個定長的純0字符串 
     *  
     * @param length 
     *            字符串長度 
     * @return 純0字符串 
     */  
    public static String generateZeroString(int length) {  
        StringBuffer sb = new StringBuffer();  
        for (int i = 0; i < length; i++) {  
            sb.append('0');  
        }  
        return sb.toString();  
    }  

    /** 
     * 根據數字生成一個定長的字符串,長度不夠前面補0 
     *  
     * @param num 
     *            數字 
     * @param fixdlenth 
     *            字符串長度 
     * @return 定長的字符串 
     */  
    public static String toFixdLengthString(long num, int fixdlenth) {  
        StringBuffer sb = new StringBuffer();  
        String strNum = String.valueOf(num);  
        if (fixdlenth - strNum.length() >= 0) {  
            sb.append(generateZeroString(fixdlenth - strNum.length()));  
        } else {  
            throw new RuntimeException("將數字" + num + "轉化爲長度爲" + fixdlenth  
                    + "的字符串發生異常!");  
        }  
        sb.append(strNum);  
        return sb.toString();  
    }  

    /** 
     * 每次生成的len位數都不相同 
     *  
     * @param param 
     * @return 定長的數字 
     */  
    public static int getNotSimple(int[] param, int len) {  
        Random rand = new Random();  
        for (int i = param.length; i > 1; i--) {  
            int index = rand.nextInt(i);  
            int tmp = param[index];  
            param[index] = param[i - 1];  
            param[i - 1] = tmp;  
        }  
        int result = 0;  
        for (int i = 0; i < len; i++) {  
            result = result * 10 + param[i];  
        }  
        return result;  
    }  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章