SM2椭圆曲线公钥密码算法的JAVA实现
2019独角兽企业重金招聘Python工程师标准>>>
package com.zpc.cryptography;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Enumeration;import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DEROutputStream;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Base64;public class SM2Utils {public static byte[] encrypt(byte[] publicKey, byte[] data) throws IOException {if (publicKey == null || publicKey.length == 0) {return null;}if (data == null || data.length == 0) {return null;}byte[] source = new byte[data.length];System.arraycopy(data, 0, source, 0, data.length);Cipher cipher = new Cipher();SM2 sm2 = SM2.Instance();ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);ECPoint c1 = cipher.Init_enc(sm2, userKey);cipher.Encrypt(source);byte[] c3 = new byte[32];cipher.Dofinal(c3);DERInteger x = new DERInteger(c1.getX().toBigInteger());DERInteger y = new DERInteger(c1.getY().toBigInteger());DEROctetString derDig = new DEROctetString(c3);DEROctetString derEnc = new DEROctetString(source);ASN1EncodableVector v = new ASN1EncodableVector();v.add(x);v.add(y);v.add(derDig);v.add(derEnc);DERSequence seq = new DERSequence(v);ByteArrayOutputStream bos = new ByteArrayOutputStream();DEROutputStream dos = new DEROutputStream(bos);dos.writeObject(seq);return bos.toByteArray();
}public static byte[] decrypt(byte[] privateKey, byte[] encryptedData) throws IOException {if (privateKey == null || privateKey.length == 0) {return null;}if (encryptedData == null || encryptedData.length == 0) {return null;}byte[] enc = new byte[encryptedData.length];System.arraycopy(encryptedData, 0, enc, 0, encryptedData.length);SM2 sm2 = SM2.Instance();BigInteger userD = new BigInteger(1, privateKey);ByteArrayInputStream bis = new ByteArrayInputStream(enc);ASN1InputStream dis = new ASN1InputStream(bis);ASN1Primitive derObj = dis.readObject();//DERObject derObj = dis.readObject();ASN1Sequence asn1 = (ASN1Sequence) derObj;//DERInteger x = (DERInteger) asn1.getObjectAt(0);//DERInteger y = (DERInteger) asn1.getObjectAt(1);ASN1Integer x = (ASN1Integer) asn1.getObjectAt(0);ASN1Integer y = (ASN1Integer) asn1.getObjectAt(1);ECPoint c1 = sm2.ecc_curve.createPoint(x.getValue(), y.getValue(), true);Cipher cipher = new Cipher();cipher.Init_dec(userD, c1);DEROctetString data = (DEROctetString) asn1.getObjectAt(3);enc = data.getOctets();cipher.Decrypt(enc);byte[] c3 = new byte[32];cipher.Dofinal(c3);return enc;
}/*** 签名** @param userId* @param privateKey* @param sourceData* @return* @throws IOException*/
public static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws IOException {if (privateKey == null || privateKey.length == 0) {return null;}if (sourceData == null || sourceData.length == 0) {return null;}SM2 sm2 = SM2.Instance();BigInteger userD = new BigInteger(privateKey);//System.out.println("userD: " + userD.toString(16));//System.out.println("");ECPoint userKey = sm2.ecc_point_g.multiply(userD);//System.out.println("椭圆曲线点X: " + userKey.getX().toBigInteger().toString(16));//System.out.println("椭圆曲线点Y: " + userKey.getY().toBigInteger().toString(16));//System.out.println("");byte[] z = sm2.sm2GetZ(userId, userKey);//System.out.println("SM3摘要Z: " + Util.getHexString(z));//System.out.println("");//System.out.println("M: " + Util.getHexString(sourceData));//System.out.println("");SM3Digest sm3 = new SM3Digest();sm3.update(z, 0, z.length);sm3.update(sourceData, 0, sourceData.length);byte[] md = new byte[32];sm3.doFinal(md, 0);//System.out.println("SM3摘要值: " + Util.getHexString(md));//System.out.println("");SM2Result sm2Result = new SM2Result();sm2.sm2Sign(md, userD, userKey, sm2Result);//System.out.println("r: " + sm2Result.r.toString(16));//System.out.println("s: " + sm2Result.s.toString(16));//System.out.println("");DERInteger d_r = new DERInteger(sm2Result.r);DERInteger d_s = new DERInteger(sm2Result.s);ASN1EncodableVector v2 = new ASN1EncodableVector();v2.add(d_r);v2.add(d_s);DERSequence sign = new DERSequence(v2);//DERObject sign = new DERSequence(v2);//byte[] signdata = sign.getDEREncoded();byte[] signdata = sign.getEncoded();return signdata;
}@SuppressWarnings("unchecked")
public static boolean verifySign(byte[] userId, byte[] publicKey, byte[] sourceData, byte[] signData) throws IOException {if (publicKey == null || publicKey.length == 0) {return false;}if (sourceData == null || sourceData.length == 0) {return false;}SM2 sm2 = SM2.Instance();ECPoint userKey = sm2.ecc_curve.decodePoint(publicKey);SM3Digest sm3 = new SM3Digest();byte[] z = sm2.sm2GetZ(userId, userKey);sm3.update(z, 0, z.length);sm3.update(sourceData, 0, sourceData.length);byte[] md = new byte[32];sm3.doFinal(md, 0);//System.out.println("SM3摘要值: " + Util.getHexString(md));//System.out.println("");ByteArrayInputStream bis = new ByteArrayInputStream(signData);ASN1InputStream dis = new ASN1InputStream(bis);//DERObject derObj = dis.readObject();ASN1Primitive derObj = dis.readObject();Enumeration<ASN1Integer> e = ((ASN1Sequence) derObj).getObjects();BigInteger r = e.nextElement().getValue();BigInteger s = e.nextElement().getValue();SM2Result sm2Result = new SM2Result();sm2Result.r = r;sm2Result.s = s;//System.out.println("r: " + sm2Result.r.toString(16));//System.out.println("s: " + sm2Result.s.toString(16));//System.out.println("");sm2.sm2Verify(md, userKey, sm2Result.r, sm2Result.s, sm2Result);return sm2Result.r.equals(sm2Result.R);
}public static void main(String[] args) throws Exception {String plainText = "message digest";//1.源数据数组byte[] sourceData = plainText.getBytes();// 国密规范测试私钥String prik = "128B2FA8BD433C6C068C8D803DFF79792A519A55171B1B650C23661D15897263";//2.私钥先转十六进制,然后进行Base64编码String prikS = new String(Base64.encode(Util.hexToByte(prik)));System.out.println("转换后的私钥:prikS====" + prikS);//System.out.println("");// 国密规范测试用户IDString userId = "ALICE123@YAHOO.COM";//获取userId十六进制字符串System.out.println("十六进制userId: " + Util.getHexString(userId.getBytes()));//System.out.println("");//System.out.println("签名: ");//3.用userId和私钥,对明文数据签名(userid、prik、sourceData)byte[] c = SM2Utils.sign(userId.getBytes(), Base64.decode(prikS.getBytes()), sourceData);System.out.println("SM2签名后值====" + Util.getHexString(c));//System.out.println("");// 国密规范测试公钥String pubk = "040AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857";String pubkS = new String(Base64.encode(Util.hexToByte(pubk)));System.out.println("转换后的公钥pubkS====" + pubkS);//System.out.println("");//System.out.println("验签: ");//4.用公钥进行验签(userId、pubk、sourceData、签名数据c)boolean vs = SM2Utils.verifySign(userId.getBytes(), Base64.decode(pubkS.getBytes()), sourceData, c);System.out.println("验签结果: " + vs);//System.out.println("");//System.out.println("加密: ");//5.SM2加密算法byte[] cipherText = SM2Utils.encrypt(Base64.decode(pubkS.getBytes()), sourceData);System.out.println("SM2加密后结果===" + new String(Base64.encode(cipherText)));System.out.println("");//System.out.println("解密: ");//6.SM2解密算法plainText = new String(SM2Utils.decrypt(Base64.decode(prikS.getBytes()), cipherText));System.out.println("解密后获取的结果===" + plainText);}
}
两个相关JAR从这里下载
https://pan.baidu.com/s/1ggDmn3H
https://pan.baidu.com/s/1mkcK3nM
转载于:https://my.oschina.net/u/568367/blog/1605097
SM2椭圆曲线公钥密码算法的JAVA实现相关推荐
- 国密算法Go语言实现(详解)(九) ——SM2(椭圆曲线公钥密码算法)
国密算法Go语言实现(详解)(九) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...
- SM2椭圆曲线公钥密码算法(Python实现)
本文目录 一.实验目的(包括实验环境.实现目标等等) 1. 实验环境 2. 实现目标 3. 实验中需要导入的库 二.方案设计(包括背景.原理.必要的公式.图表.算法步骤等等) 1. 实验背景 2. 实 ...
- GMSSL :SM2椭圆曲线公钥密码算法——数字签名算法1
2021SC@SDUSC 一.相关术语以及定义 二.数字签名算法 1.辅助函数 密码杂凑算法和随机数发生器 杂凑运算:这个输出串称为该消息的杂凑值. 就是一种可将一个 key 对应到一个索引的函数,一 ...
- 国密算法Go语言实现(详解)(十) ——SM2(椭圆曲线公钥密码算法)
国密算法Go语言实现(详解)(十) --SM2(椭圆曲线公钥密码算法) 原创代码:https://github.com/ZZMarquis/gm 引用时,请导入原创代码库.本文仅以注释方式详解代码逻辑 ...
- SM2椭圆曲线公钥密码算法的C语言实现(基于Miracl大数运算库)
SM2椭圆曲线公钥密码算法的C语言实现(基于Miracl大数运算库) 实验环境 预备知识 FpF_pFp 及椭圆曲线 素域 FpF_pFp FpF_pFp 上的椭圆曲线 FpF_pFp 上椭圆 ...
- 12、SM2椭圆曲线公钥密码算法
参考推荐: 国家密码管理局关于发布<SM2椭圆曲线公钥密码算法>公告(国密局公告第21号)_国家密码管理局 https://blog.csdn.net/u013137970/article ...
- GMSSL :SM2椭圆曲线公钥密码算法——数字签名算法4
2021SC@SDUSC 目录 一.ECDSA介绍 二.代码分析 一.ECDSA介绍 ECDSA的全名是Elliptic Curve DSA,即椭圆曲线DSA.它是Digital Signature ...
- GMSSL :SM2椭圆曲线公钥密码算法-密钥交换协议
2021SC@SDUSC 目录 一.整体架构 二.具体分析 前一篇文章写了密钥交换协议的基本流程,这一篇文章看一下代码实现 一.整体架构 整体来看这一部分有6个函数,相对重要的是序号3,4代表的函数 ...
- SM2国密算法公钥解压缩
SM2一般用到的或者第三方提供的公钥都是压缩过的,长度为66个长度,既33字节. 格式如下,保密期间秘钥内容用*代替了,从02到....3F3B共33字节.66个长度 06:028736002931F ...
最新文章
- 启动php-fpm服务器_无服务器冷启动不是问题-这就是为什么(对于大多数应用程序)...
- 函数sigsuspend
- Android Studio 1.1的安装和遇到的坑
- oracle查看context,oracle context(上下文)
- 安装了虚拟机后mysql用不了_在虚拟机上安装mysql,安装好了并且初始化之后,一直无法启动mysql如何解决?...
- CSS——Fonts(字体)
- vs2017c#开源项目_2017年值得关注的开源项目
- faster-rcnn tensorflow windows python 训练自己数据
- macOS 12 Monterey实用功能
- MIT Place Pulse数据集及google街景图片爬取
- android系统 备份恢复,Android系统备份及系统还原方法介绍
- 最后1天,购票渠道即将关闭!Unite 2018开发者大会全日程公布
- iPhone手机总是弹出输入ID密码怎么办?
- 神经功能缺损评分 css,不同神经功能缺损程度脑梗死病人血尿酸水平变化及其与近期预后关系分析...
- 10分钟轻松定制网站日志分析大盘
- Future 模式详解(并发使用)
- GNN-CS224W: 3 Node Embeddings
- 电子科技大学计算机复试综面,2018年电子科技大学考研复试分数线已公布
- MC基础教程#2 加载器、模组、光影、材质包、数据包下载及安装(国际Java版)
- index函数用法python_python中的index函数 Python中的index一般是什么意思,怎么个用法?...
热门文章
- 2018年最新Python学习路线图
- mysql 数据库里查询语句中不等于的两种写法
- ajax的跨域和请求——详解
- C++ 强制类型转换操作符(static_cast、dynamic_cast、const_cast和reinterpret_cast)
- Python:实现GrabCut算法(附完整源码)
- vim编辑器如何退出
- 项目经理的软技能、硬技能
- 【森气杂谈】群晖NAS内外网磁盘映射以及quick connect设置
- 在LINUX-DEBIAN系统下挂载新硬盘的方法
- NDCG评价指标讲解