【转】C#实现SM2国密加密

本文主要讲解“国密加密算法”SM系列之SM2的C#实现方法,加密规则请详阅国密局发布的文档。

首先需第三方Nuget包:Portable.BouncyCastle (源码来自http://www.bouncycastle.org/csharp/)

SM2的加密需使用到SM3加密处理

1.1 SM2密码计算

 

    /// <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();}}

 

1.2 加密处理中心

 

    /// <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();//Zsm3.BlockUpdate(z, 0, z.Length);//待签名消息sm3.BlockUpdate(data, 0, data.Length);// Hbyte[] 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用户身份标识IDsm3.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和Yp = userKey.Normalize().XCoord.ToBigInteger().ToByteArray();sm3.BlockUpdate(p, 0, p.Length);p = userKey.Normalize().YCoord.ToBigInteger().ToByteArray();sm3.BlockUpdate(p, 0, p.Length);// Zbyte[] md = new byte[sm3.GetDigestSize()];sm3.DoFinal(md, 0);return md;}}

 

1.3 加密调用

 

    /// <summary>/// Sm2算法   /// 对标国际RSA算法/// </summary>public class Sm2Crypto {/// <summary>/// 数据/// </summary>public string Str { get; set; }/// <summary>/// 数据/// </summary>public byte[] Data { get; set; }/// <summary>/// 公钥/// </summary>public string PublicKey { get; set; }/// <summary>/// 私钥/// </summary>public string PrivateKey { get; set; }/// <summary>/// 获取密钥/// </summary>/// <param name="privateKey">私钥</param>/// <param name="publicKey">公钥</param>public static void GetKey(out string privateKey, out string publicKey){SM2 sm2 = SM2.Instance;AsymmetricCipherKeyPair key = sm2.EccKeyPairGenerator.GenerateKeyPair();ECPrivateKeyParameters ecpriv = (ECPrivateKeyParameters)key.Private;ECPublicKeyParameters ecpub = (ECPublicKeyParameters)key.Public;publicKey = Encoding.Default.GetString(Hex.Encode(ecpub.Q.GetEncoded())).ToUpper();privateKey = Encoding.Default.GetString(Hex.Encode(ecpriv.D.ToByteArray())).ToUpper();}#region 解密public object Decrypt(Sm2Crypto entity){var data = !string.IsNullOrEmpty(entity.Str) ?Hex.Decode(entity.Str) :entity.Data;return Encoding.Default.GetString(Decrypt(Hex.Decode(entity.PrivateKey), data));}/// <summary>/// 解密/// </summary>/// <param name="privateKey"></param>/// <param name="encryptedData"></param>/// <returns></returns>private 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);//c1.Normalize();Cipher cipher = new Cipher();cipher.InitDec(userD, c1);cipher.Decrypt(c2);cipher.Dofinal(c3);return c2;}#endregion#region 加密public string Encrypt(Sm2Crypto entity){var data = !string.IsNullOrEmpty(entity.Str) ?Encoding.Default.GetBytes(entity.Str) :entity.Data;return Encrypt(Hex.Decode(entity.PublicKey), data);}/// <summary>/// 加密/// </summary>/// <param name="publicKey"></param>/// <param name="data"></param>/// <returns></returns>private 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);//userKey.Normalize();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();}#endregion}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436832.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php udp发送和接收_63、php利用原生socket创建udp服务

1、案例函数汇总2、案例通过socket创建udp服务&#xff0c;获取对端的ip和port信息。并进行打印2.1、udp服务源码/*** Copyright(C) Iamasb* project : 3、workerman相关知识点* explain : 原生socket创建创建udp服务* filename : socket_udp.php* author : Iamasb*/// 创建udp…

【转】C#实现SM3国密加密

C#实现SM3国密加密 本文主要讲解“国密加密算法”SM系列之SM3的C#实现方法&#xff0c;加密规则请详阅国密局发布的文档。 首先需第三方Nuget包&#xff1a;Portable.BouncyCastle &#xff08;源码来自http://www.bouncycastle.org/csharp/&#xff09; 1.1常规处理 /// &l…

mq集群要建传输队列吗_面试官:消息队列这些我必问!

作者&#xff1a;mousycodersegmentfault.com/a/1190000021054802消息队列连环炮项目里怎么样使用 MQ 的&#xff1f;为什么要使用消息队列&#xff1f;消息队列有什么优点和缺点&#xff1f;kafka,activemq,rabbitmq,rocketmq 都有什么去呗&#xff1f;如何保证消息队列高可用…

【转】国密算法sm4 CBC模式加解密

一.什么是CBC模式? CBC模式的全称是Cipher Block Chaining模式&#xff08;密文分组链接模式&#xff09;&#xff0c;之所以叫这个名字&#xff0c;是因为密文分组像链条一样相互连接在一起。 在CBC模式中&#xff0c;首先将明文分组与前一个密文分组进行异或运算&#xff0c…

oracle数据库连接时报12514_连接Oracle数据库时报ORA-12541:TNS:无监听程序的图文解决教程...

在用PL/SQL Developer等客户端工具连接oracle服务器时出现ORA-12541:TNS:无监听程序的错误,如下图:发现原来是oracle的监听没有启动,重启监听后就连接成功了,下面跟大家分享一下如何启动oracle的监听。1.在安装Oracle服务器的主机上&#xff0c;打开Net Configuration Assistan…

【转】对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)

版权声明&#xff1a;本文为作者原创&#xff0c;如需转载&#xff0c;请注明出处https://blog.csdn.net/weixin_42940826注&#xff1a;以下图片来自于《图解密码学》&#xff0c;这本书讲的更全面细致&#xff0c;建议阅读&#xff0c;在我资源库中有此书&#xff0c;还有使用…

中发生数据丢失_如何防止Redis脑裂导致数据丢失?

所谓的脑裂&#xff0c;就是指在主从集群中&#xff0c;同时有两个主节点&#xff0c;它们都能接收写请求。而脑裂最直接的影响&#xff0c;就是客户端不知道应该往哪个主节点写入数据&#xff0c;结果就是不同的客户端会往不同的主节点上写入数据。而且&#xff0c;严重的话&a…

【转】C#实现SM4国密加密

本文主要讲解“国密加密算法”SM系列之SM4的C#实现方法&#xff0c;加密规则请详阅国密局发布的文档。 首先需第三方Nuget包&#xff1a;Portable.BouncyCastle &#xff08;源码来自http://www.bouncycastle.org/csharp/&#xff09; 1.1 SM4主类 /// <summary>/// //…

vscode怎么自动将px转换成vw_基于react/vue移动端适配之px自动转rem、vw

作为一名前端开发&#xff0c;在做移动端适配时rem、vw是我们经常用到的单位&#xff0c;但是我们在实际开发过程中需要将设计稿上的px转换成rem&#xff0c;如果手动去计算&#xff0c;将是一个很耗时、费力的过程。这是就需要一个工具可以帮我们自动将px转成rem、vw。开始之前…

【转】TransactionScope事务简介

在.NET 1.0/1.1 版本我们使用SqlTransaction.处理事务 string connString ConfigurationManager.ConnectionStrings["db"].ConnectionString; using (var conn new SqlConnection(connString)) { conn.Open(); using (IDbTransaction tran conn.BeginTransact…

后台接收datetime_input上传date日期时间数据到后台报400怎么办?

前端上传日期时间数据到后台时&#xff0c;上传失败我这里是用里存放时间&#xff0c;上传到后台的controller方法时&#xff0c;参数类型是java.util.Date&#xff0c;发现没有到controller方法里面。报错&#xff1a;不能将String转成Date。我想错误的原因是前端传上来的是St…

【转】C#中使用TransactionScope类(分布式事务) 和 锁

如果在C#中使用TransactionScope类(分布式事务),则须注意如下事项: 1、在项目中引用using System.Transactions命名空间&#xff08;先要在添加net组件的引用&#xff09;; 2、具体示例如下&#xff1a; public static void sendMessage(){ TransactionOptions tran…

网络通道数2的倍数_限流笔记-通道限流(二)

在工作中的时候&#xff0c;由于我负责的一个系统需要调用很多的第3方的系统&#xff0c;可是呢&#xff0c;这些个第3方的系统的性能完全不一致&#xff0c;有的好有的坏&#xff0c;还成本都不一样&#xff0c;当然了平时把&#xff0c;直接使用成本低的就行了&#xff0c;但…

【转】[技术回顾系列]--WebService事务处理

如果在WEB服务中有这样一个场景&#xff0c;某个WEB服务的方法要执行两个任务&#xff0c;它首先要在数据库中创建一个新表&#xff0c;接着调用对象来收集和格式化数据&#xff0c;并在新表中插入数据。象这样的一组方法&#xff0c;我们必须保证他们都成功执行&#xff0c;否…

mysql题目_MySQL练习题

创建下列表并创建相关约束问题1&#xff1a;查询出成绩表&#xff0c;而且student_id 后面要有对应的学生名&#xff0c;course_id 后面要有对应的课程名.1 SELECT2 score.sid,3 score.student_id,4 student.sname,5 score.course_id,6 course.cname,7 score.number8 FROM scor…

【转】BASE64编码规则

Base64编码要求把3个8位字节&#xff08;3*824&#xff09;转化为4个6位的字节&#xff08;4*624&#xff09;&#xff0c;之后在6位的前面补两个0&#xff0c;形成8位一个字节的形式。&#xff08;将字符串转换为二进制&#xff0c;从前往后&#xff0c;每6位一取&#xff0c;…

查看mysql数据库的死锁日志_【MySQL】mysql死锁以及死锁日志分析

1.死锁的概念死锁&#xff1a;死锁一般是事务相互等待对方资源&#xff0c;最后形成环路造成的。对于死锁&#xff0c;数据库处理方法&#xff1a;牺牲一个连接&#xff0c;保证另外一个连接成功执行。发生死锁会返回ERROR&#xff1a;1213 错误提示&#xff0c;大部分的死锁In…

【转】二进制文件和ASCII文件有何区别

二进制文件和ASCII文件&#xff08;即文本文件&#xff09;的区别&#xff0c;对于和计算机亲近时间尚短的同学是个难题。本文用简单的例子&#xff0c;试图展示其中的道道&#xff0c;希望能对菜鸟们有些帮助。 1、一个例子&#xff1a;两种100000 有程序&#xff1a; #includ…

mysql优化和索引_mysql优化和索引

表的优化1.定长与变长分离如 int,char(4),time核心且常用字段&#xff0c;建成定长&#xff0c;放在一张表&#xff1b;而varchar,text,blob这种变长字段适合单放一张表&#xff0c;用主键与核心表关联。2.常用字段和不常用字段要分离3.在 1 对多需要关联统计的字段上&#xff…

【转】为什么不能使用字符流读取非文本的二进制文件?

读取文件 刚学Java的IO流部分时&#xff0c;书上说只能使用字节流去读取图片、视频等非文本二进制文件&#xff0c;不能使用字符流&#xff0c;否则文件会损坏。所以我就一直记住这一点了&#xff0c;但是为什么不能使用&#xff0c;这一直是我的一个疑惑。今天&#xff0c;我…