國密SM2硬件分組算法

 sm2分組加密 如果被加密的內容超過136的話就需要分組加密了 漁翁加密卡支持: sm2加密最大數據長度是136位

GBK編碼,一個漢字佔兩個字節。UTF-8編碼是變長編碼,通常漢字佔三個字節,擴展B區以後的漢字佔四個字節。

 GBK編碼,一個漢字佔兩個字節。UTF-8編碼是變長編碼,通常漢字佔三個字節,擴展B區以後的漢字佔四個字節。
 * UTF-16編碼,通常漢字佔兩個字節,擴展D區中的漢字佔四個字節 中文字支持45分組 特殊字符支持136分組 sm2分組解密數據特性:

 

 

下面是國密硬件字節分組算法實現

/**
	 * 字符串按照佔字節數大小進行切分分組
	 * 
	 * @param src
	 * @param bytes
	 * @return
	 */
	public static List<String> chineseSplitFunction(String src, int bytes) {
		try {
			if (src == null) {
				return null;
			}
			List<String> splitList = new ArrayList<String>();
			int startIndex = 0; // 字符串截取起始位置
			int endIndex = bytes > src.length() ? src.length() : bytes; // 字符串截取結束位置
			while (startIndex < src.length()) {
				String subString = src.substring(startIndex, endIndex);
				// 截取的字符串的字節長度大於需要截取的長度時,說明包含中文字符
				// 在GBK編碼中,一箇中文字符佔2個字節,UTF-8編碼格式,一箇中文字符佔3個字節。
				while (subString.getBytes(ENCODE_UTF).length > bytes) {
					--endIndex;
					subString = src.substring(startIndex, endIndex);
				}
				splitList.add(src.substring(startIndex, endIndex));
				startIndex = endIndex;
				// 判斷結束位置時要與字符串長度比較(src.length()),之前與字符串的bytes長度比較了,導致越界異常。
				endIndex = (startIndex + bytes) > src.length() ? src.length()
						: startIndex + bytes;

			}
			return splitList;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

注意:分組加密後是2進制的亂碼,如果存在不同系統之間的交互,可以把每一個分組的加密的密文信息轉換成16進制後,在解密的時候將16進制轉換成二進制再分組解密。(分組解密字節加密卡最大支持260,不過這個不用考慮,硬件136字節能加密就能解密)

附送 工具類

package com.people.utils;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * sm2分組加密 如果被加密的內容超過136的話就需要分組加密了 漁翁加密卡支持: sm2加密最大數據長度是136位
 * GBK編碼,一個漢字佔兩個字節。UTF-8編碼是變長編碼,通常漢字佔三個字節,擴展B區以後的漢字佔四個字節。
 * UTF-16編碼,通常漢字佔兩個字節,擴展D區中的漢字佔四個字節 中文字支持45分組 特殊字符支持136分組 sm2分組解密數據特性:
 * 解密內容長度最大246
 * 
 * @author zhaozhiqiang
 *
 */
public class Sm2GroupEncryUtils {
	// 編碼方式
	private static final String ENCODE_UTF = "UTF-8";
	public static final String chineseString = "13132,,,,,,我是testStsdfgdgagagaasdasfasfdring哈哈哈";

	public static void main(String[] arg) throws Exception {
		// List<String> splitStringList = chineseSplitFunction(chineseString,
		// 5);
		// for (String split:splitStringList) {
		// System.out.println(split);
		// }
		byte[] ss = new byte[531];
		for (int i = 0; i < ss.length; i++) {
			ss[i] = (byte) i;

		}
		int num=0;
		ArrayList<byte[]> suByteGroupData = suByteGroupData(ss,246);
		    for (byte[] bs : suByteGroupData) {
		    	System.out.println("解密分組內容長度"+bs.length);
		    	num=num+bs.length;
			}
		    System.out.println("解密內容長度"+num);
	}
	/**
	 * sm2解密分組數據
	 * @param src
	 * @param start 第一次是0
	 * @param preCount 前面的字節數據大小
	 * @param count 動態分組的密文字節大小
	 * @return
	 */
	public static byte[] suByteGroupForeverData(byte[] src,int start,int preCount, int count) {
		if(start==0&&preCount==0){
			byte[] subBytes = subBytes(src, 0, count);	
			return subBytes;
		}else{
			byte[] subBytes = subBytes(src, src.length-preCount, count);	
			return subBytes;
		}
	}
	/**
	 * sm2解密分組數據
	 * 
	 * @param src
	 *            原始數據
	 * @param count
	 *            分組的字節長度,sm2解密字節長度最大支持246
	 * @return
	 */
	public static ArrayList<byte[]> suByteGroupData(byte[] src, int count) {
		ArrayList<byte[]> listByte = new ArrayList<byte[]>();
		// 獲取原始數據的字節長度
		int srcLenth = src.length;
		double f1 = new BigDecimal((float) srcLenth / count).setScale(2,
				BigDecimal.ROUND_HALF_UP).doubleValue();
		int ceil = (int) Math.ceil(f1);
		System.out.println("解密分組次數:"+ceil);
		// 比較原始數據和當前的分組字節長度
		if (srcLenth <= count) {
			byte[] subBytes = subBytes(src, 0, srcLenth);
			listByte.add(subBytes);
			return listByte;
		} else {// 原始數據字節長度大於分組長度需要截取分組
			for (int i = 1; i <= ceil; i++) {
				if ((src.length % count) == 0) {// 剛好整除
					byte[] subBytes1 = subBytes(src, i * count, count);
					listByte.add(subBytes1);
				} else {// 沒有整除,分兩部分,一部分是整除的部分(count)還有餘下的部分(srcLenth-count*(i-1))
					if (i <= ceil - 1) {
						byte[] subBytes2 = subBytes(src, (i-1)* (count), count);
						listByte.add(subBytes2);
					} else {
						byte[] subBytes3 = subBytes(src, (i-1)* (count), srcLenth
								- (i-1)* (count));
						listByte.add(subBytes3);
					}
				}
			}
		}
		return listByte;

	}

	/**
	 * 在字節數組中截取指定長度數組
	 * 
	 * @param src
	 * @param begin
	 * @param count
	 * @return
	 */
	public static byte[] subBytes(byte[] src, int begin, int count) {
		byte[] bs = new byte[count];
		System.arraycopy(src, begin, bs, 0, count);
		return bs;
	}

	/**
	 * 字符串按照佔字節數大小進行切分分組
	 * 
	 * @param src
	 * @param bytes
	 * @return
	 */
	public static List<String> chineseSplitFunction(String src, int bytes) {
		try {
			if (src == null) {
				return null;
			}
			List<String> splitList = new ArrayList<String>();
			int startIndex = 0; // 字符串截取起始位置
			int endIndex = bytes > src.length() ? src.length() : bytes; // 字符串截取結束位置
			while (startIndex < src.length()) {
				String subString = src.substring(startIndex, endIndex);
				// 截取的字符串的字節長度大於需要截取的長度時,說明包含中文字符
				// 在GBK編碼中,一箇中文字符佔2個字節,UTF-8編碼格式,一箇中文字符佔3個字節。
				while (subString.getBytes(ENCODE_UTF).length > bytes) {
					--endIndex;
					subString = src.substring(startIndex, endIndex);
				}
				splitList.add(src.substring(startIndex, endIndex));
				startIndex = endIndex;
				// 判斷結束位置時要與字符串長度比較(src.length()),之前與字符串的bytes長度比較了,導致越界異常。
				endIndex = (startIndex + bytes) > src.length() ? src.length()
						: startIndex + bytes;

			}
			return splitList;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 字符串按照佔字節數大小進行切分分組 當前場景適用於不帶,符號的字符串
	 * 
	 * @param value
	 * @param length
	 * @return
	 * @throws Exception
	 * @throws Exception
	 */
	public static String splitBySize(String value, int length) throws Exception {
		char[] cs = value.toCharArray();
		String str = "";
		int index = 0;
		boolean flag = false;
		for (char c : cs) {
			index += String.valueOf(c).getBytes(ENCODE_UTF).length;
			if (index > length) {
				if (flag) {

					if ((index % length) == 0) {
						if (str.substring(str.length() - 1).equals(",")) {
							str = str + c;
						} else {
							str = str + c + ",";
						}
					} else {
						String[] split = str.split(",");
						String string = split[split.length - 1];
						if ((String.valueOf(c).getBytes(ENCODE_UTF).length + String
								.valueOf(string).getBytes(ENCODE_UTF).length) > length) {
							if (str.substring(str.length() - 1).equals(",")) {
								str = str + c;
							} else {
								str = str + "," + c;
							}

						} else {
							str = str + c;
						}
					}
				} else {
					if ((index % length) == 0) {
						String[] split = str.split(",");
						String string = split[split.length - 1];
						if ((String.valueOf(c).getBytes(ENCODE_UTF).length + String
								.valueOf(string).getBytes(ENCODE_UTF).length) > length) {
							str = str + "," + c;
						} else {
							str = str + c;
						}
						flag = true;
					} else {
						String[] split = str.split(",");
						String string = split[split.length - 1];
						if ((String.valueOf(c).getBytes(ENCODE_UTF).length + String
								.valueOf(string).getBytes(ENCODE_UTF).length) > length) {
							str = str + "," + c;
						} else {
							str = str + c;
						}
					}
				}
			} else {
				if (index < length) {
					str = str + c;
				} else if (index == length) {
					str = str + c + ",";
					flag = true;
				}
			}
		}
		return str;
	}

	/**
	 * java截取字符串中字節長度,超出的捨棄
	 * 
	 * @param str
	 * @param subSLength
	 * @return
	 */
	public static String subByteStr(String str, int subSLength) {
		String subStr = "";
		try {
			if (str == null)
				return "";
			else {
				int tempSubLength = subSLength;// 截取字節數
				subStr = str.substring(0,
						str.length() < subSLength ? str.length() : subSLength);// 截取的子串
				int subStrByetsL = subStr.getBytes(ENCODE_UTF).length;// 截取子串的字節長度
				// 說明截取的字符串中包含有漢字
				while (subStrByetsL > tempSubLength) {
					int subSLengthTemp = --subSLength;
					subStr = str.substring(0,
							subSLengthTemp > str.length() ? str.length()
									: subSLengthTemp);
					subStrByetsL = subStr.getBytes(ENCODE_UTF).length;
				}
			}
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return subStr;
	}

	/**
	 * 把原始字符串分割成指定長度的字符串列表
	 * 
	 * @param inputString
	 *            原始字符串
	 * @param length
	 *            指定長度
	 * @return
	 */
	public static List<String> getStrList(String inputString, int length) {
		int size = inputString.length() / length;
		if (inputString.length() % length != 0) {
			size += 1;
		}
		return getStrList(inputString, length, size);
	}

	/**
	 * 把原始字符串分割成指定長度的字符串列表
	 * 
	 * @param inputString
	 *            原始字符串
	 * @param length
	 *            指定長度
	 * @param size
	 *            指定列表大小
	 * @return
	 */
	public static List<String> getStrList(String inputString, int length,
			int size) {
		List<String> list = new ArrayList<String>();
		for (int index = 0; index < size; index++) {
			String childStr = substring(inputString, index * length,
					(index + 1) * length);
			list.add(childStr);
		}
		return list;
	}

	/**
	 * 分割字符串,如果開始位置大於字符串長度,返回空
	 * 
	 * @param str
	 *            原始字符串
	 * @param f
	 *            開始位置
	 * @param t
	 *            結束位置
	 * @return
	 */
	public static String substring(String str, int f, int t) {
		if (f > str.length())
			return null;
		if (t > str.length()) {
			return str.substring(f, str.length());

		} else {
			return str.substring(f, t);
		}
	}

	/**
	 * 計算中英文字符串的字節長度 <br/>
	 * 一箇中文佔3個字節
	 *
	 * @param str
	 * @return int 字符串的字節長度
	 */
	public static int getChinaAndEnglishStrLength(String str) {
		if (str == null || str.length() == 0) {
			return 0;
		}
		try {
			return str.getBytes(ENCODE_UTF).length;
		} catch (UnsupportedEncodingException e) {
			System.out.println("計算中英文字符串的字節長度失敗," + e);
		}
		return 0;
	}

	/**
	 * 計算中英文字符串的字節長度
	 * 
	 * @param str
	 * @return int
	 */
	public static int getEnglishAndChinaStrLength(String str) {
		if (str == null || str.length() == 0) {
			return 0;
		}
		int len = 0;
		for (int i = 0, j = str.length(); i < j; i++) {
			// UTF-8編碼格式中文佔三個字節,GBK編碼格式 中文佔兩個字節 ;
			len += (str.charAt(i) > 255 ? 3 : 1);
		}
		return len;
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章