热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

国密算法SM2证书制作

国密算法sm2非对称算法椭圆曲线原文:http:www.jonllen.cnjonllenwork162.aspx前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKe
国密算法sm2非对称算法椭圆曲线

原文:http://www.jonllen.cn/jonllen/work/162.aspx

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

[java] view plaincopy
 
  1. public static BigInteger[] Sm2Sign(byte[] md, AsymmetricCipherKeyPair keypair)  
  2. {  
  3.             SM3Digest sm3 = new SM3Digest();  
  4.   
  5.             ECPublicKeyParameters ecpub = (ECPublicKeyParameters)keypair.Public;  
  6.   
  7.             byte[] z = SM2CryptoServiceProvider.Sm2GetZ(Encoding.Default.GetBytes(SM2CryptoServiceProvider.userId), ecpub.Q);  
  8.             sm3.BlockUpdate(z, 0, z.Length);  
  9.   
  10.             byte[] p = md;  
  11.             sm3.BlockUpdate(p, 0, p.Length);  
  12.   
  13.             byte[] hashData = new byte[32];  
  14.             sm3.DoFinal(hashData, 0);  
  15.   
  16.             // e  
  17.             BigInteger e = new BigInteger(1, hashData);  
  18.             // k  
  19.             BigInteger k = null;  
  20.             ECPoint kp = null;  
  21.             BigInteger r = null;  
  22.             BigInteger s = null;  
  23.             BigInteger userD = null;  
  24.   
  25.             do  
  26.             {  
  27.                 do  
  28.                 {  
  29.   
  30.                     ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)keypair.Private;  
  31.                     k = ecpriv.D;  
  32.                     kp = ecpub.Q;  
  33.   
  34.                     userD = ecpriv.D;  
  35.   
  36.                     // r  
  37.                     r = e.Add(kp.X.ToBigInteger());  
  38.                     r = r.Mod(ecc_n);  
  39.                 }  
  40.                 while (r.Equals(BigInteger.Zero) || r.Add(k).Equals(ecc_n));  
  41.   
  42.                 // (1 + dA)~-1  
  43.                 BigInteger da_1 = userD.Add(BigInteger.One);  
  44.                 da_1 = da_1.ModInverse(ecc_n);  
  45.                 // s  
  46.                 s = r.Multiply(userD);  
  47.                 s = k.Subtract(s).Mod(ecc_n);  
  48.                 s = da_1.Multiply(s).Mod(ecc_n);  
  49.             }  
  50.             while (s.Equals(BigInteger.Zero));  
  51.   
  52.             byte[] btRS = new byte[64];  
  53.             byte[] btR = r.ToByteArray();  
  54.             byte[] btS = s.ToByteArray();  
  55.             Array.Copy(btR, btR.Length - 32, btRS, 0, 32);  
  56.             Array.Copy(btS, btS.Length - 32, btRS, 32, 32);  
  57.   
  58.             return new BigInteger[] { r, s };  
  59. }  

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

[java] view plaincopy
 
  1. public static bool Verify(byte[] msg, byte[] signData, byte[] certData)  
  2. {  
  3.   
  4.             X509Certificate2 x5092 = new X509Certificate2(certData);  
  5.             byte[] certPK = x5092.GetPublicKey();  
  6.   
  7.             certPK = SubByte(certPK, 1, 64);  
  8.   
  9.             byte[] certPKX = SubByte(certPK, certPK.Length - 32 - 32, 32);  
  10.             byte[] certPKY = SubByte(certPK, certPK.Length - 32, 32);  
  11.   
  12.   
  13.             System.String strcertPKX = ByteToHexStr(certPKX);  
  14.             System.String strcertPKY = ByteToHexStr(certPKY);  
  15.             BigInteger biX = new BigInteger(strcertPKX, 16);  
  16.             BigInteger biY = new BigInteger(strcertPKY, 16);  
  17.   
  18.   
  19.             ECFieldElement x = new FpFieldElement(ecc_p, biX);  
  20.             ECFieldElement y = new FpFieldElement(ecc_p, biY);  
  21.   
  22.             ECPoint userKey = new FpPoint(ecc_curve, x, y);  
  23.   
  24.   
  25.             SM3Digest sm3 = new SM3Digest();  
  26.             byte[] z = Sm2GetZ(Encoding.Default.GetBytes(userId), userKey);  
  27.             sm3.BlockUpdate(z, 0, z.Length);  
  28.   
  29.   
  30.             byte[] p = msg;  
  31.             sm3.BlockUpdate(p, 0, p.Length);  
  32.   
  33.             byte[] md = new byte[32];  
  34.             sm3.DoFinal(md, 0);  
  35.   
  36.   
  37.             byte[] btR = SubByte(signData, 0, 32);  
  38.             byte[] btS = SubByte(signData, 32, 32);  
  39.   
  40.   
  41.             System.String strR = ByteToHexStr(btR);  
  42.             System.String strS = ByteToHexStr(btS);  
  43.             BigInteger r = new BigInteger(strR, 16);  
  44.             BigInteger s = new BigInteger(strS, 16);  
  45.   
  46.             // e_  
  47.             BigInteger e = new BigInteger(1, md);  
  48.             // t  
  49.             BigInteger t = r.Add(s).Mod(ecc_n);  
  50.   
  51.             if (t.Equals(BigInteger.Zero))  
  52.                 return false;  
  53.   
  54.             // x1y1  
  55.             ECPoint x1y1 = ecc_point_g.Multiply(s);  
  56.             x1y1 = x1y1.Add(userKey.Multiply(t));  
  57.   
  58.             // R  
  59.             BigInteger R = e.Add(x1y1.X.ToBigInteger()).Mod(ecc_n);  
  60.   
  61.             return r.Equals(R);  
  62. }  

制作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证书生成
[java] view plaincopy
 
  1. public static Org.BouncyCastle.X509.X509Certificate MakeRootCert(string filePath, IDictionary subjectNames)  
  2. {  
  3.         AsymmetricCipherKeyPair keypair = SM2CryptoServiceProvider.SM2KeyPairGenerator.GenerateKeyPair();  
  4.         ECPublicKeyParameters pubKey = (ECPublicKeyParameters)keypair.Public; //CA公钥     
  5.         ECPrivateKeyParameters priKey = (ECPrivateKeyParameters)keypair.Private;    //CA私钥     
  6.   
  7.   
  8.   
  9.         X509Name issuerDN = new X509Name(GetDictionaryKeys(subjectNames), subjectNames);  
  10.         X509Name subjectDN = issuerDN;  //自签证书,两者一样  
  11.   
  12.         SM2X509V3CertificateGenerator sm2CertGen = new SM2X509V3CertificateGenerator();  
  13.         //X509V3CertificateGenerator sm2CertGen = new X509V3CertificateGenerator();  
  14.         sm2CertGen.SetSerialNumber(new BigInteger(128, new Random()));   //128位     
  15.         sm2CertGen.SetIssuerDN(issuerDN);  
  16.         sm2CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-1));  
  17.         sm2CertGen.SetNotAfter(DateTime.UtcNow.AddDays(365 * 10));  
  18.         sm2CertGen.SetSubjectDN(subjectDN);  
  19.         sm2CertGen.SetPublicKey(pubKey); //公钥  
  20.   
  21.   
  22.         sm2CertGen.SetSignatureAlgorithm("SM3WITHSM2");  
  23.   
  24.         sm2CertGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));  
  25.         sm2CertGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(pubKey));  
  26.         sm2CertGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pubKey));  
  27.         sm2CertGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(6));  
  28.   
  29.   
  30.         Org.BouncyCastle.X509.X509Certificate sm2Cert = sm2CertGen.Generate(keypair);  
  31.   
  32.         sm2Cert.CheckValidity();  
  33.         sm2Cert.Verify(pubKey);  
  34.   
  35.         return sm2Cert;  
  36. }  


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

,SM2证书公钥标识
[java] view plaincopy
 
  1. using System;  
  2.   
  3. using Org.BouncyCastle.Asn1.X509;  
  4. using Org.BouncyCastle.Asn1;  
  5.   
  6.   
  7. namespace Common.Security  
  8. {  
  9.     public class SM2AlgorithmIdentifier  
  10.         : AlgorithmIdentifier  
  11.     {  
  12.   
  13.         private readonly bool parametersDefined;  
  14.   
  15.     public SM2AlgorithmIdentifier(  
  16.             DerObjectIdentifier objectID):base(objectID)  
  17.         {  
  18.   
  19.         }  
  20.   
  21.   
  22.     public SM2AlgorithmIdentifier(  
  23.             DerObjectIdentifier    objectID,  
  24.             Asn1Encodable parameters)  
  25.             : base(objectID, parameters)  
  26.         {  
  27.             this.parametersDefined = true;  
  28.         }  
  29.   
  30.     /** 
  31.          * Produce an object suitable for an Asn1OutputStream. 
  32.          *          *      AlgorithmIdentifier ::= Sequence { 
  33.          *                            algorithm OBJECT IDENTIFIER, 
  34.          *                            parameters ANY DEFINED BY algorithm OPTIONAL } 
  35.          *  
  36.     */  
  37.           public override Asn1Object ToAsn1Object()  
  38.           {  
  39.              DerObjectIdentifier sm2Identifier = new DerObjectIdentifier("1.2.156.10197.1.301");  
  40.              Asn1EncodableVector v = new Asn1EncodableVector(base.ObjectID, sm2Identifier);  
  41.              return new DerSequence(v);            
  42.           }       
  43.   
  44.       }   
  45. }  


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证书制作


推荐阅读
  • 本文详细介绍了如何解决DNS服务器配置转发无法解析的问题,包括编辑主配置文件和重启域名服务的具体步骤。 ... [详细]
  • importpymysql#一、直接连接mysql数据库'''coonpymysql.connect(host'192.168.*.*',u ... [详细]
  • 微软推出Windows Terminal Preview v0.10
    微软近期发布了Windows Terminal Preview v0.10,用户可以在微软商店或GitHub上获取这一更新。该版本在2月份发布的v0.9基础上,新增了鼠标输入和复制Pane等功能。 ... [详细]
  • MySQL 5.7 学习指南:SQLyog 中的主键、列属性和数据类型
    本文介绍了 MySQL 5.7 中主键(Primary Key)和自增(Auto-Increment)的概念,以及如何在 SQLyog 中设置这些属性。同时,还探讨了数据类型的分类和选择,以及列属性的设置方法。 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • php更新数据库字段的函数是,php更新数据库字段的函数是 ... [详细]
  • 第二十五天接口、多态
    1.java是面向对象的语言。设计模式:接口接口类是从java里衍生出来的,不是python原生支持的主要用于继承里多继承抽象类是python原生支持的主要用于继承里的单继承但是接 ... [详细]
  • 解决Parallels Desktop错误15265的方法
    本文详细介绍了在使用Parallels Desktop时遇到错误15265的多种解决方案,包括检查网络连接、关闭代理服务器和修改主机文件等步骤。 ... [详细]
  • 解决 Windows Server 2016 网络连接问题
    本文详细介绍了如何解决 Windows Server 2016 在使用无线网络 (WLAN) 和有线网络 (以太网) 时遇到的连接问题。包括添加必要的功能和安装正确的驱动程序。 ... [详细]
  • ZooKeeper 入门指南
    本文将详细介绍ZooKeeper的工作机制、特点、数据结构以及常见的应用场景,包括统一命名服务、统一配置管理、统一集群管理、服务器动态上下线和软负载均衡。 ... [详细]
  • 自动验证时页面显示问题的解决方法
    在使用自动验证功能时,页面未能正确显示错误信息。通过使用 `dump($info->getError())` 可以帮助诊断和解决问题。 ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本文详细介绍了如何利用Duilib界面库开发窗体动画效果,包括基本思路和技术细节。这些方法不仅适用于Duilib,还可以扩展到其他类似的界面开发工具。 ... [详细]
  • 大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式
    大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式 ... [详细]
  • 如何将TS文件转换为M3U8直播流:HLS与M3U8格式详解
    在视频传输领域,MP4虽然常见,但在直播场景中直接使用MP4格式存在诸多问题。例如,MP4文件的头部信息(如ftyp、moov)较大,导致初始加载时间较长,影响用户体验。相比之下,HLS(HTTP Live Streaming)协议及其M3U8格式更具优势。HLS通过将视频切分成多个小片段,并生成一个M3U8播放列表文件,实现低延迟和高稳定性。本文详细介绍了如何将TS文件转换为M3U8直播流,包括技术原理和具体操作步骤,帮助读者更好地理解和应用这一技术。 ... [详细]
author-avatar
张馨桐等你2502895757
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有