此次算法支持16位密钥和32位密钥加密,如果密钥长度是32位,则需要更新加密包,16位密钥则不需要更新加密包,不清楚怎样更新加密包的,可以查看加密专栏另一篇文章,在此不再赘述

如何让AES128加密支持32位密钥

如果只需要看AES128加密则只需要下面这个方法就可以了

	/**
	 * AES128加密
	 * @param src 加密原串
	 * @param key  密钥
	 * @return
	 */
	public static String aesEncrypt(String src, String key) {
		try{
			if (key == null || key.equals("")) {
				logger.info("密钥为空:"+ key);
				return null;
			}
			byte[] raw = key.getBytes("utf-8");
			SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
			Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
			byte[] encrypted = cipher.doFinal(src.getBytes("utf-8"));
			return Base64Coder.encodeLines(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。
			// 	若有换行符困扰则使用:
			//	return Base64Coder.encodeLines(encrypted).replaceAll("[\\s*\t\n\r]", "");
			
		}catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

实际开发可能会遇到的加密完整需求:去除某些属性、字典排序、构造加密原串、最后才是AES128加密等

	/*
	* aes128加密串获得
	* @param param 待加密参数
 	* */
public static String aesSign(Map<String,String> param) {
		//	实名认证密钥
		String secretkey = PropertiesUtil.getProperty(GmsConstant.ADULT_AUTHENTICATION_SECRETKEY);
		// 加密串
		String signature = "";
		// 去除数组中的空值、签名参数、appkey(不需要的可以去除此步骤)
		Map<String, String> encrypteMap = paraFilter(param);
		// 按ascii码排序(不需要的可以去除此步骤)
		List<Map.Entry<String, String>> infoIds = asciiSort(encrypteMap);
		//	构造待加密原串
		String produceStr = produceAesStr(infoIds);
		try {
			signature = aesEncrypt(produceStr,secretkey);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("aesSign签名异常-param:"+ param.toString());
		}
		return signature;
	}

去除加密参数中的某些属性,可自定义

	/**
	 * 除去空值、 sign 的系统参数和除去请求体外的业务参数(去除哪些参数可以自定义)
	 * @param para 请求要素
	 * @return 除去空值、sign 的系统参数和除去请求体外的业务参数后的参数
	 */
	public static Map<String, String> paraFilter(Map<String, String> para) {

		Map<String, String> result = new HashMap<String, String>();

		if (para == null || para.size() <= 0) {
			return result;
		}

		for (String key : para.keySet()) {
			String value = para.get(key);
			if (value == null || value.equals("") || key.equalsIgnoreCase("data")
					|| key.equalsIgnoreCase("sign")) {
				continue;
			}
			result.put(key, value);
		}
		return result;
	}

待加密参数按字典顺序排序

	/**
	 * map集合按ascii码从小到大排序
	 * @param map 排序前的map集合
	 * @return List<Map.Entry<String, String>> 排序后的list集合
	 */
	public static List<Map.Entry<String, String>> asciiSort(Map<String, String> map) {
		List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>();
		try {
			infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
			// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
			Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {

				public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
					return (o1.getKey()).toString().compareTo(o2.getKey());
				}
			});
		}catch(Exception e){
			logger.info("asciiSort(参数异常):"+map);
			e.printStackTrace();
		}
		return infoIds;
	}

加密原串构造

	/**
	 * 【实名认证】构造AES-128签名原串
	 * @param paramList 参数list
	 * @return "key":"val","key":"val"字符串(格式可以自定义)
	 */
	public static String produceAesStr(List<Map.Entry<String, String>> paramList) {
		String result = "";
		// 构造签名键值对的格式
		StringBuilder sb = new StringBuilder();
		sb.append("{");
		for (Map.Entry<String, String> item : paramList) {
			if (item.getKey() != null || item.getKey() != "") {
				String key = item.getKey();
				String val = item.getValue();
				if (!(val == "" || val == null)) {
					sb.append('"'+key + '"' + ':' + '"' + val + '"' + ",");
				}
			}
		}
		result = sb.toString();
		// 	去除末尾的","
		if(result.length()>1){
			return result.substring(0, sb.toString().length()-1)+"}";
		}else {
			return result;
		}
	}

在这里插入图片描述

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐