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 class Cipher
{
private int ct = 1;
/// <summary>
/// 椭圆曲线E上点P2
/// </summary>
private ECPoint p2;
private SM3Digest sm3keybase;
private SM3Digest sm3c3;
private readonly byte[] key = new byte[32];
private byte keyOff = 0;
public Cipher()
{
}
private void Reset()
{
sm3keybase = new SM3Digest();
sm3c3 = new SM3Digest();
byte[] p;
p = p2.Normalize().XCoord.ToBigInteger().ToByteArray();
sm3keybase.BlockUpdate(p, 0, p.Length);
sm3c3.BlockUpdate(p, 0, p.Length);
p = p2.Normalize().YCoord.ToBigInteger().ToByteArray();
sm3keybase.BlockUpdate(p, 0, p.Length);
ct = 1;
NextKey();
}
private void NextKey()
{
SM3Digest sm3keycur = new SM3Digest(sm3keybase);
sm3keycur.Update((byte)(ct >> 24 & 0x00ff));
sm3keycur.Update((byte)(ct >> 16 & 0x00ff));
sm3keycur.Update((byte)(ct >> 8 & 0x00ff));
sm3keycur.Update((byte)(ct & 0x00ff));
sm3keycur.DoFinal(key, 0);
keyOff = 0;
ct++;
}
public virtual ECPoint InitEnc(SM2 sm2, ECPoint userKey)
{
AsymmetricCipherKeyPair key = sm2.EccKeyPairGenerator.GenerateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;
ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;
BigInteger k = ecpriv.D;
ECPoint c1 = ecpub.Q;
p2 = userKey.Multiply(k);
Reset();
return c1;
}
public virtual void Encrypt(byte[] data)
{
//p2.Normalize();
sm3c3.BlockUpdate(data, 0, data.Length);
for (int i = 0; i < data.Length; i++)
{
if (keyOff == key.Length)
NextKey();
data[i] ^= key[keyOff++];
}
}
public virtual void InitDec(BigInteger userD, ECPoint c1)
{
p2 = c1.Multiply(userD);
Reset();
}
public virtual void Decrypt(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
if (keyOff == key.Length)
NextKey();
data[i] ^= key[keyOff++];
}
sm3c3.BlockUpdate(data, 0, data.Length);
}
public virtual void Dofinal(byte[] c3)
{
byte[] p = p2.Normalize().YCoord.ToBigInteger().ToByteArray();
sm3c3.BlockUpdate(p, 0, p.Length);
sm3c3.DoFinal(c3, 0);
Reset();
}
}
}
SM2
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SM2Test
{
/// <summary>
/// 加密处理中心
/// </summary>
public class SM2
{
public static SM2 Instance
{
get
{
return new SM2();
}
}
public static SM2 InstanceTest
{
get
{
return new SM2();
}
}
#region 曲线参数
/// <summary>
/// 曲线参数
/// </summary>
public static readonly string[] CurveParameter = {
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF",// p,0
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC",// a,1
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93",// b,2
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123",// n,3
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7",// gx,4
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0" // gy,5
};
/// <summary>
/// 椭圆曲线参数
/// </summary>
public string[] EccParam = CurveParameter;
/// <summary>
/// 椭圆曲线参数P
/// </summary>
public readonly BigInteger EccP;
/// <summary>
/// 椭圆曲线参数A
/// </summary>
public readonly BigInteger EccA;
/// <summary>
/// 椭圆曲线参数B
/// </summary>
public readonly BigInteger EccB;
/// <summary>
/// 椭圆曲线参数N
/// </summary>
public readonly BigInteger EccN;
/// <summary>
/// 椭圆曲线参数Gx
/// </summary>
public readonly BigInteger EccGx;
/// <summary>
/// 椭圆曲线参数Gy
/// </summary>
public readonly BigInteger EccGy;
#endregion
/// <summary>
/// 椭圆曲线
/// </summary>
public readonly ECCurve EccCurve;
/// <summary>
/// 椭圆曲线的点G
/// </summary>
public readonly ECPoint EccPointG;
/// <summary>
/// 椭圆曲线 bc规范
/// </summary>
public readonly ECDomainParameters EccBcSpec;
/// <summary>
/// 椭圆曲线密钥对生成器
/// </summary>
public readonly ECKeyPairGenerator EccKeyPairGenerator;
private SM2()
{
EccParam = CurveParameter;
EccP = new BigInteger(EccParam[0], 16);
EccA = new BigInteger(EccParam[1], 16);
EccB = new BigInteger(EccParam[2], 16);
EccN = new BigInteger(EccParam[3], 16);
EccGx = new BigInteger(EccParam[4], 16);
EccGy = new BigInteger(EccParam[5], 16);
ECFieldElement ecc_gx_fieldelement = new FpFieldElement(EccP, EccGx);
ECFieldElement ecc_gy_fieldelement = new FpFieldElement(EccP, EccGy);
EccCurve = new FpCurve(EccP, EccA, EccB);
EccPointG = new FpPoint(EccCurve, ecc_gx_fieldelement, ecc_gy_fieldelement);
EccBcSpec = new ECDomainParameters(EccCurve, EccPointG, EccN);
ECKeyGenerationParameters ecc_ecgenparam;
ecc_ecgenparam = new ECKeyGenerationParameters(EccBcSpec, new SecureRandom());
EccKeyPairGenerator = new ECKeyPairGenerator();
EccKeyPairGenerator.Init(ecc_ecgenparam);
}
/// <summary>
/// 获取杂凑值H
/// </summary>
/// <param name="z">Z值</param>
/// <param name="data">待签名消息</param>
/// <returns></returns>
public virtual byte[] Sm2GetH(byte[] z, byte[] data)
{
SM3Digest sm3 = new SM3Digest();
//Z
sm3.BlockUpdate(z, 0, z.Length);
//待签名消息
sm3.BlockUpdate(data, 0, data.Length);
// H
byte[] md = new byte[sm3.GetDigestSize()];
sm3.DoFinal(md, 0);
return md;
}
/// <summary>
/// 获取Z值
/// Z=SM3(ENTL∣∣userId∣∣a∣∣b∣∣gx∣∣gy ∣∣x∣∣y)
/// </summary>
/// <param name="userId">签名方的用户身份标识</param>
/// <param name="userKey">签名方公钥</param>
/// <returns></returns>
public virtual byte[] Sm2GetZ(byte[] userId, ECPoint userKey)
{
SM3Digest sm3 = new SM3Digest();
byte[] p;
// ENTL由2个字节标识的ID的比特长度
int len = userId.Length * 8;
sm3.Update((byte)(len >> 8 & 0x00ff));
sm3.Update((byte)(len & 0x00ff));
// userId用户身份标识ID
sm3.BlockUpdate(userId, 0, userId.Length);
// a,b为系统曲线参数;
p = EccA.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = EccB.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
// gx、gy为基点
p = EccGx.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = EccGy.ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
// x,y用户的公钥的X和Y
p = userKey.Normalize().XCoord.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
p = userKey.Normalize().YCoord.ToBigInteger().ToByteArray();
sm3.BlockUpdate(p, 0, p.Length);
// Z
byte[] md = new byte[sm3.GetDigestSize()];
sm3.DoFinal(md, 0);
return md;
}
}
}
SM2Utils
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Utilities.Encoders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SM2Test
{
class SM2Utils
{
public static void GenerateKeyPair(out ECPoint publicKey, out BigInteger privateKey)
{
SM2 sm2 = SM2.Instance;
AsymmetricCipherKeyPair key = sm2.EccKeyPairGenerator.GenerateKeyPair();
ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;
ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;
privateKey = ecpriv.D;
publicKey = ecpub.Q;
}
public static String Encrypt(byte[] publicKey, byte[] data)
{
if (null == publicKey || publicKey.Length == 0)
{
return null;
}
if (data == null || data.Length == 0)
{
return null;
}
byte[] source = new byte[data.Length];
Array.Copy(data, 0, source, 0, data.Length);
Cipher cipher = new Cipher();
SM2 sm2 = SM2.Instance;
ECPoint userKey = sm2.EccCurve.DecodePoint(publicKey);
ECPoint c1 = cipher.InitEnc(sm2, userKey);
cipher.Encrypt(source);
byte[] c3 = new byte[32];
cipher.Dofinal(c3);
String sc1 = Encoding.Default.GetString(Hex.Encode(c1.GetEncoded()));
String sc2 = Encoding.Default.GetString(Hex.Encode(source));
String sc3 = Encoding.Default.GetString(Hex.Encode(c3));
return (sc1 + sc2 + sc3).ToUpper();
}
public static byte[] Decrypt(byte[] privateKey, byte[] encryptedData)
{
if (null == privateKey || privateKey.Length == 0)
{
return null;
}
if (encryptedData == null || encryptedData.Length == 0)
{
return null;
}
String data = Encoding.Default.GetString(Hex.Encode(encryptedData));
byte[] c1Bytes = Hex.Decode(Encoding.Default.GetBytes(data.Substring(0, 130)));
int c2Len = encryptedData.Length - 97;
byte[] c2 = Hex.Decode(Encoding.Default.GetBytes(data.Substring(130, 2 * c2Len)));
byte[] c3 = Hex.Decode(Encoding.Default.GetBytes(data.Substring(130 + 2 * c2Len, 64)));
SM2 sm2 = SM2.Instance;
BigInteger userD = new BigInteger(1, privateKey);
ECPoint c1 = sm2.EccCurve.DecodePoint(c1Bytes);
Cipher cipher = new Cipher();
cipher.InitDec(userD, c1);
cipher.Decrypt(c2);
cipher.Dofinal(c3);
return c2;
}
}
}
调用
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math;
namespace SM2Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 获取公钥私钥 加密 解密
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
ECPoint publicKey=null;
BigInteger privateKey=null;
SM2Utils.GenerateKeyPair(out publicKey, out privateKey);
System.Console.Out.WriteLine("公钥: " + Encoding.Default.GetString(Hex.Encode(publicKey.GetEncoded())).ToUpper());
System.Console.Out.WriteLine("私钥: " + Encoding.Default.GetString(Hex.Encode(privateKey.ToByteArray())).ToUpper());
String plainText = "lxw测试";
byte[] sourceData = Encoding.Default.GetBytes(plainText);
//下面的秘钥可以使用generateKeyPair()生成的秘钥内容
//国密规范正式私钥
String prik = "00971C650DB6F5B690C12F6D3651CAD3F6BB2DA9D67F29CA9AF4BAF84A6F2EF5FA";
//国密规范正式公钥
String pubk = "047DBFC88D4853D95D9BAD8489C2D77ED6EF012FD80853AA7549CA0857380FD217D323057F551BE49305D1A71AA190767288E3254377CD4970E0DE9CFBA7248E4E";
System.Console.Out.WriteLine("加密: ");
String cipherText = SM2Utils.Encrypt(Hex.Decode(pubk), sourceData);
System.Console.Out.WriteLine(cipherText);
System.Console.Out.WriteLine("解密: ");
plainText = Encoding.Default.GetString(SM2Utils.Decrypt(Hex.Decode(prik), Hex.Decode(cipherText)));
System.Console.Out.WriteLine(plainText);
Console.ReadLine();
}
/// <summary>
/// 加密
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
String plainText = "lxw测试";
String pubk = "047DBFC88D4853D95D9BAD8489C2D77ED6EF012FD80853AA7549CA0857380FD217D323057F551BE49305D1A71AA190767288E3254377CD4970E0DE9CFBA7248E4E";
byte[] sourceData = Encoding.Default.GetBytes(plainText);
System.Console.Out.WriteLine("加密: ");
String cipherText = SM2Utils.Encrypt(Hex.Decode(pubk), sourceData);
System.Console.Out.WriteLine(cipherText);
System.Console.Out.WriteLine(cipherText.Length);
}
/// <summary>
/// 解密
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
String cipherText = "04214B8588CFBADBF06DB82D82FD7FE8BF1C28B583D7646F4D65810F1094B564B5F865BDC8AF6B7BE004ADF46DFFF501520EA3D7C9F161214FFAF8B45AE25C151BFC43B409675FC56FFCAD6A9209525FB694ED00BAB366437A1AA353D48F5FF627DCD9F3041A78EF";
//国密规范正式私钥
String prik = "00971C650DB6F5B690C12F6D3651CAD3F6BB2DA9D67F29CA9AF4BAF84A6F2EF5FA";
//国密规范正式公钥
String pubk = "047DBFC88D4853D95D9BAD8489C2D77ED6EF012FD80853AA7549CA0857380FD217D323057F551BE49305D1A71AA190767288E3254377CD4970E0DE9CFBA7248E4E";
System.Console.Out.WriteLine("解密: ");
String plainText = Encoding.Default.GetString(SM2Utils.Decrypt(Hex.Decode(prik), Hex.Decode(cipherText)));
System.Console.Out.WriteLine(plainText);
}
}
}
C# SM2的更多相关文章
- SM2国密证书合法性验证
通常我们遇到过的X509证书都是基于RSA-SHA1算法的,目前国家在大力推行国密算法,未来银行发行的IC卡也都是基于PBOC3.0支持国密算法的,因此我们来学习一下如何验证SM2国密证书的合法性.至 ...
- 制作SM2证书
前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密 ...
- java 解析国密SM2算法证书
首先说明用Java自带的解析x509证书类,是不能解析sm2算法的证书,执行会抛出异常. 用开源库bouncycastle能够解析.详细代码 private byte[] getCSPK(byte[] ...
- bouncycastle 国密SM2 API的使用
摘要:本文不对SM2做过多的介绍,主要介绍java bouncycastle库关于SM2的相关API的使用及注意事项 1. SM2 签名: 注意: 1)签名格式ASN1(描述了一种对数据进行表示.编码 ...
- 谈谈PBOC3.0中使用的国密SM2算法
转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/39780825 作者:小马 一 知识准备 SM2是国密局推出的一种他们自己说具有自主 ...
- Postman接口自动化测试实例用到的完整的SM2前端加密算法代码
var __g__ = {}; !function(t,e){"object"==typeof exports?module.exports=exports=e():"f ...
- 学习笔记——SM2算法原理及实现
RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法 SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve Cryptosyste ...
- Expanded encryption and decryption signature algorithm SM2 & SM3
Expanded encryption and decryption signature algorithm supports multiple signature digest algorithms ...
- 关于国密算法 SM1,SM2,SM3,SM4 的笔记
国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位. SM1 为对称加密.其加密强度与AES相当.该算法不公开,调用该算法时,需要通过加密芯片的接 ...
- SM2椭圆曲线公钥密码算法
国家必须要有属于自己的一套加密机制才行...好复杂.分享下看哪位看得懂其中的原理 国家密码管理局于2010年12月17日发布了SM2椭圆曲线公钥密码算法,并要求为对现有基于RSA算法的电子认证系统.密 ...
随机推荐
- JLink OB相关的一些记录
使用 STM32F103 Bluepill 制作 JLink OB https://github.com/GCY/JLINK-ARM-OB https://stm32duinoforum.com/fo ...
- java.lang.System快速指南
1.介绍 在本教程中,我们将快速了解java.lang.System类及其特性和核心功能. 2.IO 系统类是java.lang的一部分,它的一个主要特性是让我们能够访问标准的I/O流. 简单地说,它 ...
- ElementUI导出表格数据为Excel文件
功能介绍 将列表的数据导出成excel文件是管理系统中非常常见的功能.最近正好用到了ElementUI+Vue的组合做了个导出效果,拿出来分享一下,希望可以帮到大家:) 实现效果 实现步骤 1.定义导 ...
- MASM32 - PlaySound的实现
MASM安装教程: https://blog.csdn.net/u010486308/article/details/105495848 代码参考: .model flat, stdcall opti ...
- 项目实战:Qt+iMax6生命探测仪(探测障碍物、静止目标、动态目标、生命目标、探测半径、探测前方雷达显示、动态目标轨迹显示、探测热力图、探测过程存储与回放)
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110994486长期持续带来更多项目与技术分享, ...
- 【Azure 环境】各种语言版本或命令,发送HTTP/HTTPS的请求合集
问题描述 写代码的过程中,时常遇见要通过代码请求其他HTTP,HTTPS的情况,以下是收集各种语言的请求发送,需要使用的代码或命令 一:PowerShell Invoke-WebRequest htt ...
- 【Azure 应用服务】更新镜像后并重启应用服务,部署日志始终没有出现加载新镜像成功的日志
问题描述 在App Service中部署镜像文件,发现镜像一直没有部署,重启App Service服务也无效果. DockerFile如下: FROM crunchgeek/php-fpm:7.0 # ...
- gitlab推送代码触发jenkins构建
预期:推送devloop或者master分支的代码, 自动执行jenkins 发布测试环境 首先,jenkins中需要安装如下插件 打开一个任务配置,构建触发器中勾选"Build when ...
- 使用C#和MemoryCache组件实现轮流调用APIKey以提高并发能力
文章信息 标题:使用C#和MemoryCache组件实现轮流调用API Key以提高并发能力的技巧 摘要:本文介绍了如何利用C#语言中的MemoryCache组件,结合并发编程技巧,实现轮流调用多个A ...
- Python列表字典推导式
[一]语法 列表推导式可以利用列表,元组,字典,集合等数据类型,快速的生成一个特定需要的列表. 语法格式如下 [表达式 for 迭代变量 in 可迭代对象 [if 条件表达式]] [二]列表推导式 [ ...