java利用bc库实现国密sm2签名验签

1370人浏览 / 0人评论

一、签名算法

设待签名的消息为M,为了获取消息M的数字签名(r,s),作为签名者的用户A应实现以下运算步骤:
A1:置M’=ZA||M;
A3:用随机数发生器产生随机数k∈[1,n-1];
A4:计算椭圆曲线点(x1,y1)=[k]G,按规则将x1的数据类型转换为整数;
A5:计算r=(e+x1) modn,若r=0或r+k=n则返回A3;
A6:计算s = ((1 +dA)^−1 • (k − r • dA)) mod n,若s=0则返回A3;
A7:按规则将r、s的数据类型转换为字节串,消息M的签名为(r,s)。

无特殊约定的情况下,用户标识ID的长度为16字节,其默认值从左至右依次为:0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38。默认用户标识ID转换成字符串就是:1234567812345678。

二、验签算法

为了检验收到的消息M′及其数字签名(r′, s′),作为验证者的用户B应实现以下运算步骤:
B1:检验r′ ∈[1,n-1]是否成立,若不成立则验证不通过;
B2:检验s′ ∈[1,n-1]是否成立,若不成立则验证不通过;
B3:置M=ZA||M′;
B4:计算e′ = Hv(M),按规则将e′的数据类型转换为整数;
B5:按规则将r′、s′的数据类型转换为整数,计算t = (r′ + s′) modn,若t = 0,则验证不通过;
B6:计算椭圆曲线点(x′1; y′1)=[s′]G +[t]PA
B7:按规则将x′1的数据类型转换为整数,计算R = (e′ + x′1) modn,检验R=r′是否成立,若成立则验证通过;否则验证不通过。

三、签名、验签实例

下面利用开源BC库进行国密SM2的签名和验签。国密SM2签名算法的名称为:SM3withSM2,算法对象标识OID为:1.2.156.10197.1.501,这个OID是唯一标识。更多的国密算法OID及意义可参考The GmSSL Project

示例代码:

KeyPair keyPair = this.getKeyPair();
byte[] plainText = "test".getBytes();
log.info("原文:{}", plainText);
/**
 * 签名
 */
// SM3withSM2签名算法OID为1.2.156.10197.1.501,此处也可用算法OID
Signature signature = Signature.getInstance("SM3withSM2", "BC");
// 设置签名私钥
signature.initSign(keyPair.getPrivate());
// 待签原文
signature.update(plainText);
// 执行签名
byte[] signValue = signature.sign();
log.info("签名结果:{}", signValue);
log.info("签名结果:{}", HexUtil.encodeHexStr(signValue));
/**
 * 验签
 */
signature = Signature.getInstance("SM3withSM2", "BC");
// 设置验签公钥
signature.initVerify(keyPair.getPublic());
// 待签原文
signature.update(plainText);
// 执行验签
boolean result = signature.verify(signValue);
log.info("验签结果:{}", result);

运行结果:

私钥:308193020100301306072a8648ce3d020106082a811ccf5501822d0479307702010104209b5edad821c9b731c73812cd01fd20acee44be18c0215a8b998667f78a9aa6aea00a06082a811ccf5501822da144034200049428979dd8687ca6001c6502d6640b17a0b8adbae4a04d71ea84fc26a2979ead194841aa3a17034600ccbdc432e2d0763ed632340e5bb65e5f7eef52c67e2a26
公钥:3059301306072a8648ce3d020106082a811ccf5501822d034200049428979dd8687ca6001c6502d6640b17a0b8adbae4a04d71ea84fc26a2979ead194841aa3a17034600ccbdc432e2d0763ed632340e5bb65e5f7eef52c67e2a26
原文:[116, 101, 115, 116]
签名结果:[48, 69, 2, 33, 0, -7, 42, 78, 17, 83, 38, 109, 14, -49, 52, -30, -121, 26, 70, 8, -40, -17, -33, -124, -106, 105, -49, 107, -99, 27, -119, 26, -33, 100, 79, 58, -28, 2, 32, 54, -117, -54, -110, -53, -43, -128, 6, -66, 102, -96, 117, -113, -29, -69, 61, 98, 87, -91, 62, 45, 45, 110, 91, 121, 89, -14, -103, 67, 20, -36, -58]
签名结果:3045022100f92a4e1153266d0ecf34e2871a4608d8efdf849669cf6b9d1b891adf644f3ae40220368bca92cbd58006be66a0758fe3bb3d6257a53e2d2d6e5b7959f2994314dcc6
验签结果:true

BC库签名数据为ASN1格式,通过ASN查看工具可看到。

国密的签名值的ASN.1定义如下:

 

参考资料

【1】GB/T 32918.2-2016 信息安全技术 SM2椭圆曲线公钥密码算法 第2部分:数字签名算法

【2】GB/T 35276-2017 信息安全技术 SM2密码算法使用规范

全部评论