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的更多相关文章

  1. SM2国密证书合法性验证

    通常我们遇到过的X509证书都是基于RSA-SHA1算法的,目前国家在大力推行国密算法,未来银行发行的IC卡也都是基于PBOC3.0支持国密算法的,因此我们来学习一下如何验证SM2国密证书的合法性.至 ...

  2. 制作SM2证书

    前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密 ...

  3. java 解析国密SM2算法证书

    首先说明用Java自带的解析x509证书类,是不能解析sm2算法的证书,执行会抛出异常. 用开源库bouncycastle能够解析.详细代码 private byte[] getCSPK(byte[] ...

  4. bouncycastle 国密SM2 API的使用

    摘要:本文不对SM2做过多的介绍,主要介绍java bouncycastle库关于SM2的相关API的使用及注意事项 1. SM2 签名: 注意: 1)签名格式ASN1(描述了一种对数据进行表示.编码 ...

  5. 谈谈PBOC3.0中使用的国密SM2算法

    转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/39780825 作者:小马 一 知识准备 SM2是国密局推出的一种他们自己说具有自主 ...

  6. Postman接口自动化测试实例用到的完整的SM2前端加密算法代码

    var __g__ = {}; !function(t,e){"object"==typeof exports?module.exports=exports=e():"f ...

  7. 学习笔记——SM2算法原理及实现

    RSA算法的危机在于其存在亚指数算法,对ECC算法而言一般没有亚指数攻击算法 SM2椭圆曲线公钥密码算法:我国自主知识产权的商用密码算法,是ECC(Elliptic Curve Cryptosyste ...

  8. Expanded encryption and decryption signature algorithm SM2 & SM3

    Expanded encryption and decryption signature algorithm supports multiple signature digest algorithms ...

  9. 关于国密算法 SM1,SM2,SM3,SM4 的笔记

    国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位. SM1 为对称加密.其加密强度与AES相当.该算法不公开,调用该算法时,需要通过加密芯片的接 ...

  10. SM2椭圆曲线公钥密码算法

    国家必须要有属于自己的一套加密机制才行...好复杂.分享下看哪位看得懂其中的原理 国家密码管理局于2010年12月17日发布了SM2椭圆曲线公钥密码算法,并要求为对现有基于RSA算法的电子认证系统.密 ...

随机推荐

  1. C语言,结构体成员的地址

    先回顾一个基础的知识,不同类型的数据在16位,32位,64位的机器分别占用多少字节. 类型 16位机器(字节) 32位机器(字节) 64位机器(字节) char 1 1 1 short 2 2 2 i ...

  2. Spring事务使用注意事项

    Spring提供的事务使用起来很方便,一个@Transactional注解就搞定全部,但是如果不注意,也会踩坑 提到事务就应该想到至少以下几点: 1.在事务方法中加锁,可能会导致锁失效 无论是Java ...

  3. sensitive-word-admin 敏感词控台 v1.2.0 版本开源

    开源目的 丰富 sensitive-word 的生态. 提供最基本的操作例子,便于在此基础上丰富实现自己的敏感词控台. 避免重复开发的成本,让更多的精力专注于业务. 拓展阅读 sensitive-wo ...

  4. MYSQL服务无法启动:InnoDB: .\ibdata1 can't be opened in read-write mode

    今天在那做实验倒腾mysql数据库,后来发现服务无法启动,查看日志报错如下: 2015-01-07 17:48:54 9136 [ERROR] InnoDB: .\ibdata1 can't be o ...

  5. 【Android逆向】某小说网站签名破解

    1. 豌豆荚下载v5.4的版本 2. 参考前面两篇文章进行反编译和重打包后,安装到手机发现会有验签失败的报错 抓取log 03-29 16:15:37.545 25910 26539 D KM-NAT ...

  6. E4X已经被废弃,各浏览器基本上不再支持它;

    E4X是一种在ECMAScript标准的基础上加入的动态XML支持的程序语言扩展. 到2019年,目前主流浏览器已经不太支持它了,一些版本的Firefox浏览器或许还可以使用,但它已经在主流浏览器的主 ...

  7. Lucene介绍与使用

    Lucene介绍与使用 原文链接:https://blog.csdn.net/weixin_42633131/article/details/82873731 不选择使用Lucene的6大原因? 原文 ...

  8. APScheduler可能遇到的问题

    uWsgi使用多进程模式启动Django项目,因此我们会有多个进程去执行这个定时任务,导致定时任务被重复执行.解决这个问题的方法,我们直接就会想到采用加锁的方式.第一个拿到锁的进程,执行定时任务,其余 ...

  9. python实用模块之netifaces获取网络接口地址相关信息

    文档 https://pypi.org/project/netifaces/ 安装 pip install netifaces 使用 import netifaces netifaces.interf ...

  10. .net core6 Autofac依赖注入

    一.引言 .net core6在文件方面是精简了,所以配置方面也发生了部分变化:下面记录下.net core6中怎么配置Autofac 进行依赖注入. 二.项目创建 1).首先引用两个包:在Nuget ...