国密SM2算法的java和nodejs实现
转至 http://mp.weixin.qq.com/s/nboZAvg1qYiJIEun6yF2aQ
国密即国家密码局认定的国产密码算法,即商用密码。包括对称加密(SM1) ,非对称加密(SM2) , 信息摘要(SM3). 本文介绍SM2
SM2 基于 ECC实现。.国家密码局推荐ECC曲线是256位,相当于比特币的secp256k1.
SM2 数学计算过程可以参考国家密码局官网的公布文档
本文介绍SM2 签名验签的java和nodejs的实现
ECC 算法依赖两个重要的数学运算 1,大数运算,2,椭圆乘法运算。
Java 中天生有BigInteger类,椭圆乘法运算可以借助于开源的java加密库:bouncycastle ,gradle 工程添加依赖:
compile ‘org.bouncycastle:bcprov-jdk15on:1.55’
下面就贴代码吧
public class SM2
{//测试参数
// public static final String[] ecc_param = {
// "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3",
// "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498",
// "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A",
// "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7",
// "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D",
// "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"
// };//正式参数public static String[] ecc_param = { "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF","FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC","28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93","FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123","32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7","BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"};public static SM2 Instance() {return new SM2();}public final BigInteger ecc_p;public final BigInteger ecc_a;public final BigInteger ecc_b;public final BigInteger ecc_n;public final BigInteger ecc_gx;public final BigInteger ecc_gy;public final ECCurve ecc_curve;public final ECPoint ecc_point_g;public final ECDomainParameters ecc_bc_spec;public final ECKeyPairGenerator ecc_key_pair_generator;public final ECFieldElement ecc_gx_fieldelement;public final ECFieldElement ecc_gy_fieldelement;public SM2() {this.ecc_p = new BigInteger(ecc_param[0], 16);this.ecc_a = new BigInteger(ecc_param[1], 16);this.ecc_b = new BigInteger(ecc_param[2], 16);this.ecc_n = new BigInteger(ecc_param[3], 16);this.ecc_gx = new BigInteger(ecc_param[4], 16);this.ecc_gy = new BigInteger(ecc_param[5], 16);this.ecc_gx_fieldelement = new Fp(this.ecc_p, this.ecc_gx);this.ecc_gy_fieldelement = new Fp(this.ecc_p, this.ecc_gy);this.ecc_curve = new ECCurve.Fp(this.ecc_p, this.ecc_a, this.ecc_b);this.ecc_point_g = new ECPoint.Fp(this.ecc_curve, this.ecc_gx_fieldelement, this.ecc_gy_fieldelement);this.ecc_bc_spec = new ECDomainParameters(this.ecc_curve, this.ecc_point_g, this.ecc_n);ECKeyGenerationParameters ecc_ecgenparam;ecc_ecgenparam = new ECKeyGenerationParameters(this.ecc_bc_spec, new SecureRandom());this.ecc_key_pair_generator = new ECKeyPairGenerator();this.ecc_key_pair_generator.init(ecc_ecgenparam);}
}
签名代码片段:public static BigInteger[] Sm2Sign(byte[] md, AsymmetricCipherKeyPair keypair) {SM3Digest sm3 = new SM3Digest();ECPublicKeyParameters ecpub = (ECPublicKeyParameters) keypair.getPublic();byte[] hashData = new byte[32];sm3.update(md, 0, md.length);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;BigInteger ecc_n = null;do {do {ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters) keypair.getPrivate();k = ecpriv.getD();kp = ecpub.getQ();ecc_n = ecpriv.getParameters().getN();userD = ecpriv.getD();// r = (e+x) mod nr = e.add(kp.getX().toBigInteger());r = r.mod(ecc_n);}while (r.equals(BigInteger.ZERO) || r.add(k).equals(ecc_n));//s= (((1 + dA)~-1) * (k - r*da )) mod nBigInteger 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));return new BigInteger[]{r, s};}签验代码片段:public static boolean Sm2verify(byte[] md, BigInteger r, BigInteger s, AsymmetricCipherKeyPair keypair) {SM3Digest sm3 = new SM3Digest();ECPublicKeyParameters ecpub = (ECPublicKeyParameters) keypair.getPublic();byte[] hashData = new byte[32];sm3.update(md, 0, md.length);sm3.doFinal(hashData, 0);// eBigInteger e = new BigInteger(1, hashData);// kECPoint k;ECPoint G = null;ECPoint Pa = null;BigInteger t = null;BigInteger R = null;BigInteger ecc_n = null;Pa = ecpub.getQ();G = ecpub.getParameters().getG();ecc_n = ecpub.getParameters().getN();if(r.equals(BigInteger.ONE) || r.equals(ecc_n)) {return false;}if(s.equals(BigInteger.ONE) || s.equals(ecc_n)) {return false;}t = r.add(s).mod(ecc_n);if (t.equals(BigInteger.ZERO)) {return false;}//k(x,y) = s*G + t*Pak = G.multiply(s).add(Pa.multiply(t));//R = (e+k.x) mod nR = e.add(k.getX().toBigInteger()).mod(ecc_n);//R == r trueif (R.equals(r)) return true;return false;}
nodejs的实现方式
nodejs本身没有BigInteger的,但有牛人写了个BigInteger ,https://www.npmjs.com/package/biginteger
椭圆运算:https://github.com/cryptocoinjs/ecurve
有这两基本运算,就可以按国密局文档编写我们的SM2算法了
下面直接贴代码吧
var ecurve = require('ecurve');
var Point = ecurve.Point;
var BigInteger = require('bigi');
var Curve = ecurve.Curve;
var assert = require('assert')var SM2=getCurveSM2();
function getCurveSM2() {var curve = {p: "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",a: "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",b: "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",n: "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",h: "01",Gx: "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",Gy: "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0"}if (!curve) return nullvar p = new BigInteger(curve.p, 16)var a = new BigInteger(curve.a, 16)var b = new BigInteger(curve.b, 16)var n = new BigInteger(curve.n, 16)var h = new BigInteger(curve.h, 16)var Gx = new BigInteger(curve.Gx, 16)var Gy = new BigInteger(curve.Gy, 16)return new Curve(p, a, b, Gx, Gy, n, h)
}function getQ(d) {var D = BigInteger.fromBuffer(d);var G = SM2.Gvar Q = G.multiply(D);return Q;
}
function decodeFrom(buffer) {return Point.decodeFrom(SM2,buffer);
}function decodeFromXY(buffer) {var byteLength = Math.floor((SM2.p.bitLength() + 7) / 8)assert.equal(buffer.length, byteLength * 2, 'Invalid sequence length')var x = BigInteger.fromBuffer(buffer.slice(0, byteLength))var y = BigInteger.fromBuffer(buffer.slice(byteLength))var Q = Point.fromAffine(SM2, x, y)return Q;
}function sign(hash, d) {//var x = d.toBuffer(32)var e = BigInteger.fromBuffer(hash)var D = BigInteger.fromBuffer(d);var n = SM2.nvar G = SM2.Gvar Q = G.multiply(D);var r, s;do {do {r = e.add(Q.affineX);r = r.mod(n);}while (r.equals(BigInteger.ZERO) || r.add(D).equals(n));//s= (((1 + dA)~-1) * (k - r*da )) mod nvar da_1 = D.add(BigInteger.ONE);da_1 = da_1.modInverse(n);// ss = r.multiply(D);s = D.subtract(s).mod(n);s = da_1.multiply(s).mod(n);}while (s.equals(BigInteger.ZERO));return {r:r.toBuffer(),s:s.toBuffer()};
}
function verify (hash, signature, Q) {var n = SM2.nvar G = SM2.Gvar r = BigInteger.fromBuffer(signature.r);var s = BigInteger.fromBuffer(signature.s);// 1.4.1 Enforce r and s are both integers in the interval [1, n − 1]if (r.signum() <= 0 || r.compareTo(n) >= 0) return falseif (s.signum() <= 0 || s.compareTo(n) >= 0) return false// 1.4.2 H = Hash(M), already done by the user// 1.4.3 e = Hvar e = BigInteger.fromBuffer(hash)var t;t = r.add(s).mod(n);if (t.equals(BigInteger.ZERO)) {return false;}//k(x,y) = s*G + t*Pavar k = G.multiply(s).add(Q.multiply(t));//R = (e+k.x) mod nR = e.add(k.affineX).mod(n);//R == r trueif (R.equals(r)) return true;return false;}
module.exports = {Curve: SM2,Point:Point,decodeFrom:decodeFrom,decodeFromXY:decodeFromXY,getQ:getQ,sign: sign,verify: verify
}
以上代码只是代码片段,需要完整工程的同学可以关注订阅号索取源代码
如果你喜欢这篇文章,请动动手指点击二维码关注本公众号
微信扫一扫
关注该公众号
国密SM2算法的java和nodejs实现相关推荐
- java 产生p10证书_【国密SM2算法】JAVA创建pkcs10格式的csr证书请求文件
代码: public static void main(String[] args) throws Exception { Security.addProvider(new org.bouncycas ...
- 国密SM2算法的只求理解不求甚解 (4/5)SM2算法加解密协议
国密SM2算法的只求理解不求甚解 (1/5)前置数学知识:模运算 国密SM2算法的只求理解不求甚解 (2/5)前置数学知识:平面几何 国密SM2算法的只求理解不求甚解 (3/5)SM2算法数学模型 国 ...
- 一文告诉你,国密SM2算法有多优秀
可能很多人都想不到,密码技术是与核技术.航天技术并列的国家三大安全核心技术之一,在保障信息安全,建设行业网络安全环境,增强我国行业信息系统的"安全可控"能力等方面发挥着至为关键的作 ...
- 国密SM2算法与RSA算法对比分析
SM2算法和RSA算法都是公钥密码算法,SM2算法是一种更先进安全的算法,在安全性能.速度性能等方面都优于RSA算法,在我国商用密码体系中被用来替换RSA算法.国家密码管理局于2010年12月17日发 ...
- 国密SM2算法(JS加密,C#、Java解密)
常见的渗透测试会将网站登录时密码使用明文传输视为风险.推荐使用国密算法或者RSA算法对密码进行加密传输. RSA加密(JS加密,C#.Java解密)请参考<RSA对称加密(JS加密,C#.Jav ...
- 国密SM2算法密钥派生函数KDF的实现
前段时间需要实现国密算法SM2的签名.验签.加密.解密等功能,加解密过程使用到的密钥派生函数(KDF),从网上搜到的代码不符合<GMT 0003.4-2012 SM2椭圆曲线公钥密码算法 > ...
- 国密SM2电子签章JAVA实现
本文默认所需的国密SM2证书已生成完成.基于BouncyCastle JAR包+itextpdf,利用itext提供的2个签名接口:ExternalDigest 及 ExternalSignature ...
- mysql国密算法_【国密SM2算法】通过公钥证书获取JAVA对象
网上关于国密算法的资料较单一,大部分代码都是写的怎么通过java代码生成公私钥串. 实际项目中对方已经给了他们的公钥证书,这里记录如何通过代码解析获得Ecpoint对象并输出 关键代码 String ...
- PBOC3.0中使用的国密SM2算法
一.知识准备 PBOC3.0规范就是<中国金融集成电路(IC)卡规范>3.0版本. SM2是国密局推出的一种他们自己说具有自主知识产权的非对称商用密码算法.本身是基于ECC椭圆曲线算法的, ...
最新文章
- DevOps \u0026 SRE 必备技能清单
- 计算机职称在线考试报名系统,计算机职称考试报名时间及入口2021年9月
- 如何通过 C# 生成安全的 Base64 URL 字符串?
- 程序员的算法课(16)-B+树在数据库索引中的作用
- 编程语言对比 容器
- 将系统升级为鸿蒙11.1系统,即将脱胎换骨!EMUI11.1升级名单遭曝光,或要和跟安卓说再见...
- Yii2.0 两次奇葩的数据库连接经历
- linux 文件压缩与解压
- 聚类算法论文研读 record
- 阿里云服务器如何登录?阿里云服务器的三种登录方法...
- c语言程序流程图模板word,《流程图模板》word版.doc
- 清理linux系统内存缓存
- 嵌入式开发板设置IP
- Euraka服务注册篇
- Java软件测试工程师之学习进阶路线
- python自动发送短信验证码、短信通知、营销短信、语音短信
- MySQL使用教程(Navicat)
- 如何读取PLC的寄存器地址和点表?
- QA:GMS认证、CTS测试、GTS测试、谷歌认证、安卓认证,Android
- 单相交流调压电路matlab仿真,单相斩控式交流调压电路