前段时间将系统的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签名实现如下:

SM2签名

publicstaticBigInteger[] Sm2Sign(byte[] md, AsymmetricCipherKeyPair keypair)

...{

SM3Digest sm3=newSM3Digest();

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=newbyte[32];

sm3.DoFinal(hashData,0);

//eBigInteger e=newBigInteger(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=newbyte[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);

returnnewBigInteger[]...{ r, s };

}

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

SM2验签

publicstaticboolVerify(byte[] msg,byte[] signData,byte[] certData)

...{

X509Certificate2 x5092=newX509Certificate2(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=newBigInteger(strcertPKX,16);

BigInteger biY=newBigInteger(strcertPKY,16);

ECFieldElement x=newFpFieldElement(ecc_p, biX);

ECFieldElement y=newFpFieldElement(ecc_p, biY);

ECPoint userKey=newFpPoint(ecc_curve, x, y);

SM3Digest sm3=newSM3Digest();

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=newbyte[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=newBigInteger(strR,16);

BigInteger s=newBigInteger(strS,16);

//e_BigInteger e=newBigInteger(1, md);

//tBigInteger t=r.Add(s).Mod(ecc_n);

if(t.Equals(BigInteger.Zero))

returnfalse;

//x1y1ECPoint x1y1=ecc_point_g.Multiply(s);

x1y1=x1y1.Add(userKey.Multiply(t));

//RBigInteger R=e.Add(x1y1.X.ToBigInteger()).Mod(ecc_n);

returnr.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证书生成

publicstaticOrg.BouncyCastle.X509.X509Certificate MakeRootCert(stringfilePath, IDictionary subjectNames)

...{

AsymmetricCipherKeyPair keypair=SM2CryptoServiceProvider.SM2KeyPairGenerator.GenerateKeyPair();

ECPublicKeyParameters pubKey=(ECPublicKeyParameters)keypair.Public;//CA公钥ECPrivateKeyParameters priKey=(ECPrivateKeyParameters)keypair.Private;//CA私钥

X509Name issuerDN=newX509Name(GetDictionaryKeys(subjectNames), subjectNames);

X509Name subjectDN=issuerDN;//自签证书,两者一样 SM2X509V3CertificateGenerator sm2CertGen=newSM2X509V3CertificateGenerator();

//X509V3CertificateGenerator sm2CertGen = new X509V3CertificateGenerator();sm2CertGen.SetSerialNumber(newBigInteger(128,newRandom()));//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,newBasicConstraints(true));

sm2CertGen.AddExtension(X509Extensions.SubjectKeyIdentifier,false,newSubjectKeyIdentifierStructure(pubKey));

sm2CertGen.AddExtension(X509Extensions.AuthorityKeyIdentifier,false,newAuthorityKeyIdentifierStructure(pubKey));

sm2CertGen.AddExtension(X509Extensions.KeyUsage,true,newKeyUsage(6));

Org.BouncyCastle.X509.X509Certificate sm2Cert=sm2CertGen.Generate(keypair);

sm2Cert.CheckValidity();

sm2Cert.Verify(pubKey);

returnsm2Cert;

}

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

SM2证书公钥标识

usingSystem;

usingOrg.BouncyCastle.Asn1.X509;

usingOrg.BouncyCastle.Asn1;

namespaceCommon.Security

...{

publicclassSM2AlgorithmIdentifier

: AlgorithmIdentifier

...{

privatereadonlyboolparametersDefined;

publicSM2AlgorithmIdentifier(

DerObjectIdentifier objectID):base(objectID)

...{

}

publicSM2AlgorithmIdentifier(

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 }

*

*/publicoverrideAsn1Object ToAsn1Object()

...{

DerObjectIdentifier sm2Identifier=newDerObjectIdentifier("1.2.156.10197.1.301");

Asn1EncodableVector v=newAsn1EncodableVector(base.ObjectID, sm2Identifier);

returnnewDerSequence(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

国密算法java源码_国密算法SM2证书制作相关推荐

  1. 【老生谈算法】matlab实现画交通流密速关系源码——交通流密速

    用matlab画交通流密速关系 1.文档下载: 本算法已经整理成文档如下,有需要的朋友可以点击进行下载 序号 文档(点击下载) 本项目文档 [老生谈算法]matlab画交通流密速关系程序源码.doc ...

  2. 相册java源码_电子相册java源码

    电子相册java源码 import java.awt.*; import java.awt.FlowLayout; import java.awt.event.*; import javax.swin ...

  3. 药店java源码_基于jsp的药店-JavaEE实现药店 - java项目源码

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的药店, 该项目可用各类java课程设计大作业中, 药店的系统架构分为前后台两部分, 最终实现在线上进行药店各项功能 ...

  4. fama matlab源码_基于优化算法改造的Fama-French三因子模型

    基于光大证券金融工程研报<站在巨人的肩膀上,从牛基组合到牛股发现 --FOF 专题研究系列之十六 >中提及的Carhart四因子Alpha优化模型,本文在Fama-French三因子模型上 ...

  5. 防饿了么java源码_饿了么点餐源码、今日头条源码 等

    Android精选源码 Android优质博客 简评:优雅的运用 Kotlin 的 null safety 特性,而不要简单的直接用 !!.对于 Null 的检查是 Kotlin 的特点之一.强制你在 ...

  6. 二手商城java 源码_基于jsp的二手商城-JavaEE实现二手商城 - java项目源码

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的二手商城, 该项目可用各类java课程设计大作业中, 二手商城的系统架构分为前后台两部分, 最终实现在线上进行二手 ...

  7. 拼图java源码_拼图游戏Java版源代码JAVA游戏源码下载

    Java版的拼图游戏,玩家能够自己更换图片,只需你把它分成块,另外它是以成绩=1000-时间(秒)-移动步数*10来决意你是否输了,按F1键起头游戏,Y健预览图片. 拼图游戏Java版源代码 (1 f ...

  8. vim ctags java源码_如何使用vim的插件Ctags查看Linux源码

    一.ubuntu下安装Linux内核源码 (1).查看自己的内核版本 (2).查看源内的内核源码类表 (3).下载源码 (4).进入/usr/src (5).解压下载的文件到用户主 二.安装vim插件 ...

  9. 跳一跳改分java源码_解密微信小程序漏洞:可下载任意小游戏源代码,“跳一跳”可改分...

    原标题:解密微信小程序漏洞:可下载任意小游戏源代码,"跳一跳"可改分 雷锋网消息,据 IT 之家 1 月 2 日消息称,"跳一跳"居然可以利用漏洞自己改分数,甚 ...

最新文章

  1. 浅谈身为小白学习Linux系统的四点实用建议
  2. 笔记-知识产权与标准化知识-计算机软件可靠性和可维护性管理的评审要求
  3. 利用geogle中memory工具分析js占用内存
  4. 二叉树输出(信息学奥赛一本通-T1366)
  5. myPassword
  6. 力扣-876 链表的中间结点
  7. Python基础练习-002-求1000以内的完全数
  8. 电子技术基础资料合集
  9. mysql实现用拼音搜索中文的数据库实现
  10. Firefox 浏览器更新以后出现书签丢失
  11. 让人舒心就是领导力和内在激励
  12. 2023年西南交通大学马克思主义理论考研上岸前辈备考经验
  13. 996的大公司和965的小公司,你怎么选?
  14. 实战案例,手把手教你使用 Tableau 绘制超炫酷可视化图表
  15. 用html5做课件,涨姿势┃一分钟PPT轻松转化H5,让“课件”动起来
  16. 2022年上海医院三基考试仿真试题(含答案)
  17. 到底哪些事情属于测试人员的职责?
  18. 高德地图图片叠加层示例方法的缺点
  19. TFS2010-团队项目--(TF250044,TF218027) 权限不足问题解决方案
  20. 【波形库】对比和分析波形的在线平台

热门文章

  1. 慕课离线下载视频支持电脑播放
  2. 一张图看懂项目管理的47个过程(干货)
  3. 微信朋友圈自动刷评论
  4. 【牛客刷题专栏】0x27:JZ29 顺时针打印矩阵(C语言编程题)
  5. python3数据库MongoDB的全面安装教程
  6. “春节档”游戏运营核心方法论
  7. 登录页面ajax提交
  8. 微信小程序如何使用Git实现版本管理
  9. Tessent专栏第五篇:TessentMemoryBIST用户手册第二章下
  10. 慕课网_《Java实现邮箱验证》学习总结