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

article/2025/8/21 11:56:31

前段时间将系统的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);

// e

BigInteger e = new BigInteger(1, hashData);

// k

BigInteger 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;

// r

r = e.Add(kp.X.ToBigInteger());

r = r.Mod(ecc_n);

}

while (r.Equals(BigInteger.Zero) || r.Add(k).Equals(ecc_n));

// (1 + dA)~-1

BigInteger da_1 = userD.Add(BigInteger.One);

da_1 = da_1.ModInverse(ecc_n);

// s

s = 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);

// t

BigInteger t = r.Add(s).Mod(ecc_n);

if (t.Equals(BigInteger.Zero))

return false;

// x1y1

ECPoint x1y1 = ecc_point_g.Multiply(s);

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

// R

BigInteger 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证书代码如下:

6489eebeebb152d8cd2e43a63130c000.gifSM2证书生成

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椭圆曲线密码算法标识对象,这样在生成的证书中就可以看到公钥参数字段,如下所示:

6489eebeebb152d8cd2e43a63130c000.gifSM2证书公钥标识

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


http://chatgpt.dhexx.cn/article/idqW3mmE.shtml

相关文章

SM2椭圆曲线

文章目录 题目环境方案设计背景原理算法步骤 方案实现流程图加密解密 主要函数C代码测试数据结果 注意问题 说明 题目 实现SM2椭圆曲线公钥密码算法,对给出的英文消息进行加密得到密文,并能通过密文解密出明文。 环境 Windows10,MinGW-W64…

JAVA集成国密SM2

JAVA集成国密SM2加解密 一、pom配置二、代码集成2.1、目录结构2.2、源码2.3、测试 三、相关链接 国密算法概述:https://blog.csdn.net/qq_38254635/article/details/131801527 SM2椭圆曲线公钥密码算法 为非对称加密,基于ECC。该算法已公开。由于该算法…

Java SM2

pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http…

ECCSM2

ECC&SM2 ECC 基本内容 概念 ECC 全称为椭圆曲线加密&#xff0c;EllipseCurve Cryptography&#xff0c;是一种基于椭圆曲线数学的公钥密码。与传统的基于大质数因子分解困难性的加密方法(RSA)不同&#xff0c;ECC 依赖于解决椭圆曲线离散对数问题的困难性。它的优势主要…

C# SM2

Cipher using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC;namespace SM2Test {/// <summary>/// 密码计算/// </summary>public…

Springboot整合SM2加密的笔记

首先要明白公钥是加密&#xff0c;私钥用来解密。 国密公钥格式&#xff1a;公钥为64位&#xff0c;前后各32位&#xff0c;对应椭圆算法中BigInteger X 和 BigInteger X &#xff0c;私钥为32位&#xff0c;对应算法中的BigInteger d。 工具类&#xff1a; 可以参考https:/…

SM2加解密、签名验签

导论 SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法&#xff0c;在我们国家商用密码体系中被用来替换RSA算法。 国产SM2算法&#xff0c;是基于ECC的&#xff0c;但二者在签名验签、加密解密过程中或许有些许区别&#xff0c;目前鄙人还不太清楚&#xff0c…

sm2和sm4加密算法浅析

sm2和sm4加密算法浅析 一: SM2 简介&#xff1a;SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法 &#xff0c;SM2为非对称加密&#xff0c;基于ECC。该算法已公开。由于该算法基于ECC&#xff0c;故其签名速度与秘钥生成速度都快于RSA。ECC 256位&#xff0…

国密算法(SM2)简介及SM2生成秘钥

国密算法&#xff08;SM2&#xff09;生成秘钥 一、国密算法介绍二、SM2算法和RSA算法比较三、生成SM2秘钥1、openssl生成SM2秘钥1.1、安装openssl1.2、生成SM2私钥1.3、生成SM2公钥 2、nodejs:使用sm-crypto包生成SM2秘钥3、c生成秘钥 参考 一、国密算法介绍 国密即国家密码局…

向量积(叉积)

a和b叉积可表示为ab&#xff0c;结果是一个和这两个向量都垂直的伪向量 ab absinθ*n &#xff0c;ab为两向量的模长&#xff0c;θ是两向量的夹角&#xff0c;n是垂直二者的单位向量。 叉积的长度可以理解为以ab为邻边的平行四边形面积 叉积的运算 反交换律 ab-ba 分配律…

向量的点乘(内积)和叉乘(外积)

向量点乘&#xff1a;a * b&#xff08;常被写为a b&#xff09; 点乘,也叫向量的内积、数量积.顾名思义,求下来的结果是一个数. 向量a向量b|a||b|cos 在物理学中,已知力与位移求功,实际上就是求向量F与向量s的内积,即要用点乘. 向量叉乘&#xff1a;a ∧ b&#xff08;常被…

向量的内积(点乘)与外积(叉乘)

向量的内积&#xff08;点乘&#xff09;与外积&#xff08;叉乘&#xff09; 向量的内积点乘 向量的外积叉乘 向量的内积&#xff08;点乘&#xff09; 内积的几何意义&#xff1a; 用来表征或计算两个向量之间的夹角在b向量在a向量方向上的投影。 向量的外积&#xff08;叉…

两向量的向量积

两向量的向量积 两向量 a 与 b 的向量积&#xff08;外积&#xff09;是一个向量&#xff0c;记做 a b \mathbf{a}\times \mathbf{b} ab 或 [ a b ] [\mathbf{a}\mathbf{b}] [ab]&#xff0c;它的模是 ∣ a b ∣ ∣ a ∣ ∣ b ∣ sin ⁡ ∠ ( a , b ) |\mathbf{a}\times…

8.2 向量数量积与向量积(点乘与叉乘)

本篇内容依然是向量的运算&#xff0c;只不过不属于线性运算&#xff0c;内容包括向量的数量积与向量积。 一、向量的数量积&#xff08;内积、点乘&#xff0c;参与运算的是向量&#xff0c;结果是数&#xff09; &#xff08;一&#xff09;问题产生的背景与表达 &#x…

【口诀】巧记泰勒公式

函数 多项式函数 可以计算出精确值 非多项式函数 无法计算出精确值 泰勒公式的本质 多项式函数逼近非多项式函数 随着项数累加&#xff0c;逼近的误差就会越小 规律&#xff1a; 只需要确定x的指数符号只有两种情况 要么符号相同(全为) 要么符号交替( -)开头要么1&am…

matlab泰勒公式含义,泰勒公式的哲学意义与敏捷研发

学过微积分的人都知道泰勒展开公式,它是将一个在x=x0处具有n阶导数的函数f(x)利用关于(x-x0)的n次多项式来逼近函数的方法,用标准的数学术语来描述是这样的:若函数f(x)在包含x0的某个闭区间[a,b]上具有n阶导数,且在开区间(a,b)上具有(n 1)阶导数,则对闭区间[a,b]上任意一点…

泰勒公式及泰勒级数

目录 一、背景二、提出问题三、解决问题四、应用——泰勒级数※ 函数的幂级数展开 参考文献 一、背景 对于一些复杂的函数&#xff0c;通常会找简单的函数做近似&#xff0c;而多项式函数就是常用的一种简单函数。 比如当 ∣ x ∣ |x| ∣x∣ 很小时&#xff0c;有以下近似&a…

泰勒公式求极限(如何用+精度怎么确定)一文扫除泰勒公式难点

有些复杂的极限题&#xff0c;里面会涵盖着各种各样的函数&#xff0c;这些群魔乱舞的函数加大了我们计算极限的难度&#xff0c;此时想&#xff1a;如果可以将这些函数统一成一样的形式该多好?此时&#xff0c;就有我们的泰勒公式了。 1.泰勒公式怎么用&#xff1a; 指数函…

泰勒公式记忆方法

泰勒公式记忆方法 几个常见函数的泰勒公式 f ( x ) f ( x 0 ) f ′ ( x 0 ) ( x − x ) f ′ ′ ( x 0 ) 2 ! ( x − x 0 ) 2 ⋯ f ( n ) ( x 0 ) n ! ( x − x 0 ) n R n ( x ) f ( x ) f ( 0 ) f ′ ( 0 ) x f ′ ′ ( 0 ) 2 ! x 2 ⋯ f ( n ) ( 0 ) n ! x n o (…

理解高斯分布

开始前&#xff0c;先看几个重要概念&#xff1a; 概率函数&#xff1a;把事件概率表示成关于事件变量的函数 概率分布函数&#xff1a;一个随机变量ξ取值小于某一数值x的概率&#xff0c;这概率是x的函数&#xff0c;称这种函数为随机变量ξ的分布函数&#xff0c;简称分布…