256位密鑰帶偏移量的AES加密方案

你知道的越多,你不知道的越多
點贊再看,養成習慣
如果您有疑問或者見解,歡迎指教:
企鵝:869192208

前言

前段時間做了個與外部接口的數據對接,基於數據傳輸安全等因素的考量,需要對接口傳輸的參數進行AES加密方案,以下是對方公司提供的對接文檔的數據加密要求:

加密說明:
數據傳輸和返回的結果都用AES加密處理
AESKey:125858a550c605c199c19d778b81327b
AESIV:0392039203920300 示例:{“typeAction”:0}
加密後的字符串爲:9KdUttr+dfXTvUTSPAmxVA3l+5kR2+zPkc2N2PJiic8=

在線AES加解密測試地址:http://tool.chacuo.net/cryptaes
AES加密示例

以上所有入參都進過加密處理 示例:

{“jsonParam”:“Mxqe9kbyWyvR64n/kiEQK7M1kGMqCZ3KgFg8Z5EVI/XajilAz16Ed7sK156EShTqwOrmZb7QdOWF/kbj2KJa/jmO+ylIe+9vdrqRRFxddY4=”}

返回參數示例:

{“errcode”:0,“data”:“lKGC/SI9dsTWZ6vc8Wtvvm0w9NZxR3XyhnlVeWq+cQkK+yce7uWr61KvZ5Eomgue44omSx2fhHef\r\nqFwWrpnM9+YLLPn5z/ODbDkshZg6/yMlTtC1PnvfNPfqN/tDscBE\r\n”,“errmsg”:""}


因爲某些國家的進口管制限制,Java發佈的運行環境包中的加解密有一定的限制。比如默認不允許256位密鑰的AES加解密,解決方法就是修改策略文件。
替換的文件:%JDK_HOME%\jre\lib\security\local_policy.jar

官方網站提供了JCE無限制權限策略文件的下載:

  • JDK6的下載地址:

http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html

  • JDK7的下載地址:

http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

  • JDK8的下載地址:

http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

下載後解壓,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
如果安裝了JRE,將兩個jar文件放到%JRE_HOME%\lib\security下覆蓋原來文件,記得先備份。
如果安裝了JDK,將兩個jar文件放到%JDK_HOME%\jre\lib\security下。

jce_policy資源合輯地址:https://download.csdn.net/download/CDWLX/12231194

下面是經過測試的完整代碼:
  • 方案一
package common;  
      
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
    


import org.apache.commons.codec.binary.Base64;
      
    /** 
     * AES工具類 
     *  
     * <pre> 
     *   因爲某些國家的進口管制限制,Java發佈的運行環境包中的加解密有一定的限制。比如默認不允許256位密鑰的AES加解密,解決方法就是修改策略文件。 
     *   替換的文件:%JDK_HOME%\jre\lib\security\local_policy.jar 
     *   參考: http://czj4451.iteye.com/blog/1986483 
     */  
    public class AESTest {  
        // 密鑰  
        public static String AESKey = "125858a550c605c199c19d778b81327b";  
        public static String AESIV = "0392039203920300";
        private static String charset = "utf-8";  
        // 偏移量  
        private static int offset = 16;  
        private static String transformation = "AES/CBC/PKCS5Padding";  
        private static String algorithm = "AES";  
      
        /** 
         * 加密 
         *  
         * @param content 
         * @return 
         */  
        public static String encrypt(String content) {  
            return encrypt(content, AESKey);  
        }  
      
        /** 
         * 解密 
         *  
         * @param content 
         * @return 
         */  
        public static String decrypt(String content) {  
            return decrypt(content, AESKey);  
        }  
      
        /** 
         * 加密 
         *  
         * @param content 
         *            需要加密的內容 
         * @param AESKey 
         *            加密密碼 
         * @return 
         */  
        public static String encrypt(String content, String AESKey) {  
            try {  
                SecretKeySpec skey = new SecretKeySpec(AESKey.getBytes(), algorithm);  
                IvParameterSpec iv = new IvParameterSpec(AESIV.getBytes(), 0, offset);  
                Cipher cipher = Cipher.getInstance(transformation);  
                byte[] byteContent = content.getBytes(charset);  
                cipher.init(Cipher.ENCRYPT_MODE, skey, iv);// 初始化  
                byte[] result = cipher.doFinal(byteContent);  
                return new Base64().encodeToString(result); // 加密  
            } catch (Exception e) {  
                System.out.println(e);
            }  
            return null;  
        }  
      
        /** 
         * AES(256)解密 
         *  
         * @param content 
         *            待解密內容 
         * @param AESKey 
         *            解密密鑰 
         * @return 解密之後 
         * @throws Exception 
         */  
        public static String decrypt(String content, String AESKey) {  
            try {  
      
                SecretKeySpec skey = new SecretKeySpec(AESKey.getBytes(), algorithm);  
                IvParameterSpec iv = new IvParameterSpec(AESIV.getBytes(), 0, offset);  
                Cipher cipher = Cipher.getInstance(transformation);  
                cipher.init(Cipher.DECRYPT_MODE, skey, iv);// 初始化  
                byte[] result = cipher.doFinal(new Base64().decode(content));  
                return new String(result); // 解密  
            } catch (Exception e) {  
                System.out.println(e);
            }  
            return null;  
        }  
      
        public static void main(String[] args) throws Exception {  
            String s = "{\"code\":\"YWBD_GLLR\",\"params\":[{\"name\":\"ID\",\"value\":\"01265a3dc493462e9cdd4a26c41f19de\"}]}";
            // 加密  
            System.out.println("加密前:" + s);  
            String encryptResultStr = encrypt(s);  
            System.out.println("加密後:" + encryptResultStr);  
            // 解密  
            System.out.println("解密後:" + decrypt(encryptResultStr));  
        }  
    }  
運行結果:

運行結果

  • 方案二
    Encodes.java
/**
 * Copyright (c) 2005-2012 springside.org.cn
 */
package com.minstone.common.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;

/**
 * 封裝各種格式的編碼解碼工具類. 1.Commons-Codec的 hex/base64 編碼 2.自制的base62 編碼
 * 3.Commons-Lang的xml/html escape 4.JDK提供的URLEncoder
 * 
 * @author calvin
 * @version 2013-01-15
 */
public class Encodes {

	private static final String DEFAULT_URL_ENCODING = "UTF-8";
	private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
			.toCharArray();

	/**
	 * Hex編碼.
	 */
	public static String encodeHex(byte[] input) {
		return new String(Hex.encodeHex(input));
	}

	/**
	 * Hex解碼.
	 */
	public static byte[] decodeHex(String input) {
		try {
			return Hex.decodeHex(input.toCharArray());
		} catch (DecoderException e) {
			throw Exceptions.unchecked(e);
		}
	}

	public static byte[] stringToByte(String input) {
		return input.getBytes();
	}

	/**
	 * Base64編碼.
	 */
	public static String encodeBase64(byte[] input) {
		return new String(Base64.encodeBase64(input));
	}

	/**
	 * Base64編碼.
	 */
	public static String encodeBase64(String input) {
		try {
			return new String(Base64.encodeBase64(input
					.getBytes(DEFAULT_URL_ENCODING)));
		} catch (UnsupportedEncodingException e) {
			return "";
		}
	}

	// /**
	// * Base64編碼, URL安全(將Base64中的URL非法字符'+'和'/'轉爲'-'和'_', 見RFC3548).
	// */
	// public static String encodeUrlSafeBase64(byte[] input) {
	// return Base64.encodeBase64URLSafe(input);
	// }

	/**
	 * Base64解碼.
	 */
	public static byte[] decodeBase64(String input) {
		return Base64.decodeBase64(input.getBytes());
	}

	/**
	 * Base64解碼.
	 */
	public static String decodeBase64String(String input) {
		try {
			return new String(Base64.decodeBase64(input.getBytes()),
					DEFAULT_URL_ENCODING);
		} catch (UnsupportedEncodingException e) {
			return "";
		}
	}

	/**
	 * Base62編碼。
	 */
	public static String encodeBase62(byte[] input) {
		char[] chars = new char[input.length];
		for (int i = 0; i < input.length; i++) {
			chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
		}
		return new String(chars);
	}

	/**
	 * Html 轉碼.
	 */
	public static String escapeHtml(String html) {
		return StringEscapeUtils.escapeHtml4(html);
	}

	/**
	 * Html 解碼.
	 */
	public static String unescapeHtml(String htmlEscaped) {
		return StringEscapeUtils.unescapeHtml4(htmlEscaped);
	}

	/**
	 * Xml 轉碼.
	 */
	public static String escapeXml(String xml) {
		return StringEscapeUtils.escapeXml(xml);
	}

	/**
	 * Xml 解碼.
	 */
	public static String unescapeXml(String xmlEscaped) {
		return StringEscapeUtils.unescapeXml(xmlEscaped);
	}

	/**
	 * URL 編碼, Encode默認爲UTF-8.
	 */
	public static String urlEncode(String part) {
		try {
			return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
		} catch (UnsupportedEncodingException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * URL 解碼, Encode默認爲UTF-8.
	 */
	public static String urlDecode(String part) {

		try {
			return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
		} catch (UnsupportedEncodingException e) {
			throw Exceptions.unchecked(e);
		}
	}
}

Exceptions.java

/**
 * Copyright (c) 2005-2012 springside.org.cn
 */
package com.minstone.common.utils;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.http.HttpServletRequest;

/**
 * 關於異常的工具類.
 * @author calvin
 * @version 2013-01-15
 */
public class Exceptions {

	/**
	 * 將CheckedException轉換爲UncheckedException.
	 */
	public static RuntimeException unchecked(Exception e) {
		if (e instanceof RuntimeException) {
			return (RuntimeException) e;
		} else {
			return new RuntimeException(e);
		}
	}

	/**
	 * 將ErrorStack轉化爲String.
	 */
	public static String getStackTraceAsString(Throwable e) {
		if (e == null){
			return "";
		}
		StringWriter stringWriter = new StringWriter();
		e.printStackTrace(new PrintWriter(stringWriter));
		return stringWriter.toString();
	}

	/**
	 * 判斷異常是否由某些底層的異常引起.
	 */
	public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
		Throwable cause = ex.getCause();
		while (cause != null) {
			for (Class<? extends Exception> causeClass : causeExceptionClasses) {
				if (causeClass.isInstance(cause)) {
					return true;
				}
			}
			cause = cause.getCause();
		}
		return false;
	}

	/**
	 * 在request中獲取異常類
	 * @param request
	 * @return 
	 */
	public static Throwable getThrowable(HttpServletRequest request){
		Throwable ex = null;
		if (request.getAttribute("exception") != null) {
			ex = (Throwable) request.getAttribute("exception");
		} else if (request.getAttribute("javax.servlet.error.exception") != null) {
			ex = (Throwable) request.getAttribute("javax.servlet.error.exception");
		}
		return ex;
	}
	
}

Cryptos.java

package com.minstone.common.security;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.minstone.common.utils.Encodes;
import com.minstone.common.utils.Exceptions;

/**
 * 支持HMAC-SHA1消息簽名 及 DES/AES對稱加密的工具類.
 * 
 * 支持Hex與Base64兩種編碼方式.
 * 
 * @author calvin
 */
public class Cryptos {

	private static final String AES = "AES";
	private static final String AES_CBC = "AES/CBC/PKCS5Padding";
	private static final String HMACSHA1 = "HmacSHA1";

	private static final String DEFAULT_URL_ENCODING = "UTF-8";
	private static final int DEFAULT_HMACSHA1_KEYSIZE = 160; //RFC2401
	private static final int DEFAULT_AES_KEYSIZE = 128;
	private static final int DEFAULT_IVSIZE = 16;
	
	private static final byte[] DEFAULT_KEY = new byte[]{-97,88,-94,9,70,-76,126,25,0,3,-20,113,108,28,69,125}; 

	private static SecureRandom random = new SecureRandom();

	//-- HMAC-SHA1 funciton --//
	/**
	 * 使用HMAC-SHA1進行消息簽名, 返回字節數組,長度爲20字節.
	 * 
	 * @param input 原始輸入字符數組
	 * @param key HMAC-SHA1密鑰
	 */
	public static byte[] hmacSha1(byte[] input, byte[] key) {
		try {
			SecretKey secretKey = new SecretKeySpec(key, HMACSHA1);
			Mac mac = Mac.getInstance(HMACSHA1);
			mac.init(secretKey);
			return mac.doFinal(input);
		} catch (GeneralSecurityException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 校驗HMAC-SHA1簽名是否正確.
	 * 
	 * @param expected 已存在的簽名
	 * @param input 原始輸入字符串
	 * @param key 密鑰
	 */
	public static boolean isMacValid(byte[] expected, byte[] input, byte[] key) {
		byte[] actual = hmacSha1(input, key);
		return Arrays.equals(expected, actual);
	}

	/**
	 * 生成HMAC-SHA1密鑰,返回字節數組,長度爲160位(20字節).
	 * HMAC-SHA1算法對密鑰無特殊要求, RFC2401建議最少長度爲160位(20字節).
	 */
	public static byte[] generateHmacSha1Key() {
		try {
			KeyGenerator keyGenerator = KeyGenerator.getInstance(HMACSHA1);
			keyGenerator.init(DEFAULT_HMACSHA1_KEYSIZE);
			SecretKey secretKey = keyGenerator.generateKey();
			return secretKey.getEncoded();
		} catch (GeneralSecurityException e) {
			throw Exceptions.unchecked(e);
		}
	}

	//-- AES funciton --//

	/**
	 * 使用AES加密原始字符串.
	 * 
	 * @param input 原始輸入字符數組
	 */
	public static String aesEncrypt(String input) {
		try {
			return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), DEFAULT_KEY));
		} catch (UnsupportedEncodingException e) {
			return "";
		}
	}
	
	/**
	 * 使用AES加密原始字符串.
	 * 
	 * @param input 原始輸入字符數組
	 * @param key 符合AES要求的密鑰
	 */
	public static String aesEncrypt(String input, String key) {
		try {
			return Encodes.encodeHex(aesEncrypt(input.getBytes(DEFAULT_URL_ENCODING), Encodes.decodeHex(key)));
		} catch (UnsupportedEncodingException e) {
			return "";
		}
	}
	
	/**
	 * 使用AES加密原始字符串.
	 * 
	 * @param input 原始輸入字符數組
	 * @param key 符合AES要求的密鑰
	 */
	public static byte[] aesEncrypt(byte[] input, byte[] key) {
		return aes(input, key, Cipher.ENCRYPT_MODE);
	}

	/**
	 * 使用AES加密原始字符串.
	 * 
	 * @param input 原始輸入字符數組
	 * @param key 符合AES要求的密鑰
	 * @param iv 初始向量
	 */
	public static byte[] aesEncrypt(byte[] input, byte[] key, byte[] iv) {
		return aes(input, key, iv, Cipher.ENCRYPT_MODE);
	}

	/**
	 * 使用AES解密字符串, 返回原始字符串.
	 * 
	 * @param input Hex編碼的加密字符串
	 */
	public static String aesDecrypt(String input) {
		try {
			return new String(aesDecrypt(Encodes.decodeHex(input), DEFAULT_KEY), DEFAULT_URL_ENCODING);
		} catch (UnsupportedEncodingException e) {
			return "";
		}
	}
	
	/**
	 * 使用AES解密字符串, 返回原始字符串.
	 * 
	 * @param input Hex編碼的加密字符串
	 * @param key 符合AES要求的密鑰
	 */
	public static String aesDecrypt(String input, String key) {
		try {
			return new String(aesDecrypt(Encodes.decodeHex(input), Encodes.decodeHex(key)), DEFAULT_URL_ENCODING);
		} catch (UnsupportedEncodingException e) {
			return "";
		}
	}
	
	/**
	 * 使用AES解密字符串, 返回原始字符串.
	 * 
	 * @param input Hex編碼的加密字符串
	 * @param key 符合AES要求的密鑰
	 */
	public static byte[] aesDecrypt(byte[] input, byte[] key) {
		return aes(input, key, Cipher.DECRYPT_MODE);
	}

	/**
	 * 使用AES解密字符串, 返回原始字符串.
	 * 
	 * @param input Hex編碼的加密字符串
	 * @param key 符合AES要求的密鑰
	 * @param iv 初始向量
	 */
	public static byte[] aesDecrypt(byte[] input, byte[] key, byte[] iv) {
		return aes(input, key, iv, Cipher.DECRYPT_MODE);
	}

	/**
	 * 使用AES加密或解密無編碼的原始字節數組, 返回無編碼的字節數組結果.
	 * 
	 * @param input 原始字節數組
	 * @param key 符合AES要求的密鑰
	 * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
	 */
	private static byte[] aes(byte[] input, byte[] key, int mode) {
		try {
			SecretKey secretKey = new SecretKeySpec(key, AES);
			Cipher cipher = Cipher.getInstance(AES);
			cipher.init(mode, secretKey);
			return cipher.doFinal(input);
		} catch (GeneralSecurityException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 使用AES加密或解密無編碼的原始字節數組, 返回無編碼的字節數組結果.
	 * 
	 * @param input 原始字節數組
	 * @param key 符合AES要求的密鑰
	 * @param iv 初始向量
	 * @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE
	 */
	private static byte[] aes(byte[] input, byte[] key, byte[] iv, int mode) {
		try {
			SecretKey secretKey = new SecretKeySpec(key, AES);
			IvParameterSpec ivSpec = new IvParameterSpec(iv);
			Cipher cipher = Cipher.getInstance(AES_CBC);
			cipher.init(mode, secretKey, ivSpec);
			return cipher.doFinal(input);
		} catch (GeneralSecurityException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 生成AES密鑰,返回字節數組, 默認長度爲128位(16字節).
	 */
	public static String generateAesKeyString() {
		return Encodes.encodeHex(generateAesKey(DEFAULT_AES_KEYSIZE));
	}
	
	/**
	 * 生成AES密鑰,返回字節數組, 默認長度爲128位(16字節).
	 */
	public static byte[] generateAesKey() {
		return generateAesKey(DEFAULT_AES_KEYSIZE);
	}

	/**
	 * 生成AES密鑰,可選長度爲128,192,256位.
	 */
	public static byte[] generateAesKey(int keysize) {
		try {
			KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
			keyGenerator.init(keysize);
			SecretKey secretKey = keyGenerator.generateKey();
			return secretKey.getEncoded();
		} catch (GeneralSecurityException e) {
			throw Exceptions.unchecked(e);
		}
	}

	/**
	 * 生成隨機向量,默認大小爲cipher.getBlockSize(), 16字節.
	 */
	public static byte[] generateIV() {
		byte[] bytes = new byte[DEFAULT_IVSIZE];
		random.nextBytes(bytes);
		return bytes;
	}
}

CryptosTest.java

package common;

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

import com.minstone.common.security.Cryptos;

public class CryptosTest {

    public static String AESKey = "125858a550c605c199c19d778b81327b";
    public static String AESIV = "0392039203920300";
    
    public static String param = "<?xml version=\"1.0\" encoding=\"GBK\"?>\n<SPItemListDef>\n\t<TableCols name=\"YWBD_WHT_HLWWHJYDWBG\"  id = \"0\">\n\t\t<List name=\"YWBD_WHT_HLWWHJYGDXX\">\n\t\t\t<TableCols id = \"0\">\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>GDQY</ColName>\n\t\t\t\t\t<ColValue><![CDATA[測試]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>HLWWHJYDWBG_SEQ</ColName>\n\t\t\t\t\t<ColValue><![CDATA[72ed76449b374b3bba77347561dfcc70]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>GDFRXM</ColName>\n\t\t\t\t\t<ColValue><![CDATA[測試]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t\t<Column>\n\t\t\t\t\t<ColName>SEQ</ColName>\n\t\t\t\t\t<ColValue><![CDATA[2ec5c892b0934f6381b8d2e20dd388c7]]></ColValue>\n\t\t\t\t</Column>\n\t\t\t</TableCols>\n\t\t</List>\n\t\t<Column>\n\t\t\t<ColName>YZSDZ</ColName>\n\t\t\t<ColValue><![CDATA[廣州市]]></ColValue>\n\t\t</Column>\n\t\t<Column>\n\t\t\t<ColName>BGSQR</ColName>\n\t\t\t<ColValue><![CDATA[明動軟件]]></ColValue>\n\t\t</Column>\n\t\t<Column>\n\t\t\t<ColName>SEQ</ColName>\n\t\t\t<ColValue><![CDATA[72ed76449b374b3bba77347561dfcc70]]></ColValue>\n\t\t</Column>\n\t</TableCols>\n</SPItemListDef>";

    
    public static void main(String[] args) {
        String enCode = enCode(param);
        enCode = "sU8EtK9gy/B7sOfrNrtaPf5+b6gcBA2u1i7VYVoIWd0z0S/GJBwR4NQQAaWBjqimZKysWZ3aefH3YN3xqBrG0I1O1q1zlGuDM6+P0JuZFXWOJB90wOvAFywoDBiFb6j3u4s73++BcZpTKV5HpQoWZjIA7eaVjVZX1ML5Z04xNuAnQH2ZM104v/S+5toxt8BbQgI8x1fYfU8vXiHmZkvzc/jGsg8ZDrXKa0utVMdak+EqzGFMAsj7YMclL3YFVQjW1ax0f81CU2oNWD6JMKalLmqFud1QAADhUtRkfsfsMldxLDykFV+Pzpd6OlAX34uPbWOBYdTS/unt0ExZklHE7bU/VYSAhZdZPsfxyO5usUEYMHJtv15Xqk3t8Dq9QZ28NZ1xcRK5nHoEckchLZpQyD5uXWbLdhy2GO4MS+7qSCBgV5QgUgOWN86LZgCPxmkOV5mYBxXtWI2mByOIm4d3ul8D4VBb2I04QDw/iVwOOKXuFzKL1lwuf3p9Z/ZvhTuPkLqVUQoa9f63G2flGSUIZ5oOVzQkBiJ/H/ybpRl19NTAhwZJK5QiD7OgK4DEd0WmrW64pj9Bun1yEQnSknc/zHvQw1WXQiecQ0CKF3uvUG0aOskwdZwDXvcvdXyt8+hEjGZf2CRxVjxgNRcpHl0M/S6kDhk0Yv3NXYTOspmG2SyR2Eofw8YGZxO3yWxqKzIZQOgFdFhygq/Zrtt7CUiw0+0fSRMM8wCzDKeIZr5yUdUiNUQzOdrygC2lGSPrP3GP+RcKGuHBe4N62uBrGj14IDj/74ZPjSiLm3NuOZ7pBGHVqr7RH9Uz9Sjv9coRs3At/ypVSXWpigy6Mi/ZuctnvcgK1tgAXs9QMvxVkJCzuKx0qQL7MArdFMngLySxP+1Z81It9PKXU7olc+koits5BIHWibXMF7TBBX1VDv/af+Kugjs6L+6uKBrU10XmKRrYORSaT81Ws5R5pwb9DK6psL+zjToeKH8mpTrPzPqMxV+qwYK4Yxr91xWblBxMCEdab/BljhtdOB37QrikB3ECXTSg8qWSsp1ciMnVuidP5Dmo0UUxDoKATeYhcM6r20s4v3+6TjoPTDu27lsEAUiKdS2iYCq0QUN4nZ+qehhje8uHU5KFaV9kgdAKN8MECM+GnhK+Uc1Pf02zNnetLYKu7u5bdW57JOE6ldbpu1YbUERNxX609ybDpsm9ixBreRPGy3oaWJ3Tbvtu6wVzK5ATRhfN04WnaI6Z/3H2y8OoC8tbnFdXFFbAeMPMRQIZUy/WG9dzOZ3cuCaak2OKmBWnTqABpd3yNR6ZUZOEiwd36EkGP6zWNrE0J0GlBdugU2b7";
        decode(enCode);
    }

    private static String enCode(String param) {
        byte[] aesEncrypt = Cryptos.aesEncrypt(param.getBytes(), AESKey.getBytes(), AESIV.getBytes());
        System.out.println("param:" + param);
        System.out.println(new Base64().encodeToString(aesEncrypt));
        return Base64.encodeBase64String(aesEncrypt);
    }

    private static void decode(String param) {
        System.out.println("param:" + param);
        //System.out.println(new String(new Base64().decode(param)) );
        byte[] aesDecrypt = Cryptos.aesDecrypt( new Base64().decode(param), AESKey.getBytes(), AESIV.getBytes());
        System.out.println(new String(aesDecrypt));
    }
}

  • 運行結果
    運行結果

注意:在這過程中,遇到了一個坑,那就是解密的時候,最好將傳入的解密參數的 " " 替換爲 “+” ,否則報錯。

以下是實際應用的時候的部分代碼:
/**
     * 描述:獲取表單業務數據xml(參數及返回值均進行AES加密)
     * @author chendongwei
     * @date 2020年2月18日 下午4:15:55
     * @param request
     * @param response
     * @param info
     * @param params
     * @param token
     */
    @RequestMapping(value = "getFormDataXMLAES", produces = "text/html;charset=UTF-8")
    public void getFormDataXMLAES(HttpServletRequest request, HttpServletResponse response,
                                 @RequestParam(value = "jsonParam", required = false) String jsonParam,
                                 @RequestParam(value = "token", required = false) String token) {
        Map<String, Object> xml;
        try {
            //common.properties 配置了AESKey和AESIV
            String AESKey = Global.getConfig("AESKey");
            String AESIV = Global.getConfig("AESIV");
            //對入參進行AES解密
            byte[] aesDecrypt = Cryptos.aesDecrypt(new Base64().decode(jsonParam.replace(" ", "+")), AESKey.getBytes(), AESIV.getBytes());
            jsonParam = new String(aesDecrypt);
            //將解密後的json解析爲Map,再獲取到實際參數
            Map<String, Object> maps = JSON.parseObject(jsonParam);
            FormInfo info = new FormInfo();
            info.setCode(maps.get("code").toString());
            String params = maps.get("params").toString();
            String returnDataType = maps.get("returnDataType").toString();
            logger.info("code:" + maps.get("code").toString() + ",params:" + maps.get("params").toString() + ",returnDataType:" + returnDataType);
            
            if (StringUtils.isNotBlank(token))
                token = URLDecoder.decode(token, "utf-8");
            boolean isGetXml = true;
            if ("json".equals(returnDataType)) {
                isGetXml = false;
            }
            xml = formInfoService.getFromDataXML(info, params, isGetXml, token, request);
            
            ...
            xml.put("data", Base64.encodeBase64String(Cryptos.aesEncrypt(xml.get("rtnData").toString().getBytes("UTF-8"), AESKey.getBytes(), AESIV.getBytes())));
            ...
            xml.put("errcode", 0);
            xml.put("errmsg", null);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            ...
        }
        renderString(response, xml);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章