SM2加解密java语言

maven项目 引入bcprov-jdk15on

     <dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.65</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>

代码如下

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 1. @description: 钥匙对* 2. @author: xh* 3. @time: 2022/3/18*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SMKeyPair {//私钥private String priKey;//公钥private String pubKey;}
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.CryptoException;
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.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;/*** 1. @description: SM2工具类* 2. @author: xh* 3. @time: 2022/3/18*/
@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 SMKeyPair genKeyPair() {return genKeyPair(true);}/*** 生成公私钥对* @param compressedPubKey  是否压缩公钥* @return*/public static SMKeyPair genKeyPair(boolean compressedPubKey) {AsymmetricCipherKeyPair asymmetricCipherKeyPair = genKeyPair0();//提取公钥点ECPoint ecPoint = ((ECPublicKeyParameters) asymmetricCipherKeyPair.getPublic()).getQ();//公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥,04的时候,可以去掉前面的04String pubKey = Hex.toHexString(ecPoint.getEncoded(compressedPubKey));BigInteger privatekey = ((ECPrivateKeyParameters) asymmetricCipherKeyPair.getPrivate()).getD();String priKey = privatekey.toString(16);SMKeyPair keyPair = new SMKeyPair(priKey, pubKey);return keyPair;}/*** 私钥签名* @param privateKey    私钥* @param content       待签名内容* @return*/public static String sign(String privateKey, String content) throws CryptoException {//待签名内容转为字节数组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默认值:1234567812345678try {sm2Signer.init(true, new ParametersWithID(new ParametersWithRandom(privateKeyParameters, SecureRandom.getInstance("SHA1PRNG")), Strings.toByteArray("1234567812345678")));} catch (NoSuchAlgorithmException e) {log.error("签名时出现异常:", e);}sm2Signer.update(message, 0, message.length);//生成签名,签名分为两部分r和s,分别对应索引0和1的数组byte[] signBytes = sm2Signer.generateSignature();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(Hex.decode(publicKey));// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04ECPublicKeyParameters publicKeyParameters = new ECPublicKeyParameters(pukPoint, domainParameters);//创建签名实例SM2Signer sm2Signer = new SM2Signer();ParametersWithID parametersWithID = new ParametersWithID(publicKeyParameters, Strings.toByteArray("1234567812345678"));sm2Signer.init(false, parametersWithID);sm2Signer.update(message, 0, message.length);//验证签名结果boolean verify = sm2Signer.verifySignature(signData);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(Hex.decode(publicKey));// 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04ECPublicKeyParameters 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;}/*** 将未压缩公钥压缩成压缩公钥* 公钥前面的02或者03表示是压缩公钥,04表示未压缩公钥, 04的时候,可以去掉前面的04* @param pubKey    未压缩公钥(16进制,不要带头部04)* @return*/public static String compressPubKey(String pubKey) {pubKey = "04" + pubKey;    //将未压缩公钥加上未压缩标识.// 获取一条SM2曲线参数X9ECParameters sm2ECParameters = GMNamedCurves.getByName("sm2p256v1");//提取公钥点ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(pubKey));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");//提取公钥点ECPoint pukPoint = sm2ECParameters.getCurve().decodePoint(Hex.decode(compressKey));String pubKey = Hex.toHexString(pukPoint.getEncoded(Boolean.FALSE));//去掉前面的04   (04的时候,可以去掉前面的04)pubKey = pubKey.substring(2);return pubKey;}public static void main(String[] args) {SMKeyPair smKeyPair = genKeyPair(false);String priKey = smKeyPair.getPriKey();System.out.println("私钥"+ priKey);String pubKey = smKeyPair.getPubKey();System.out.println("公钥"+ pubKey);//公钥解压缩String substring = pubKey.substring(2, pubKey.length());String s = compressPubKey(substring);System.out.println("压缩后" + s);String s1 = unCompressPubKey(s);System.out.println("解压后" + s1);//明文String text = "123123123";System.out.println("测试明文文本" + text);//签名验签测试String sign = "";try {sign = sign(priKey, Hex.toHexString(text.getBytes()));} catch (CryptoException e) {e.printStackTrace();}System.out.println("生成签名" + sign);boolean verify = verify(pubKey, Hex.toHexString(text.getBytes()), sign);System.out.println("验签结果" + verify);//加解密测试String encryptData = encrypt(pubKey, text);System.out.println("加密结果" + encryptData);String decryptData = decrypt(priKey, encryptData);System.out.println("解密结果" + decryptData);}
}

国密算法SM2加解密,签名和验签java语言相关推荐

  1. 国密算法SM2加解密_签名验签图形化例子

    点击上方蓝字可直接关注!方便下次阅读.如果对你有帮助,麻烦点个在看或点个赞,感谢~ 国密SM2概述 对国密算法有了解的朋友看到SM2可能会先想到非对称加密,之前的SM4是对称加密.SM4加解密使用的是 ...

  2. 国密算法SM2加解密数据,解密出现异常

    参考开源项目:https://github.com/ZZMarquis/gmhelper 旧标准的加密排序C!C2C3 新标准 C!C3C2 C1为65字节第1字节为压缩标识,这里固定为0x04,后面 ...

  3. c++国密算法SM2加密解密demo

    c++国密算法SM2加密解密 一.代码 一.代码 封装加密.解密接口: 加密接口: Encrpt_SM2() 解密接口:Decrypt_SM2() 加密解密结果可以和nodejs的模块sm-crypt ...

  4. 国密算法-SM4加解密工具类

    import cn.hutool.crypto.symmetric.SymmetricCrypto;/*** @author : chenfan* @className : SM4Utils* @da ...

  5. 国密算法SM2加密解密

    一.依赖包 <!-- hutool的 SM2 加密--><dependency><groupId>org.bouncycastle</groupId>& ...

  6. 国家医保移动支付国密算法SM2签名验签、SM4加解密DLL

    国家医保移动支付国密算法SM2签名验签.SM4加解密DLL 支持医保移动支付(国家统一版), 已知省份有广西.贵州.安徽.河北.黑龙江.湖南.吉林.江苏.四川.新疆等各地方. DLL,非.net开发, ...

  7. 国密算法—SM2介绍及基于BC的实现

    国密算法-SM2介绍及基于BC的实现 文章目录 国密算法-SM2介绍及基于BC的实现 简介 私钥 公钥 数据格式 密钥数据格式 私钥数据格式 公钥数据格式 加密数据格式 签名数据格式 计算过程 生成密 ...

  8. 国密算法SM2证书制作

    原文链接:http://www.jonllen.com/jonllen/work/162.aspx 国密算法SM2证书制作 分类:工作 大中小 前段时间将系统的RSA算法全部升级为SM2国密算法,密码 ...

  9. 国密算法 SM2公钥密码 SM3杂凑算法 SM4分组密码 python代码完整实现

    包含SM2公钥密码.SM3杂凑算法和SM4分组密码的国密算法完整工具包完成了.此前分别发布过上述三个算法的代码: SM2:国密算法 SM2 公钥加密 非对称加密 数字签名 密钥协商 python实现完 ...

最新文章

  1. TensorFlow文本摘要生成 - 基于注意力的序列到序列模型
  2. 「每周CV论文」深度学习图像降噪应该阅读哪些文章
  3. mysql密码修改脚本
  4. ButterKnife与RxBinding中文件重复问题解决
  5. MySQL中用decimal的原因
  6. 无法读取源文件或磁盘_禁用格式化磁盘操作 保护电脑文件安全防止删除
  7. 获取项目根路径,并在其下创建一个名称为userData 的目录。
  8. 关于区块链的一些思绪
  9. 批处理-延迟环境变量扩展
  10. 虐哭无数人的烧脑刑侦科推理题,程序员一秒解
  11. c语言蜂鸣字符,蜂鸣器原理
  12. 蒙德里安的梦想 状态压缩DP (1)
  13. 申请永久免费空间、数据库空间、域名
  14. 如何快速去除图片上的水印
  15. 通过微信开发测试号进行微信登录
  16. Android简单的天气预报
  17. MySQL性能指标TPS+QPS+IOPS压测
  18. openamp RPU-APU双核间通信 建立多个通道
  19. 百度网盘不限速下载每秒6兆左右之Proxyee Down3.x安装到使用
  20. Advanced Installer 制作带升级功能的安装包

热门文章

  1. LINUX 9 ASDL 连接
  2. tbc怀旧服服务器位置,关于《魔兽世界》TBC怀旧服,来看看官方问答汇总吧
  3. Intel E810 Advanced RSS介绍
  4. JTAG原理+JTAG烧写FPGA配置芯片
  5. 取消windowsXP桌面图标下的蓝色阴影
  6. 太阳光是平行光吗_从科学角度解释,为什么太阳光不是平行的?用铁路作比较就明白了...
  7. 快救命...老板要杀人了
  8. 《人人都是产品经理》读书笔记 Part 2
  9. 中国移动M2M终端规范——WMMP协议分册
  10. layui使用富文本已经使用第三方插件Kz.layedit来优化layui的富文本