公用类算法:

PCIKeyPair.java

/**
* @Author: dzy
* @Date: 2018/9/27 14:18
* @Describe: 公私钥对
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PCIKeyPair { private String priKey; //私钥
private String pubKey; //公钥 }

CommonUtils.java

import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date; /**
* @ClassName: CommonUtils
* @Description: 通用工具类
* @since: 0.0.1
* @author: dzy
* @date: 2017年2月22日 上午11:46:44
*/
public class CommonUtils { /**
* @param date 日期
* @param pattern 模式 如:yyyyMMdd等
* @return
* @Title: formatDate
* @Description: 格式化日期
* @since: 0.0.1
*/
public static String formatDate(Date date, String pattern) {
SimpleDateFormat formatter = new SimpleDateFormat(pattern);
return formatter.format(date);
} /**
* @param strDate String类型日期
* @param pattern 日期显示模式
* @return
* @Title: parseDate
* @Description: 将String日期转换为Date类型日期
* @since: 0.0.1
*/
public static Date parseDate(String strDate, String pattern) {
SimpleDateFormat formatter = null;
if (StringUtils.isBlank(strDate)) {
return null;
}
formatter = new SimpleDateFormat(pattern);
try {
return formatter.parse(strDate);
} catch (Exception e) {
e.printStackTrace();
return null;
}
} /**
* @param date 操作前的日期
* @param field 日期的部分如:年,月,日
* @param amount 增加或减少的值(负数表示减少)
* @return
* @Title: dateAdd
* @Description: 日期的加减操作
* @since: 0.0.1
*/
public static Date dateAdd(Date date, int field, int amount) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(field, amount);
return calendar.getTime();
} /**
* @param source 源字符串
* @param offset 填充开始的位置, 0-在左边, source.getBytes().length 在右边, 如果有中文时需小心位置
* @param c 用于填充的字符
* @param length 最后字符串的字节长度
* @return
* @Title: fill
* @Description: 填充字符串, 长度是按字节计算, 不是字符
* @since: 0.0.1
*/
public static String fill(String source, int offset, char c, int length) throws UnsupportedEncodingException {
if (null == source) {
source = "";
}
if (source.getBytes(CustomConstants.CHARSET_UTF8).length == length) {
return source;
}
byte[] buf = new byte[length];
byte[] src = source.getBytes(CustomConstants.CHARSET_UTF8);
if (src.length > length) {
System.arraycopy(src, src.length - length, buf, 0, length);
return new String(buf, CustomConstants.CHARSET_UTF8);
}
if (offset > src.length) {
offset = src.length;
} else if (offset < 0) {
offset = 0;
}
int n = length - src.length; System.arraycopy(src, 0, buf, 0, offset);
for (int i = 0; i < n; i++) {
buf[i + offset] = (byte) c;
}
System.arraycopy(src, offset, buf, offset + n, src.length - offset);
return new String(buf, CustomConstants.CHARSET_UTF8);
} /**
* @param original 原字符串
* @param offset 填充开始的位置, 0-在左边, original.getBytes().length 在右边, 如果有中文时需小心位置
* @param length 替换的字节数
* @param c 用于替换的字符
* @return
* @Title: replace
* @Description: 替换字符串, 长度是按字节计算, 不是字符
* @since: 0.0.1
*/
public static String replace(String original, int offset, int length, char c) throws UnsupportedEncodingException {
if (original == null) {
original = "";
}
if (original.getBytes(CustomConstants.CHARSET_UTF8).length <= offset) {
return original;
}
if (original.getBytes(CustomConstants.CHARSET_UTF8).length < offset + length) {
length = original.getBytes(CustomConstants.CHARSET_UTF8).length - offset;
}
byte[] buf = new byte[original.length()];
byte[] src = original.getBytes(CustomConstants.CHARSET_UTF8);
System.arraycopy(src, 0, buf, 0, offset); for (int i = offset; i < offset + length; i++) {
buf[i] = (byte) c;
}
System.arraycopy(src, offset + length, buf, offset + length, src.length - offset - length);
return new String(buf, CustomConstants.CHARSET_UTF8);
} /**
* @param s 16进制字符串
* @return
* @Title: hexToByte
* @Description: 16进制字符串转字节数组
* @since: 0.0.1
*/
public static byte[] hexToByte(String s) {
byte[] result = null;
try {
int i = s.length();
// if (i % 2 == 1) {
// throw new Exception("字符串长度不是偶数.");
// }
if (i % 2 != 0) {
throw new Exception("字符串长度不是偶数.");
}
result = new byte[i / 2];
for (int j = 0; j < result.length; j++) {
result[j] = (byte) Integer.parseInt(s.substring(j * 2, j * 2 + 2), 16);
}
} catch (Exception e) {
result = null;
e.printStackTrace();
// log.error("16进制字符串转字节数组时出现异常:", e);
}
return result;
} /**
* @param bytes 字节数组
* @return
* @Title: byte2hexString
* @Description: 字节数组转换为16进制字符串 //0x33 0xD2 0x00 0x46 转换为 "33d20046" 转换和打印报文用
* @since: 0.0.1
*/
public static String byte2hexString(byte[] bytes) {
StringBuffer buf = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
if (((int) bytes[i] & 0xff) < 0x10) {
buf.append("0");
}
buf.append(Long.toString((int) bytes[i] & 0xff, 16));
}
return buf.toString().toUpperCase();
} /**
* @param hexString 16进制字符串 如:"33d20046" 转换为 0x33 0xD2 0x00 0x46
* @return
* @Title: hexString2byte
* @Description: 16进制字符串转字节数组
* @since: 0.0.1
*/
public static byte[] hexString2byte(String hexString) {
if (null == hexString || hexString.length() % 2 != 0 || hexString.contains("null")) {
return null;
}
byte[] bytes = new byte[hexString.length() / 2];
for (int i = 0; i < hexString.length(); i += 2) {
bytes[i / 2] = (byte) (Integer.parseInt(hexString.substring(i, i + 2), 16) & 0xff);
}
return bytes;
} /**
* @param i 需要转的int类型数字
* @return
* @Title: byte1ToBcd2
* @Description: int类型转BCD码
* @since: 0.0.1
*/
public static String byte1ToBcd2(int i) {
// return (new Integer(i / 16).toString() + (new Integer(i % 16)).toString());
return Integer.toString(i / 16) + Integer.toString(i % 16);
} /**
* @param b 字节数组
* @return
* @Title: byteToHex2
* @Description: 字节数组转换为16进制字符串 For example, byte[] {0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF} will be changed to String "0123456789ABCDEF"
* @since: 0.0.1
*/
public static String byteToHex2(byte[] b) {
StringBuffer result = new StringBuffer();
String tmp = ""; for (int i = 0; i < b.length; i++) {
tmp = Integer.toHexString(b[i] & 0xff);
if (tmp.length() == 1) {
result.append("0" + tmp);
} else {
result.append(tmp);
}
}
return result.toString().toUpperCase();
} /**
* @param num 数字
* @param len 字节数组长度
* @return
* @Title: intToHexBytes
* @Description: int类型转16进制字节数组
*/
public static byte[] intToHexBytes(int num, int len) {
byte[] bytes = null;
String hexString = Integer.toHexString(num);
if (len > 0) {
int length = len * 2;
hexString = CustomStringUtils.leftFill(hexString, '0', length);
bytes = CommonUtils.hexString2byte(hexString);
}
return bytes;
} /*public static String byteToHex3(byte[] b) {
String result = "";
String tmp = ""; for (int n = 0; n < b.length; n++) {
tmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
if (tmp.length() == 1) {
result = result + "0" + tmp;
} else {
result = result + tmp;
}
if (n < b.length - 1) {
result = result + "";
}
}
return result.toUpperCase();
}*/ /**
* @param str 需要转换编码的字符串
* @return
* @Title: iso2Gbk
* @Description: 将ISO-8859-1编码的字符串转成GBK编码的字符串
* @since: 0.0.1
*/
public static String iso2Gbk(String str) {
if (null == str) {
return str;
}
try {
return new String(str.getBytes("ISO-8859-1"), "GBK");
} catch (UnsupportedEncodingException e) {
// log.error("不支持的编码异常:", e);
e.printStackTrace();
return str;
}
} // /**
// * @param message
// * @return
// * @Title: getSubElement
// * @Description: 分解各子域到HashMap
// * @since: 0.0.1
// */
// public static Map<String, String> getSubElement(byte[] message) {
// Map<String, String> map = new HashMap<String, String>();
// String key = null;
// String value = null;
// int len = 0;
// int idx = 0;
// while (idx < message.length) {
// key = new String(message, idx, 2);
// idx += 2; //取了SE id 移2位
// len = Integer.parseInt(new String(message, idx, 2));
// idx += 2; //取了SE id的内容长度 移2位
// value = new String(message, idx, len);
// map.put(key, value);
// idx += len;
// }
// return map;
// } //byte数组转成long /**
* @param b 将字节数组转long类型 位置为小端
* @return
*/
public static long byteToLong(byte[] b) {
long s = 0;
long s0 = b[0] & 0xff;// 最低位
long s1 = b[1] & 0xff;
long s2 = b[2] & 0xff;
long s3 = b[3] & 0xff;
long s4 = b[4] & 0xff;// 最低位
long s5 = b[5] & 0xff;
long s6 = b[6] & 0xff;
long s7 = b[7] & 0xff; // s0不变
s1 <<= 8;
s2 <<= 16;
s3 <<= 24;
s4 <<= 8 * 4;
s5 <<= 8 * 5;
s6 <<= 8 * 6;
s7 <<= 8 * 7;
s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
return s;
} /**
* @param b 将字节数组转int类型 位置为小端
* @return
*/
public static int byteToInt(byte[] b) {
int s = 0;
int s0 = b[0] & 0xff;// 最低位
int s1 = b[1] & 0xff;
int s2 = b[2] & 0xff;
int s3 = b[3] & 0xff; // s0不变
s1 <<= 8;
s2 <<= 16;
s3 <<= 24; s = s0 | s1 | s2 | s3;
return s;
} /**
* int类型转换小端的byte数组
* @param i
* @return
*/
public static byte[] intToLittleBytes(int i) {
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.asIntBuffer().put(i);
byte[] littleBytes = byteBuffer.array();
return littleBytes;
} /**
* 将一个字节转成10进制
* @param b
* @return
*/
public static int byteToInt(byte b) {
int value = b & 0xff;
return value;
} /**
* 字节数组合并
* @param bt1 字节数组bt1
* @param bt2 字节数组bt2
* @return
*/
public static byte[] byteMerger(byte[] bt1, byte[] bt2){
byte[] bt3 = new byte[bt1.length+bt2.length];
System.arraycopy(bt1, 0, bt3, 0, bt1.length);
System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);
return bt3;
} }

SM2算法:

package com.pcidata.common.tools.encrypt;

import com.pcidata.common.tools.CommonUtils;
import com.pcidata.common.tools.CustomStringUtils;
import com.pcidata.modules.key.modelvo.response.PCIKeyPair;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.bouncycastle.util.Strings;
import org.bouncycastle.util.encoders.Hex; import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom; /**
* @Author: dzy
* @Date: 2018/9/28 15:53
* @Describe: SM2工具类
*/
@Slf4j
public class SM2Util { /**
* 生成SM2公私钥对
* @return
*/
private static AsymmetricCipherKeyPair genKeyPair0() {
//获取一条SM2曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1"); //构造domain参数
ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
sm2ECParameters.getG(), sm2ECParameters.getN()); //1.创建密钥生成器
ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator(); //2.初始化生成器,带上随机数
try {
keyPairGenerator.init(new ECKeyGenerationParameters(domainParameters, SecureRandom.getInstance("SHA1PRNG")));
} catch (NoSuchAlgorithmException e) {
log.error("生成公私钥对时出现异常:", e);
// e.printStackTrace();
} //3.生成密钥对
AsymmetricCipherKeyPair asymmetricCipherKeyPair = keyPairGenerator.generateKeyPair();
return asymmetricCipherKeyPair;
} /**
* 生成公私钥对(默认压缩公钥)
* @return
*/
public static PCIKeyPair genKeyPair() {
return genKeyPair(true);
} /**
* 生成公私钥对
* @param compressedPubKey 是否压缩公钥
* @return
*/
public static PCIKeyPair genKeyPair(boolean compressedPubKey) {
AsymmetricCipherKeyPair asymmetricCipherKeyPair = genKeyPair0(); //提取公钥点
ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();
//公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥,04的时候,可以去掉前面的04
String pubKey = Hex.toHexString(ecPoint.getEncoded(compressedPubKey)); BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();
String priKey = privatekey.toString(16); PCIKeyPair keyPair = new PCIKeyPair(priKey, pubKey);
return keyPair;
} /**
* 私钥签名
* @param privateKey 私钥
* @param content 待签名内容
* @return
*/
public static String sign(String privateKey, String content) {
//待签名内容转为字节数组
byte[] message = Hex.decode(content); //获取一条SM2曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
//构造domain参数
ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
sm2ECParameters.getG(), sm2ECParameters.getN()); BigInteger privateKeyD = new BigInteger(privateKey, 16);
ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters); //创建签名实例
SM2Signer sm2Signer = new SM2Signer(); //初始化签名实例,带上ID,国密的要求,ID默认值:1234567812345678
try {
sm2Signer.init(true, new ParametersWithID(new ParametersWithRandom(privateKeyParameters, SecureRandom.getInstance("SHA1PRNG")), Strings.toByteArray("1234567812345678")));
} catch (NoSuchAlgorithmException e) {
log.error("签名时出现异常:", e);
} //生成签名,签名分为两部分r和s,分别对应索引0和1的数组
BigInteger[] bigIntegers = sm2Signer.generateSignature(message); byte[] rBytes = modifyRSFixedBytes(bigIntegers[0].toByteArray());
byte[] sBytes = modifyRSFixedBytes(bigIntegers[1].toByteArray()); byte[] signBytes = ByteUtils.concatenate(rBytes, sBytes);
String sign = Hex.toHexString(signBytes); return sign;
} /**
* 将R或者S修正为固定字节数
* @param rs
* @return
*/
private static byte[] modifyRSFixedBytes(byte[] rs) {
int length = rs.length;
int fixedLength = 32;
byte[] result = new byte[fixedLength];
if (length < 32) {
System.arraycopy(rs, 0, result, fixedLength - length, length);
} else {
System.arraycopy(rs, length - fixedLength, result, 0, fixedLength);
}
return result;
} /**
* 验证签名
* @param publicKey 公钥
* @param content 待签名内容
* @param sign 签名值
* @return
*/
public static boolean verify(String publicKey, String content, String sign) {
//待签名内容
byte[] message = Hex.decode(content);
byte[] signData = Hex.decode(sign); // 获取一条SM2曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
// 构造domain参数
ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
sm2ECParameters.getG(),
sm2ECParameters.getN());
//提取公钥点
ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(publicKey));
// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters); //获取签名
BigInteger R = null;
BigInteger S = null;
byte[] rBy = new byte[33];
System.arraycopy(signData, 0, rBy, 1, 32);
rBy[0] = 0x00;
byte[] sBy = new byte[33];
System.arraycopy(signData, 32, sBy, 1, 32);
sBy[0] = 0x00;
R = new BigInteger(rBy);
S = new BigInteger(sBy); //创建签名实例
SM2Signer sm2Signer = new SM2Signer();
ParametersWithID parametersWithID = new ParametersWithID(publicKeyParameters, Strings.toByteArray("1234567812345678"));
sm2Signer.init(false, parametersWithID); //验证签名结果
boolean verify = sm2Signer.verifySignature(message, R, S);
return verify;
} /**
* SM2加密算法
* @param publicKey 公钥
* @param data 数据
* @return
*/
public static String encrypt(String publicKey, String data){
// 获取一条SM2曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
// 构造domain参数
ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
sm2ECParameters.getG(),
sm2ECParameters.getN());
//提取公钥点
ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(publicKey));
// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters); SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters, new SecureRandom())); byte[] arrayOfBytes = null;
try {
byte[] in = data.getBytes("utf-8");
arrayOfBytes = sm2Engine.processBlock(in, 0, in.length);
} catch (Exception e) {
log.error("SM2加密时出现异常:", e);
}
return Hex.toHexString(arrayOfBytes);
} /**
* SM2加密算法
* @param publicKey 公钥
* @param data 明文数据
* @return
*/
public static String encrypt(PublicKey publicKey, String data) { ECPublicKeyParameters ecPublicKeyParameters = null;
if (publicKey instanceof BCECPublicKey) {
BCECPublicKey bcecPublicKey = (BCECPublicKey) publicKey;
ECParameterSpec ecParameterSpec = bcecPublicKey.getParameters();
ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
ecParameterSpec.getG(), ecParameterSpec.getN());
ecPublicKeyParameters = new ECPublicKeyParameters(bcecPublicKey.getQ(), ecDomainParameters);
} SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom())); byte[] arrayOfBytes = null;
try {
byte[] in = data.getBytes("utf-8");
arrayOfBytes = sm2Engine.processBlock(in,0, in.length);
} catch (Exception e) {
log.error("SM2加密时出现异常:", e);
}
return Hex.toHexString(arrayOfBytes);
} /**
* SM2解密算法
* @param privateKey 私钥
* @param cipherData 密文数据
* @return
*/
public static String decrypt(String privateKey, String cipherData) {
byte[] cipherDataByte = Hex.decode(cipherData); //获取一条SM2曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
//构造domain参数
ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
sm2ECParameters.getG(), sm2ECParameters.getN()); BigInteger privateKeyD = new BigInteger(privateKey, 16);
ECPrivateKeyParameters privateKeyParameters = new ECPrivateKeyParameters(privateKeyD, domainParameters); SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(false, privateKeyParameters); String result = null;
try {
byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
return new String(arrayOfBytes, "utf-8");
} catch (Exception e) {
log.error("SM2解密时出现异常:", e);
}
return result; } /**
* SM2解密算法
* @param privateKey 私钥
* @param cipherData 密文数据
* @return
*/
public static String decrypt(PrivateKey privateKey, String cipherData) {
byte[] cipherDataByte = Hex.decode(cipherData); BCECPrivateKey bcecPrivateKey = (BCECPrivateKey) privateKey;
ECParameterSpec ecParameterSpec = bcecPrivateKey.getParameters(); ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
ecParameterSpec.getG(), ecParameterSpec.getN()); ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(bcecPrivateKey.getD(),
ecDomainParameters); SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(false, ecPrivateKeyParameters); String result = null;
try {
byte[] arrayOfBytes = sm2Engine.processBlock(cipherDataByte, 0, cipherDataByte.length);
return new String(arrayOfBytes, "utf-8");
} catch (Exception e) {
log.error("SM2解密时出现异常:", e);
}
return result;
} /**
* 将未压缩公钥压缩成压缩公钥
* @param pubKey 未压缩公钥(16进制,不要带头部04)
* @return
*/
public static String compressPubKey(String pubKey) {
pubKey = CustomStringUtils.append("04", pubKey); //将未压缩公钥加上未压缩标识.
// 获取一条SM2曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
// 构造domain参数
ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
sm2ECParameters.getG(),
sm2ECParameters.getN());
//提取公钥点
ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(pubKey));
// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
// ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters); String compressPubKey = Hex.toHexString(pukPoint.getEncoded(Boolean.TRUE)); return compressPubKey;
} /**
* 将压缩的公钥解压为非压缩公钥
* @param compressKey 压缩公钥
* @return
*/
public static String unCompressPubKey(String compressKey) {
// 获取一条SM2曲线参数
X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");
// 构造domain参数
ECDomainParameters domainParameters = new ECDomainParameters(sm2ECParameters.getCurve(),
sm2ECParameters.getG(),
sm2ECParameters.getN());
//提取公钥点
ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(CommonUtils.hexString2byte(compressKey));
// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04
// ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters); String pubKey = Hex.toHexString(pukPoint.getEncoded(Boolean.FALSE));
pubKey = pubKey.substring(2); //去掉前面的04 (04的时候,可以去掉前面的04) return pubKey;
} }

SM3算法:

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex; import java.security.MessageDigest; /**
* @Author: dzy
* @Date: 2018/10/19 16:36
* @Describe: SM3工具类(杂凑算法-hash算法)
*/
@Slf4j
public class SM3Util { /**
* 16进制字符串SM3生成HASH签名值算法
* @param hexString 16进制字符串
* @return
*/
public static String hexEncrypt(String hexString) {
byte[] srcData = Hex.decode(hexString);
byte[] encrypt = encrypt(srcData);
String cipherStr = Hex.toHexString(encrypt);
return cipherStr;
} /**
* 16进制字符串SM3生成HASH签名值算法
* @param hexKey 16进制密钥
* @param hexString 16进制字符串
* @return
*/
public static String hexEncrypt(String hexKey, String hexString) {
byte[] key = Hex.decode(hexKey);
byte[] srcData = Hex.decode(hexString);
byte[] encrypt = encrypt(key, srcData);
String cipherStr = Hex.toHexString(encrypt);
return cipherStr;
} /**
* 普通文本SM3生成HASH签名算法
* @param plain 待签名数据
* @return
*/
public static String plainEncrypt(String plain) {
// 将返回的hash值转换成16进制字符串
String cipherStr = null;
try {
//将字符串转换成byte数组
byte[] srcData = plain.getBytes(CustomConstants.CHARSET_UTF8);
//调用encrypt计算hash
byte[] encrypt = encrypt(srcData);
//将返回的hash值转换成16进制字符串
cipherStr = Hex.toHexString(encrypt);
} catch (Exception e) {
log.error("将字符串转换为字节时出现异常:", e);
}
return cipherStr;
} /**
* 普通文本SM3生成HASH签名算法
* @param hexKey 密钥
* @param plain 待签名数据
* @return
*/
public static String plainEncrypt(String hexKey, String plain) {
// 将返回的hash值转换成16进制字符串
String cipherStr = null;
try {
//将字符串转换成byte数组
byte[] srcData = plain.getBytes(CustomConstants.CHARSET_UTF8);
//密钥
byte[] key = Hex.decode(hexKey);
//调用encrypt计算hash
byte[] encrypt = encrypt(key, srcData);
//将返回的hash值转换成16进制字符串
cipherStr = Hex.toHexString(encrypt);
} catch (Exception e) {
log.error("将字符串转换为字节时出现异常:", e);
}
return cipherStr;
} /**
* SM3计算hashCode
* @param srcData 待计算数据
* @return
*/
public static byte[] encrypt(byte[] srcData) {
SM3Digest sm3Digest = new SM3Digest();
sm3Digest.update(srcData, 0, srcData.length);
byte[] encrypt = new byte[sm3Digest.getDigestSize()];
sm3Digest.doFinal(encrypt, 0);
return encrypt;
} /**
* 通过密钥进行加密
* @param key 密钥byte数组
* @param srcData 被加密的byte数组
* @return
*/
public static byte[] encrypt(byte[] key, byte[] srcData) {
KeyParameter keyParameter = new KeyParameter(key);
SM3Digest digest = new SM3Digest();
HMac mac = new HMac(digest);
mac.init(keyParameter);
mac.update(srcData, 0, srcData.length);
byte[] result = new byte[mac.getMacSize()];
mac.doFinal(result, 0);
return result;
} /**
* SM3计算hashCode
* @param srcData 待计算数据
* @return
* @throws Exception
*/
public static byte[] encrypt_0(byte[] srcData) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SM3", "BC");
byte[] digest = messageDigest.digest(srcData);
return digest;
} }

SM4算法:

import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex; /**
* @Author: dzy
* @Date: 2018/10/9 16:41
* @Describe: SM4算法
*/
public class SM4Util { //加解密的字节快大小
public static final int BLOCK_SIZE = 16; /**
* SM4ECB加密算法
* @param in 待加密内容
* @param keyBytes 密钥
* @return
*/
public static byte[] encryptByEcb0(byte[] in, byte[] keyBytes) {
SM4Engine sm4Engine = new SM4Engine();
sm4Engine.init(true, new KeyParameter(keyBytes));
int inLen = in.length;
byte[] out = new byte[inLen]; int times = inLen / BLOCK_SIZE; for (int i = 0; i < times; i++) {
sm4Engine.processBlock(in, i * BLOCK_SIZE, out, i * BLOCK_SIZE);
} return out;
} /**
* SM4ECB加密算法
* @param in 待加密内容
* @param keyBytes 密钥
* @return
*/
public static String encryptByEcb(byte[] in, byte[] keyBytes) {
byte[] out = encryptByEcb0(in, keyBytes);
String cipher = Hex.toHexString(out);
return cipher;
} /**
* SM4的ECB加密算法
* @param content 待加密内容
* @param key 密钥
* @return
*/
public static String encryptByEcb(String content, String key) {
byte[] in = Hex.decode(content);
byte[] keyBytes = Hex.decode(key); String cipher = encryptByEcb(in, keyBytes);
return cipher;
} /**
* SM4的ECB解密算法
* @param in 密文内容
* @param keyBytes 密钥
* @return
*/
public static byte[] decryptByEcb0(byte[] in, byte[] keyBytes) {
SM4Engine sm4Engine = new SM4Engine();
sm4Engine.init(false, new KeyParameter(keyBytes));
int inLen = in.length;
byte[] out = new byte[inLen]; int times = inLen / BLOCK_SIZE; for (int i = 0; i < times; i++) {
sm4Engine.processBlock(in, i * BLOCK_SIZE, out, i * BLOCK_SIZE);
} return out;
} /**
* SM4的ECB解密算法
* @param in 密文内容
* @param keyBytes 密钥
* @return
*/
public static String decryptByEcb(byte[] in, byte[] keyBytes) {
byte[] out = decryptByEcb0(in, keyBytes);
String plain = Hex.toHexString(out);
return plain;
} /**
* SM4的ECB解密算法
* @param cipher 密文内容
* @param key 密钥
* @return
*/
public static String decryptByEcb(String cipher, String key) {
byte[] in = Hex.decode(cipher);
byte[] keyBytes = Hex.decode(key); String plain = decryptByEcb(in, keyBytes);
return plain;
} }

Java国密相关算法(bouncycastle)的更多相关文章

  1. Linux实现树莓派3B的国密SM9算法交叉编译——(二)miracl库的测试与静态库的生成

    先参考这篇文章 Linux实现树莓派3B的国密SM9算法交叉编译——(一)环境部署.简单测试与eclipse工程项目测试 部署好环境,并简单测试交叉编译环境是否安装成功,最后实现在Eclipse上进行 ...

  2. Linux实现树莓派3B的国密SM9算法交叉编译——(三)国密SM9算法实现

    先参考这篇文章 Linux实现树莓派3B的国密SM9算法交叉编译——(二)miracl库的测试与静态库的生成 进行miracl库的交叉编译测试,并生成miracl静态链接库. 这篇文章主要介绍基于mi ...

  3. 谈谈PBOC3.0中使用的国密SM2算法

    转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/39780825 作者:小马 一 知识准备 SM2是国密局推出的一种他们自己说具有自主 ...

  4. java 解析国密SM2算法证书

    首先说明用Java自带的解析x509证书类,是不能解析sm2算法的证书,执行会抛出异常. 用开源库bouncycastle能够解析.详细代码 private byte[] getCSPK(byte[] ...

  5. 国密SM3算法在linux和windows平台结果不一致问题

    什么是sm3,是一种类似于sha256的哈希算法,是咱们国家的哈希标准算法: 最近在使用sm3算法时,同样的一份数据,调用同样的sm3接口,发现得到的结果是不一样的: 那么在应用过的过程中,如果同样的 ...

  6. Linux实现树莓派3B的国密SM9算法交叉编译——(一)环境部署、简单测试与eclipse工程项目测试

    这篇文章主要介绍了交叉编译的实现,包括环境部署,并简单测试交叉编译环境是否安装成功. 一.交叉编译 在一个平台上生成另一个平台上的可执行代码.为什么要大费周折的进行交叉编译呢?一句话:不得已而为之.有 ...

  7. 国密SM9算法C++实现(Linux)

    首先参考 Linux下编译并使用miracl密码库 该博文在linux下编译Miracl库. 编译完了,自然是要用的,下面介绍两种在C程序中使用miracl库的方法. 方法一: 1. 源码编译完后的必 ...

  8. 20155206赵飞 基于《Arm试验箱的国密算法应用》课程设计个人报告

    20155206赵飞 基于<Arm试验箱的国密算法应用>课程设计个人报告 课程设计中承担的任务 完成试验箱测试功能1,2,3 . 1:LED闪烁实验 一.实验目的  学习GPIO原理  ...

  9. 《基于Arm实验箱的国密算法应用》课程设计 结题报告

    <基于Arm实验箱的国密算法应用>课程设计 结题报告 小组成员姓名:20155206赵飞 20155220吴思其 20155234昝昕明 指导教师:娄嘉鹏 设计方案 题目要求:基于Arm实 ...

随机推荐

  1. 人脸辨识,用树莓派Raspberry Pi实现舵机云台追踪脸孔

    影像辨识作为近年最热门的专业技术之一,广泛用于智慧监视器.车电监控.智慧工厂.生物医疗电子等等:其中,人脸辨识是一个很重要的部分,网络上已经有相当多的资源可供下载使用:于是我们使用舵机云台作为镜头旋转 ...

  2. Oracle同义词和序列

    同义词:是表.索引.视图的模式对象的一个别名,通过模式对象创建同意词,可以隐藏对象的实际名称和 所有者信息,为对象提供一定的安全性,开发应用程序时:应该尽量避免直接使用表,视图 或其他对象,改用对象的 ...

  3. Erlang/Elixir: 使用 OpenCV, Python 搭建图片缩略图服务器

    这篇文章是在OSX上测试和运行的的, Ubuntu下的安装和配置请移步到这里 应用程序进程树, 默认 Poolboy 中初始化10个用于处理图片的 Python 工作进程(Worker) 首先安装Op ...

  4. 冲刺ing-3

    第三次Scrum冲刺 队员完成的任务 队员 完成任务 吴伟华 分配任务,燃尽图 蔺皓雯 编写博客,美化主界面 蔡晨旸 美化主界面 曾茜 主页面设计 鲁婧楠 服务器建构 杨池宇 服务器建构 成员遇到的问 ...

  5. 404 Note Found 现场编程

    目录 组员职责分工 github 的提交日志截图 程序运行截图 程序运行环境 GUI界面 基础功能实现 运行视频 LCG算法 过滤(降权)算法 算法思路 红黑树 附加功能一 背景 实现 附加功能二(迭 ...

  6. hdu1010--Tempter of the Bone(迷宫)

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1010 Tempter of the Bone Time Limit: 2000/1000 MS (Jav ...

  7. WebSphere应用服务器内存泄漏探测与诊断工具选择最佳实践

    内存泄漏是比较常见的一种应用程序性能问题,一旦发生,则系统的可用内存和性能持续下降:最终将导致内存不足(OutOfMemory),系统彻底宕掉,不能响应任何请求,其危害相当严重.同时,Java堆(He ...

  8. MDL详解

    以下的虚拟内存可以理解成逻辑内存,因为我觉得只有这样才能讲通下面所有的东西.以下的“未分页”指没有为页进行编码. 以下为MDL结构体(我很郁闷,我在MSDN上没有找到这个结构体) typedef st ...

  9. IT就业·软件工程之我见

    随着计算机技术的飞速发展,让人们深切感受到科技让生活更美好的真正含义. 现如今我们的正常生活,社交都越来越离不开网络和终端,因特网和各种终端设备的组合让我们即使相距千里,也能面对面对话交流:购物,我们 ...

  10. PHP 多文件打包下载 zip

    <?php $zipname = './photo.zip'; //服务器根目录下有文件夹public,其中包含三个文件img1.jpg, img2.jpg, img3.jpg,将这三个文件打包 ...