原文地址:Fight With Me!!!

制作SM2证书

前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密算法DES(AES)和摘要MD5(SHA1)也相应改变,分别对应SM1、SM3算法,SM1算法基于硬件实现,SM2、SM3算法已公开。

SM2签名验证算法

SM2签名同样也是需要先摘要原文数据,即先使用SM3密码杂凑算法计算出32byte摘要。SM3需要摘要签名方ID(默认1234567812345678)、曲线参数a,b,Gx,Gy、共钥坐标(x,y)计算出Z值,然后再杂凑原文得出摘要数据。这个地方要注意曲线参数和坐标点都是32byte,在转换为BigInteger大数计算转成字节流时要去掉空补位,否则可能会出现摘要计算不正确的问题。SM2签名实现如下:

public static BigInteger[] Sm2Sign(byte[] md, AsymmetricCipherKeyPair keypair)
{SM3Digest sm3 = new SM3Digest();ECPublicKeyParameters ecpub = (ECPublicKeyParameters)keypair.Public;byte[] z = SM2CryptoServiceProvider.Sm2GetZ(Encoding.Default.GetBytes(SM2CryptoServiceProvider.userId), ecpub.Q);sm3.BlockUpdate(z, 0, z.Length);byte[] p = md;sm3.BlockUpdate(p, 0, p.Length);byte[] hashData = new byte[32];sm3.DoFinal(hashData, 0);// eBigInteger e = new BigInteger(1, hashData);// kBigInteger k = null;ECPoint kp = null;BigInteger r = null;BigInteger s = null;BigInteger userD = null;do{do{ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)keypair.Private;k = ecpriv.D;kp = ecpub.Q;userD = ecpriv.D;// rr = e.Add(kp.X.ToBigInteger());r = r.Mod(ecc_n);}while (r.Equals(BigInteger.Zero) || r.Add(k).Equals(ecc_n));// (1 + dA)~-1BigInteger da_1 = userD.Add(BigInteger.One);da_1 = da_1.ModInverse(ecc_n);// ss = r.Multiply(userD);s = k.Subtract(s).Mod(ecc_n);s = da_1.Multiply(s).Mod(ecc_n);}while (s.Equals(BigInteger.Zero));byte[] btRS = new byte[64];byte[] btR = r.ToByteArray();byte[] btS = s.ToByteArray();Array.Copy(btR, btR.Length - 32, btRS, 0, 32);Array.Copy(btS, btS.Length - 32, btRS, 32, 32);return new BigInteger[] { r, s };
}

SM2算法是基于ECC算法的,签名同样返回2个大数,共64byte。由于原来RSA算法已很普遍支持,要实现RSA的签名验签都有标准库的实现,而SM2是国密算法在国际上还没有标准通用,算法Oid标识在X509标准中是没定义的。在.Net或Java中可以基于使用BouncyCastle加密库实现,开源的也比较好学习扩展。SM2算法验签可以使用软验签,即可以不需要使用硬件设备,同样使用原始数据、签名、证书(公钥)来实现对签名方验证,保证数据完整性未被篡改。验证过程同样需先摘要原文数据,公钥在证书中是以一个66byte的BitString,去掉前面标记位即64byte为共钥坐标(x,y),中间分割截取再以Hex方式转成BigInteger大数计算,验签代码如下:

public static bool Verify(byte[] msg, byte[] signData, byte[] certData)
{X509Certificate2 x5092 = new X509Certificate2(certData);byte[] certPK = x5092.GetPublicKey();certPK = SubByte(certPK, 1, 64);byte[] certPKX = SubByte(certPK, certPK.Length - 32 - 32, 32);byte[] certPKY = SubByte(certPK, certPK.Length - 32, 32);System.String strcertPKX = ByteToHexStr(certPKX);System.String strcertPKY = ByteToHexStr(certPKY);BigInteger biX = new BigInteger(strcertPKX, 16);BigInteger biY = new BigInteger(strcertPKY, 16);ECFieldElement x = new FpFieldElement(ecc_p, biX);ECFieldElement y = new FpFieldElement(ecc_p, biY);ECPoint userKey = new FpPoint(ecc_curve, x, y);SM3Digest sm3 = new SM3Digest();byte[] z = Sm2GetZ(Encoding.Default.GetBytes(userId), userKey);sm3.BlockUpdate(z, 0, z.Length);byte[] p = msg;sm3.BlockUpdate(p, 0, p.Length);byte[] md = new byte[32];sm3.DoFinal(md, 0);byte[] btR = SubByte(signData, 0, 32);byte[] btS = SubByte(signData, 32, 32);System.String strR = ByteToHexStr(btR);System.String strS = ByteToHexStr(btS);BigInteger r = new BigInteger(strR, 16);BigInteger s = new BigInteger(strS, 16);// e_BigInteger e = new BigInteger(1, md);// tBigInteger t = r.Add(s).Mod(ecc_n);if (t.Equals(BigInteger.Zero))return false;// x1y1ECPoint x1y1 = ecc_point_g.Multiply(s);x1y1 = x1y1.Add(userKey.Multiply(t));// RBigInteger R = e.Add(x1y1.X.ToBigInteger()).Mod(ecc_n);return r.Equals(R);
}

制作SM2证书

基于BouncyCastle开源库,可以轻松制作X509证书、CRL、pkcs10、pkcs12,支持国际通用的RSA、ECC算法。制作SM2证书可以通过扩展BouncyCastle库来实现,需加入SM2签名算法DerObjectIdentifier标识1.2.156.10197.1.501(基于SM3的SM2算法签名),密钥对的生成使用国密推荐曲线参数,然后如上所示自行实现SM2签名验证算法。X509证书由证书主体、证书签名算法标识、签名组成,和RSA证书主要不同的是SM2证书的签名算法标识和签名,及证书公钥使用ECKeyParameters。生成自签名SM2证书代码如下:

SM2证书生成:

public static Org.BouncyCastle.X509.X509Certificate MakeRootCert(string filePath, IDictionary subjectNames)
{AsymmetricCipherKeyPair keypair = SM2CryptoServiceProvider.SM2KeyPairGenerator.GenerateKeyPair();ECPublicKeyParameters pubKey = (ECPublicKeyParameters)keypair.Public; //CA公钥   ECPrivateKeyParameters priKey = (ECPrivateKeyParameters)keypair.Private;    //CA私钥   X509Name issuerDN = new X509Name(GetDictionaryKeys(subjectNames), subjectNames);X509Name subjectDN = issuerDN;  //自签证书,两者一样SM2X509V3CertificateGenerator sm2CertGen = new SM2X509V3CertificateGenerator();//X509V3CertificateGenerator sm2CertGen = new X509V3CertificateGenerator();sm2CertGen.SetSerialNumber(new BigInteger(128, new Random()));   //128位   sm2CertGen.SetIssuerDN(issuerDN);sm2CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-1));sm2CertGen.SetNotAfter(DateTime.UtcNow.AddDays(365 * 10));sm2CertGen.SetSubjectDN(subjectDN);sm2CertGen.SetPublicKey(pubKey); //公钥sm2CertGen.SetSignatureAlgorithm("SM3WITHSM2");sm2CertGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));sm2CertGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(pubKey));sm2CertGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pubKey));sm2CertGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(6));Org.BouncyCastle.X509.X509Certificate sm2Cert = sm2CertGen.Generate(keypair);sm2Cert.CheckValidity();sm2Cert.Verify(pubKey);return sm2Cert;
}

X509证书使用ASN1语法进行编码,是用类型标识、长度和值序列来描述数据结构的。SM2证书在制作设置公钥时,默认会带ECKeyParameters参数,并没有SM2的公钥参数1.2.156.10197.1.301,因此需要自己写个SM2椭圆曲线密码算法标识对象,这样在生成的证书中就可以看到公钥参数字段,如下所示:

SM2证书公钥标识

using System;using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Asn1;namespace Common.Security
{public class SM2AlgorithmIdentifier: AlgorithmIdentifier{private readonly bool parametersDefined;public SM2AlgorithmIdentifier(DerObjectIdentifier objectID):base(objectID){}public SM2AlgorithmIdentifier(DerObjectIdentifier    objectID,Asn1Encodable parameters): base(objectID, parameters){this.parametersDefined = true;}/*** Produce an object suitable for an Asn1OutputStream.*          *      AlgorithmIdentifier ::= Sequence {*                            algorithm OBJECT IDENTIFIER,*                            parameters ANY DEFINED BY algorithm OPTIONAL }* */public override Asn1Object ToAsn1Object(){DerObjectIdentifier sm2Identifier = new DerObjectIdentifier("1.2.156.10197.1.301");Asn1EncodableVector v = new Asn1EncodableVector(base.ObjectID, sm2Identifier);return new DerSequence(v);          }     }
}

SM2算法是国密局公布的公钥密码算法,在相当强度下密钥比RSA短,在使用智能卡有限空间存储时非常可贵。目前国内很多CA大都升级支持SM2算法证书,相信以后会慢慢地推广更多应用,也期望之后能与国际标准接轨。

附:

国密推荐256位曲线参数

  • p=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
  • a=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC
  • b=28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93
  • n=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123
  • Gx=32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7
  • Gy=BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0

SM2国密算法测试示例

java制作SM2证书相关推荐

  1. java生成sm2证书_(转载)Java使用IText实现PDF签章

    前文讲到了如何使用Adobe的PDF工具软件进行电子印章应用.在实际应用中还有一种情形就是需要将电子印章功能集成在我们开发的系统里,这里就要用到一些PDF的二次开发库了.做过相关开发的同学应该知道常用 ...

  2. ec java sm2证书_国密算法SM2证书制作

    前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密 ...

  3. 国密算法java源码_国密算法SM2证书制作

    前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密 ...

  4. 国密算法SM2证书制作

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

  5. Windows gmssl生成SM2证书 + java bc库签名验签

    Windows gmssl生成SM2证书 + java bc库签名验签 openssl生成SM2证书 1 生成密钥 gmssl ecparam -genkey -name sm2p256v1 -tex ...

  6. ec java sm2证书_SM2国密证书合法性验证

    通常我们遇到过的X509证书都是基于RSA-SHA1算法的,目前国家在大力推行国密算法,未来银行发行的IC卡也都是基于PBOC3.0支持国密算法的,因此我们来学习一下如何验证SM2国密证书的合法性.至 ...

  7. 【SM2证书】签发SM2根证书 (精简、直接)

    0.程序员专用开头: 1.项目结构: 2. 源码: AlgSm2Demo.java  (签名验签) package alg.sm2demo;import org.bouncycastle.jcajce ...

  8. java usbkey数字证书_Java创建数字证书

    BouncyCastle下载: 链接:http://pan.baidu.com/s/1vrcL4    密码:6i27 package com.what21.security05; import ja ...

  9. Tomcat—HTTPS之制作安全证书与浏览器端安全证书的安装

    在博客<终结者:HTTPS在Tomcat中的使用(一)--生成证书与配置Tomcat服务器>中介绍了如何生成服务器端证书和配置Tomcat服务器,本篇博客将带着大家一起研究如何生成浏览器端 ...

最新文章

  1. 教你一招超级简单的方法快速搞定grub.conf文件的丢失及损坏
  2. activiti源码编译
  3. Apache Commons 工具集使用简介
  4. 封装、继承、多态的理解
  5. 用于大型事件处理的Akka Java
  6. java查找网站在百度排名_百度网站快排系统 - 网站排名如何优化?
  7. c++ map初始化_Java多线程 未完成初始化--构造方法中新建线程
  8. 搜索引擎设计实用教程(1)-以百度为例 之一:查询处理以及分词技术
  9. 4.3-软件开发中,“原型图”的作用与绘制方法说明
  10. Spring Boot应用在kubernetes的sidecar设计与实战,mysql分表分库技术实现
  11. Rsoft光波导软件基于七芯光纤波导耦合器模拟
  12. od机考题目-机器人走迷宫
  13. c语言泰勒公式求ln,ln(1-x)的泰勒级数展开是什么?
  14. CMD下添加IP地址,删除IP地址
  15. 猫眼电影票房爬取到MySQL中_爬虫之爬取猫眼电影专业版实时数据排行榜
  16. 系统CPU负载过高、CPU使用率不高的问题
  17. 互融云借条APP系统开发 六大系统优势全面保障
  18. 关于报表以及finereport报表软软件
  19. TMDSEVM6657LS评估板恢复出厂默认状态
  20. 安卓手机端网页,开启输入法时页面内容被压缩的解决方法

热门文章

  1. 影响谷歌排名的10个重要因素【重点关注】
  2. 计算机网络 P2P应用
  3. freebsd java 能用吗_FreeBSD6.2 java web环境搭建
  4. 未来十年,互联网将如何颠覆17个传统行业
  5. 9.10 安卓常用工具类之一 定位-----LocationUtils
  6. 高性能日志:如何提升日志性能避免 IO 瓶颈?
  7. 《黑客秘笈——渗透测试实用指南》—第1章1.1节搭建渗透测试主机
  8. FPV入坑前传(20211227)(未完)
  9. 李白号称诗仙,为何七律连有些二流诗人都敌不过?
  10. 英文年月日(日期)怎么读?