同系列文章:
- 国家商用密码(一)SM2椭圆曲线公钥密码算法
- 国家商用密码(二)C#:基于BouncyCastle实现SM3密码杂凑算法
- 国家商用密码(三)C#:从HashAlgorithm类派生实现SM3密码杂凑算法
- 国家商用密码(四)开放动态库及演示程序
- 国家商用密码(五)基于SM2的软件授权码生成及校验
- 国家商用密码(六)椭圆曲线加密算法密钥生成器
- 国家商用密码(七)在Apache MINA上实现二进制流的SM4编解码器
- 国家商用密码(八)在Apache MINA上实现文本流的SM4编解码器
- 国家商用密码(九)在Apache MINA上实现二进制流数据报文的SM4编解码器
- 国家商用密码(十)在Apache MINA上实现文本流数据报文的SM4编解码器
- 国家商用密码(11)在Netty 5.0.X上实现文本流的SM4编解码器
- 国家商用密码(12)在Netty 4.1.12.Final上实现文本流的SM4编解码器
- 国家商用密码(13)在DotNetty 0.4.5上实现文本流的SM4编解码器
源代码出售:
价格:壹仟元人民币
微信:splashcn
源代码:
SM4TextToMessageCodec.cs
/* ---------------------------------------------------------- * 文件名称:SM4TextToMessageCodec.cs * * 作者:秦建辉 * * 微信:splashcn * * 博客:http://www.firstsolver.com/wordpress/ * * 开发环境: * Visual Studio V2017 * .NET Framework 4.5.2 * DotNetty 0.4.5 * * 版本历史: * V1.0 2017年06月28日 * 基于DotNetty框架的SM4文本编解码器 * * 参考资料: * https://github.com/Azure/DotNetty * ------------------------------------------------------------ */ using Com.FirstSolver.Security; using DotNetty.Buffers; using DotNetty.Common.Utilities; using DotNetty.Transport.Channels; using System; using System.Text; using System.Threading.Tasks; namespace Com.FirstSolver.Netty { /// <summary> /// SM4文本编解码器 /// </summary> public class SM4TextToMessageCodec : ChannelHandlerAdapter { /// <summary> /// 属性键:加密器 /// </summary> private static readonly AttributeKey<SM4> KEY_ENCRYPTOR = AttributeKey<SM4>.ValueOf(typeof(SM4TextToMessageCodec), "Encryptor"); /// <summary> /// 属性键:解密器 /// </summary> private static readonly AttributeKey<SM4> KEY_DECRYPTOR = AttributeKey<SM4>.ValueOf(typeof(SM4TextToMessageCodec), "Decryptor"); /// <summary> /// 属性键:通信密钥 /// </summary> private static readonly AttributeKey<string> KEY_SECRETKEY = AttributeKey<string>.ValueOf(typeof(SM4TextToMessageCodec), "SecretKey"); /// <summary> /// 构造函数 /// </summary> /// <param name="mode">运算模式,支持ECB、CBC、CFB、OFB(默认)、PCBC</param> /// <param name="padding">填充模式,支持PKCS7(默认)、ANSIX923、ISO10126、ISO7816、Zeros、None</param> /// <param name="codepage">字符集代码页,默认为UTF-8字符集</param> public SM4TextToMessageCodec(CipherMode mode = CipherMode.OFB, PaddingMode padding = PaddingMode.PKCS7, int codepage = 65001) { if ((int)mode > 4) throw new ArgumentOutOfRangeException("Unsupported cipher mode!"); Mode = mode; Padding = padding; Codepage = codepage; mEncoding = Encoding.GetEncoding(codepage); } public override bool IsSharable => true; public virtual bool AcceptOutboundMessage(object message) => message is string; public virtual bool AcceptInboundMessage(object message) => message is IByteBuffer; /// <summary> /// 异步写操作 /// </summary> /// <param name="context">通道处理器上下文</param> /// <param name="message">要发送的文本字符串</param> /// <returns>异步操作</returns> public override Task WriteAsync(IChannelHandlerContext context, object message) { if (AcceptOutboundMessage(message)) { // 将字符串转换为字节数组 byte[] Source = mEncoding.GetBytes((string)message); // 获取加密密钥 string SecretKey = context.GetAttribute<string>(KEY_SECRETKEY).Get(); if (!string.IsNullOrEmpty(SecretKey)) { // 对数据进行对称加密 SM4 Encryptor = GetEncryptor(context, SecretKey); Source = Encryptor.TransformFinalBlock(Source, 0, Source.Length); } IByteBuffer Buffer = context.Allocator.Buffer(4 + Source.Length); Buffer.WriteInt(Source.Length); // 按BigEndian字节序写入长度信息 Buffer.WriteBytes(Source); return context.WriteAsync(Buffer); } else { return context.WriteAsync(message); } } /// <summary> /// 通道读操作 /// </summary> /// <param name="context">通道处理器上下文</param> /// <param name="message">要处理的消息对象</param> public override void ChannelRead(IChannelHandlerContext context, object message) { if (AcceptInboundMessage(message)) { IByteBuffer Buffer = (IByteBuffer)message; if (Buffer.ReadableBytes > 4) { Buffer.MarkReaderIndex(); int Size = Buffer.ReadInt(); if (Buffer.ReadableBytes >= Size) { byte[] Source = new byte[Size]; Buffer.ReadBytes(Source); // 获取解密密钥 String SecretKey = context.GetAttribute<string>(KEY_SECRETKEY).Get(); if (string.IsNullOrEmpty(SecretKey)) { // 直接输出明文数据 context.FireChannelRead(mEncoding.GetString(Source)); } else { // 输出解密后的数据 SM4 Decryptor = GetDecryptor(context, SecretKey); context.FireChannelRead(mEncoding.GetString(Decryptor.TransformFinalBlock(Source, 0, Size))); } } else { // 回到标记位置 Buffer.ResetReaderIndex(); } } } else { context.FireChannelRead(message); } } /// <summary> /// 通道处理器关闭异步处理 /// </summary> /// <param name="context">通道处理器上下文</param> /// <returns>通道处理器关闭异步任务</returns> public override Task CloseAsync(IChannelHandlerContext context) { // 释放加密器 SM4 Encryptor = context.GetAttribute<SM4>(KEY_ENCRYPTOR).Get(); if (Encryptor != null) Encryptor.Dispose(); // 释放解密器 SM4 Decryptor = context.GetAttribute<SM4>(KEY_DECRYPTOR).Get(); if (Decryptor != null) Decryptor.Dispose(); return base.CloseAsync(context); } /// <summary> /// 获取加密器 /// </summary> /// <param name="context">通道处理器上下文内容</param> /// <param name="secretKey">通信密钥</param> /// <returns>加密器</returns> private SM4 GetEncryptor(IChannelHandlerContext context, string secretKey) { SM4 Encryptor = context.GetAttribute<SM4>(KEY_ENCRYPTOR).Get(); if (Encryptor == null) { Encryptor = new SM4(CipherDirection.Encryption, Mode, Padding); byte[] DerivedVector = SM3.KDF(Encoding.UTF8.GetBytes(secretKey), 32); // 对称加密私密密钥 byte[] Key = new byte[16]; Array.Copy(DerivedVector, 0, Key, 0, 16); // 对称加密初始向量 byte[] IV = new byte[16]; Array.Copy(DerivedVector, 16, IV, 0, 16); // 初始化加密器和解密器 Encryptor.Initialize(Key, IV); context.GetAttribute<SM4>(KEY_ENCRYPTOR).Set(Encryptor); } return Encryptor; } /// <summary> /// 获取解密器 /// </summary> /// <param name="context">通道处理器上下文内容</param> /// <param name="secretKey">通信密钥</param> /// <returns>解密器</returns> private SM4 GetDecryptor(IChannelHandlerContext context, string secretKey) { SM4 Decryptor = context.GetAttribute<SM4>(KEY_DECRYPTOR).Get(); if (Decryptor == null) { Decryptor = new SM4(CipherDirection.Decryption, Mode, Padding); byte[] DerivedVector = SM3.KDF(Encoding.UTF8.GetBytes(secretKey), 32); // 对称加密私密密钥 byte[] Key = new byte[16]; Array.Copy(DerivedVector, 0, Key, 0, 16); // 对称加密初始向量 byte[] IV = new byte[16]; Array.Copy(DerivedVector, 16, IV, 0, 16); // 初始化加密器和解密器 Decryptor.Initialize(Key, IV); context.GetAttribute<SM4>(KEY_DECRYPTOR).Set(Decryptor); } return Decryptor; } /// <summary> /// 获取通信密钥 /// </summary> /// <param name="context">通道处理器上下文内容</param> /// <returns>通信密钥</returns> public static string GetSecretKey(IChannelHandlerContext context) { return context.GetAttribute<string>(KEY_SECRETKEY).Get(); } /// <summary> /// 设置通信密钥 /// </summary> /// <param name="context">通道处理器上下文内容</param> /// <param name="key">通信密钥</param> public static void SetSecretKey(IChannelHandlerContext context, string key) { context.GetAttribute<string>(KEY_SECRETKEY).Set(key); } /// <summary> /// 运算模式,支持ECB、CBC、CFB、OFB(默认)、PCBC /// </summary> public readonly CipherMode Mode; /// <summary> /// 填充模式,支持PKCS7(默认)、ANSIX923、ISO10126、ISO7816、Zeros、None /// </summary> public readonly PaddingMode Padding; /// <summary> /// 字符集代码页,默认为65001(UTF-8) /// </summary> public readonly int Codepage; /// <summary> /// 字符编码 /// </summary> private readonly Encoding mEncoding; } }
例子程序: