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

C#实现SM3国密加密

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

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

1.1常规处理

 

    /// <summary>/// General/// </summary>public abstract class GeneralDigest : IDigest{/// <summary>/// 内部缓冲区的大小/// </summary>private const int ByteLength = 64;/// <summary>/// 消息摘要/// </summary>private readonly byte[] XBuf;/// <summary>/// 待更新的消息摘要的索引/// </summary>private int XBufOff;/// <summary>/// 待更新的消息摘要的大小/// </summary>private long ByteCount;/// <summary>/// 构造函数/// </summary>internal GeneralDigest(){XBuf = new byte[4];}/// <summary>/// 复制构造函数/// </summary>/// <param name="t"></param>internal GeneralDigest(GeneralDigest t){XBuf = new byte[t.XBuf.Length];Array.Copy(t.XBuf, 0, XBuf, 0, t.XBuf.Length);XBufOff = t.XBufOff;ByteCount = t.ByteCount;}/// <summary>/// 用一个字节更新消息摘要。/// </summary>/// <param name="input"></param>public void Update(byte input){XBuf[XBufOff++] = input;if (XBufOff == XBuf.Length){ProcessWord(XBuf, 0);XBufOff = 0;}ByteCount++;}/// <summary>/// 用字节块更新消息摘要/// </summary>/// <param name="input"></param>/// <param name="inOff"></param>/// <param name="length"></param>public void BlockUpdate(byte[] input, int inOff, int length){//更新当前消息摘要while ((XBufOff != 0) && (length > 0)){Update(input[inOff]);inOff++;length--;}//处理完整的消息摘要while (length > XBuf.Length){ProcessWord(input, inOff);inOff += XBuf.Length;length -= XBuf.Length;ByteCount += XBuf.Length;}//填充剩余的消息摘要while (length > 0){Update(input[inOff]);inOff++;length--;}}/// <summary>/// 产生最终的摘要值/// </summary>public void Finish(){long bitLength = (ByteCount << 3);//添加字节Update(unchecked((byte)128));while (XBufOff != 0) Update(unchecked((byte)0));ProcessLength(bitLength);ProcessBlock();}/// <summary>/// 重启/// </summary>public virtual void Reset(){ByteCount = 0;XBufOff = 0;Array.Clear(XBuf, 0, XBuf.Length);}/// <summary>/// 摘要应用其压缩功能的内部缓冲区的大小/// </summary>/// <returns></returns>public int GetByteLength(){return ByteLength;}/// <summary>/// 处理消息摘要/// ABCDEFGH 串联/// </summary>/// <param name="input"></param>/// <param name="inOff"></param>internal abstract void ProcessWord(byte[] input, int inOff);internal abstract void ProcessLength(long bitLength);/// <summary>/// 迭代压缩/// </summary>internal abstract void ProcessBlock();/// <summary>/// 算法名称/// </summary>public abstract string AlgorithmName { get; }/// <summary>/// 消息摘要生成的摘要的大小/// </summary>/// <returns></returns>public abstract int GetDigestSize();/// <summary>/// 关闭摘要,产生最终的摘要值。doFinal调用使摘要复位。/// </summary>/// <param name="output"></param>/// <param name="outOff"></param>/// <returns></returns>public abstract int DoFinal(byte[] output, int outOff);}

复制代码

1.2 执行无符号按位右移

复制代码

    /// <summary>/// 使用指定的数字执行无符号按位右移/// </summary>public class SupportClass{/// <summary>/// 使用指定的数字执行无符号按位右移/// </summary>/// <param name="number">要操作的编号</param>/// <param name="bits">要移位的比特数</param>/// <returns>移位操作产生的数字</returns>public static int URShift(int number, int bits){if (number >= 0)return number >> bits;elsereturn (number >> bits) + (2 << ~bits);}/// <summary>/// 使用指定的数字执行无符号按位右移/// </summary>/// <param name="number">要操作的编号</param>/// <param name="bits">要移位的比特数</param>/// <returns>移位操作产生的数字</returns>public static int URShift(int number, long bits){return URShift(number, (int)bits);}/// <summary>/// 使用指定的数字执行无符号按位右移/// </summary>/// <param name="number">要操作的编号</param>/// <param name="bits">要移位的比特数</param>/// <returns>移位操作产生的数字</returns>public static long URShift(long number, int bits){if (number >= 0)return number >> bits;elsereturn (number >> bits) + (2L << ~bits);}/// <summary>/// 使用指定的数字执行无符号按位右移/// </summary>/// <param name="number">要操作的编号</param>/// <param name="bits">要移位的比特数</param>/// <returns>移位操作产生的数字</returns>public static long URShift(long number, long bits){return URShift(number, (int)bits);}}

复制代码

1.3 SM3处理

复制代码

    /// <summary>///  /// ⊕ 等价于 ^/// ^ 等价于 &/// v 等价于 |/// </summary>public class SM3Digest : GeneralDigest{public override string AlgorithmName{get{return "SM3";}}/// <summary>/// 消息摘要生成的摘要的大小/// </summary>/// <returns></returns>public override int GetDigestSize(){return DigestLength;}/// <summary>/// SM3算法产生的哈希值大小/// </summary>private const int DigestLength = 32;/// <summary>/// 初始值IV/// </summary>private static readonly int[] IV = new int[] {0x7380166f, 0x4914b2b9, 0x172442d7,unchecked((int)0xda8a0600), unchecked((int)0xa96f30bc), 0x163138aa,unchecked((int)0xe38dee4d), unchecked((int)0xb0fb0e4e)};/// <summary>/// 备份的字寄存器/// </summary>private readonly int[] v = new int[8];/// <summary>/// 使用中的字寄存器/// </summary>private readonly int[] v_ = new int[8];private static readonly int[] X0 = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };private readonly int[] X = new int[68];private int xOff;/// <summary>/// 0到15的Tj常量/// </summary>private readonly int TOne = 0x79cc4519;/// <summary>/// 16到63的Tj常量/// </summary>private readonly int TSecond = 0x7a879d8a;public SM3Digest(){Reset();}/// <summary>/// 复制构造函数/// </summary>/// <param name="t"></param>public SM3Digest(SM3Digest t) : base(t){Array.Copy(t.X, 0, X, 0, t.X.Length);xOff = t.xOff;Array.Copy(t.v, 0, v, 0, t.v.Length);}/// <summary>/// 将复制的对象状态还原到该对象。/// 此方法的实现应尝试避免或最小化内存分配以执行重置。/// </summary>public override void Reset(){base.Reset();Array.Copy(IV, 0, v, 0, IV.Length);xOff = 0;Array.Copy(X0, 0, X, 0, X0.Length);}internal override void ProcessBlock(){int j;int[] ww = X;//64位比特串int[] ww_ = new int[64];#region 块消息扩展//消息扩展16 TO 67for (j = 16; j < 68; j++){ww[j] = P1(ww[j - 16] ^ ww[j - 9] ^ (Rotate(ww[j - 3], 15))) ^ (Rotate(ww[j - 13], 7)) ^ ww[j - 6];}//消息扩展0 TO 63for (j = 0; j < 64; j++){ww_[j] = ww[j] ^ ww[j + 4];}#endregion#region 压缩函数int[] vv = v;int[] vv_ = v_;//A,B,C,D,E,F,G,H为字寄存器Array.Copy(vv, 0, vv_, 0, IV.Length);//中间变量SS1,SS2,TT1,TT2int SS1, SS2, TT1, TT2;int aaa;//将消息分组B(i)划分为16个字for (j = 0; j < 16; j++){aaa = Rotate(vv_[0], 12);SS1 = aaa + vv_[4] + Rotate(TOne, j);SS1 = Rotate(SS1, 7);SS2 = SS1 ^ aaa;TT1 = FFOne(vv_[0], vv_[1], vv_[2]) + vv_[3] + SS2 + ww_[j];TT2 = GGOne(vv_[4], vv_[5], vv_[6]) + vv_[7] + SS1 + ww[j];#region 更新各个寄存器vv_[3] = vv_[2];vv_[2] = Rotate(vv_[1], 9);vv_[1] = vv_[0];vv_[0] = TT1;vv_[7] = vv_[6];vv_[6] = Rotate(vv_[5], 19);vv_[5] = vv_[4];vv_[4] = P0(TT2);#endregion}for (j = 16; j < 64; j++){aaa = Rotate(vv_[0], 12);SS1 = aaa + vv_[4] + Rotate(TSecond, j);SS1 = Rotate(SS1, 7);SS2 = SS1 ^ aaa;TT1 = FFSecond(vv_[0], vv_[1], vv_[2]) + vv_[3] + SS2 + ww_[j];TT2 = GGSecond(vv_[4], vv_[5], vv_[6]) + vv_[7] + SS1 + ww[j];#region 更新各个寄存器vv_[3] = vv_[2];vv_[2] = Rotate(vv_[1], 9);vv_[1] = vv_[0];vv_[0] = TT1;vv_[7] = vv_[6];vv_[6] = Rotate(vv_[5], 19);vv_[5] = vv_[4];vv_[4] = P0(TT2);#endregion}#endregion//256比特的杂凑值y =vv_(j+1) ABCDEFGHfor (j = 0; j < 8; j++){vv[j] ^= vv_[j];}// ResetxOff = 0;Array.Copy(X0, 0, X, 0, X0.Length);}internal override void ProcessWord(byte[] in_Renamed, int inOff){int n = in_Renamed[inOff] << 24;n |= (in_Renamed[++inOff] & 0xff) << 16;n |= (in_Renamed[++inOff] & 0xff) << 8;n |= (in_Renamed[++inOff] & 0xff);X[xOff] = n;if (++xOff == 16){ProcessBlock();}}internal override void ProcessLength(long bitLength){if (xOff > 14){ProcessBlock();}X[14] = (int)(SupportClass.URShift(bitLength, 32));X[15] = (int)(bitLength & unchecked((int)0xffffffff));}/// <summary>/// 写入到大端/// </summary>/// <param name="n"></param>/// <param name="bs"></param>/// <param name="off"></param>public static void IntToBigEndian(int n, byte[] bs, int off){bs[off] = (byte)(SupportClass.URShift(n, 24));bs[++off] = (byte)(SupportClass.URShift(n, 16));bs[++off] = (byte)(SupportClass.URShift(n, 8));bs[++off] = (byte)(n);}/// <summary>/// 关闭摘要,产生最终的摘要值。doFinal调用使摘要复位。/// </summary>/// <param name="out_Renamed"></param>/// <param name="outOff"></param>/// <returns></returns>public override int DoFinal(byte[] out_Renamed, int outOff){Finish();for (int i = 0; i < 8; i++){IntToBigEndian(v[i], out_Renamed, outOff + i * 4);}Reset();return DigestLength;}/// <summary>/// x循环左移n比特运算/// </summary>/// <param name="x"></param>/// <param name="n"></param>/// <returns></returns>private static int Rotate(int x, int n){return (x << n) | (SupportClass.URShift(x, (32 - n)));}#region 置换函数/// <summary>/// 置换函数P0/// </summary>/// <param name="x"></param>/// <returns></returns>private static int P0(int x){return (x) ^ Rotate(x, 9) ^ Rotate(x, 17);}/// <summary>/// 置换函数P1/// </summary>/// <param name="x"></param>/// <returns></returns>private static int P1(int x){return (x) ^ Rotate(x, 15) ^ Rotate(x, 23);}#endregion#region 布尔函数/// <summary>/// 0到15的布尔函数FF (X⊕^Y⊕Z)/// </summary>/// <param name="X"></param>/// <param name="Y"></param>/// <param name="Z"></param>/// <returns></returns>private static int FFOne(int X, int Y, int Z){return (X ^ Y ^ Z);}/// <summary>/// 16到63的布尔函数FF/// </summary>/// <param name="X"></param>/// <param name="Y"></param>/// <param name="Z"></param>/// <returns></returns>private static int FFSecond(int X, int Y, int Z){return ((X & Y) | (X & Z) | (Y & Z));}/// <summary>/// 0到15的布尔函数GG/// </summary>/// <param name="X"></param>/// <param name="Y"></param>/// <param name="Z"></param>/// <returns></returns>private static int GGOne(int X, int Y, int Z){return (X ^ Y ^ Z);}/// <summary>/// 16到63的布尔函数GG/// </summary>/// <param name="X"></param>/// <param name="Y"></param>/// <param name="Z"></param>/// <returns></returns>private static int GGSecond(int X, int Y, int Z){return ((X & Y) | (~X & Z));}#endregion}

复制代码

1.4调用

复制代码

    /// <summary>/// Sm3算法(10进制的ASCII)  /// 在SHA-256基础上改进实现的一种算法  /// 对标国际MD5算法和SHA算法/// </summary>public static class Sm3Crypto{/// <summary>/// sm3加密(使用自定义密钥)/// </summary>/// <param name="data"></param>/// <returns></returns>public static byte[] ToSM3byte(string data, string key){byte[] msg1 = Encoding.Default.GetBytes(data);byte[] key1 = Encoding.Default.GetBytes(key);KeyParameter keyParameter = new KeyParameter(key1); SM3Digest sm3 = new SM3Digest();HMac mac = new HMac(sm3);//带密钥的杂凑算法mac.Init(keyParameter);mac.BlockUpdate(msg1, 0, msg1.Length);byte[] result = new byte[mac.GetMacSize()];mac.DoFinal(result, 0);return Hex.Encode(result);}/// <summary>/// sm3加密/// </summary>/// <param name="data"></param>/// <returns></returns>public static byte[] ToSM3byte(this string data){ var msg = data.ToHexByte();//把字符串转成16进制的ASCII码 SM3Digest sm3 = new SM3Digest();sm3.BlockUpdate(msg, 0, msg.Length);byte[] md = new byte[sm3.GetDigestSize()];//SM3算法产生的哈希值大小sm3.DoFinal(md, 0);return Hex.Encode(md);}}

 

 

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

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

相关文章

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…

【转】对称加密和分组加密中的四种模式(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…

【转】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…

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

在工作中的时候&#xff0c;由于我负责的一个系统需要调用很多的第3方的系统&#xff0c;可是呢&#xff0c;这些个第3方的系统的性能完全不一致&#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…

查看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…

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

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

mysql更新一条语句_MySQL一条更新语句是如何执行的

一条查询语句是经过连接器 分析器 优化器 执行器等功能模块&#xff0c;最后到达存储引擎。image以下所说的都基于InnoDb引擎。当有一条记录需要更新的时候&#xff0c;InnoDB引擎会先把记录写到redo log里面&#xff0c;并更新内存&#xff0c;这个时候更新就算完成了。InnoDb…

cesium获取模型实时坐标_Cesium 顶点着色器中求解模型坐标

1. 由世界坐标转模型坐标顶点着色器&#xff1a;attribute vec3 position3DHigh;attribute vec3 position3DLow;attribute vec3 normal;attribute vec2 st;attribute float batchId;varying vec3 v_positionEC;varying vec3 v_normalEC;varying vec2 v_st;void main(){vec3 pos…

【转】关于CLR内存管理一些深层次的讨论[上篇]

半年之前&#xff0c;PM让我在部门内部进行一次关于“内存泄露”的专题分享&#xff0c;我为此准备了一份PPT。今天无意中将其翻出来&#xff0c;觉得里面提到的关于CLR下关于内存管理部分的内存还有点意思。为此&#xff0c;今天按照PPT的内容写了一篇文章。本篇文章不会再讨论…

【转】.NET Remoting

.Net Remoting提供了一种允许一个应用域中的对象与另一个应用域中的对象进行交互的框架。是.NET框架中的一个重要技术改进,它用于减轻运行应用程序的系统开销. 中文名 .Net Remoting 作 用 减轻运行应用程序的系统开销 目录 1 介绍2 .NET Remoting的原理 ▪ 1.NET Rem…

python多重赋值技巧_python教程12课:多元赋值、多重赋值、运算符以及判断字符串类型...

# 多元赋值&#xff1a;# x,y,z 和 1,2,‘String是两个元组&#xff0c;只不过元组的 () 被省略掉了x, y ,z 1, 2, Stringprint(x, y, z)(x, y ,z) (3, 4, String)print(x,y,z)# 一般用在交换变量值#交换变量值常规思路x 10,y 20z 30x ,y, z y,z,xprint(x,y,z)#使用多元赋值…

【转】关于CLR内存管理一些深层次的讨论[下篇]

《上篇》中我们主要讨论的是程序集&#xff08;Assembly&#xff09;和应用程序域&#xff08;AppDomain&#xff09;的话题&#xff0c;着重介绍了两个不同的程序集加载方式——独占方式和共享方式&#xff08;中立域方式&#xff09;&#xff1b;以及基于进程范围内的字符串驻…

【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈

理解堆与栈 导航 深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈 深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工作原理 深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆&#xff0c;值类型与引用类型 深入浅出图…

bi 存储过程方案_BI 系统中容易被忽视的数据源功能

BI 系统中容易被忽视的数据源功能用户在选购 BI 解决方案的时候&#xff0c;常常会更关注界面环节的功能指标&#xff0c;比如美观性、操作的流畅性、移动端支持等等。毕竟&#xff0c;BI 是要给业务人员使用的&#xff0c;这些看得见的内容一般不容易被遗漏。然而&#xff0c;…

【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工作原理

栈基本工作原理 导航 深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第一节 理解堆与栈 深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第二节 栈基本工作原理 深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆&#xff0c;值类型与引用类型 深入浅…

【转】深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing) 第三节 栈与堆,值类型与引用类型

前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC)&#xff0c;但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC)。另外&#xff0c;了解内存管理可以帮助我们理解在每一个程序中定义的每一个变量是怎样工作的。 简介 本文将介绍值类型与引用类…