国密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 chineseSplitFunction(String src, int bytes) {
		try {
			if (src == null) {
				return null;
			}
			List splitList = new ArrayList();
			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 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 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 suByteGroupData(byte[] src, int count) {
		ArrayList listByte = new ArrayList();
		// 获取原始数据的字节长度
		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 chineseSplitFunction(String src, int bytes) {
		try {
			if (src == null) {
				return null;
			}
			List splitList = new ArrayList();
			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 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 getStrList(String inputString, int length,
			int size) {
		List list = new ArrayList();
		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);
		}
	}

	/**
	 * 计算中英文字符串的字节长度 
* 一个中文占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; } }

 

你可能感兴趣的:(国密算法)