C#实现网络传输数据加密
1. 分组密码
分组密码是将明文消息编码表示后数字序列划分成长为n的分组,各组分别在密钥的作用下进行变换输出等长的数字序列,即密文。一次加密一个数据组,加解密所使用的是同一密钥,故其通常也称为对称加密。分组长n各种不同的对称加密算法取值不同(DES和TripleDES为64位,AES默认为128位,也可以为192位和256位),在对明文消息进行分组时如果最后个分组小于n,则要进行数据填充,使分组长达到n才能进行后续的加密处理。.net平台提供的加密类都很好的处理了上述问题,所以在用C#语言进行实际编码能很简便的完成加解密操作。
Rijndael算法作为AES的一种,已经取代TripleDES(三重DES)成为新的数据加密标准。其分组长度及密钥长度都可变,且比DES算法都要长,使其也具有了更高的安全性。本文的示例程序采用的就是Rijndael算法。
2. 运行模式
分组密码在加密时,明文分组的长度是固定,而实用中待加密消息的数据量是不定的,相邻的两个分组加解密时是否相关,就产生了不同的运行模式。下面主要介绍两种常用的分组密码运行模式
1. ECB模式
ECB模式是最简单的运行模式,各个分组使用相同的密钥进行加密,如图1所示。
图1. ECB模式示意图
当密钥取定时,对明文的每一个分组,都有一个唯一的密文与之对应。这也造就了ECB模式的最大特性,同一明文分组在消息中重复出现的话,产生的密文分组也相同。故ECB用于长消息时可能不够安全,如果消息有固定结构,攻击者可能找出这种关系。但因为在ECB模式中,各分组加解密相互独立,所以很方便进行并行计算,提高大型数据加解密的运行效率。
2. CBC模式
为了解决ECB模式的安全缺陷,可以让重复的明文分组产生不同的密文分组,CBC模式就可满足这一要求。如图2所示,在CBC模式中,一次对一个明文分组加密,每次加密使用同一密钥,加密算法的输入是当前明文分组和前一次密文分组的异或,因此加密算法的输入不会显示出于这次的明文之间的固定关系,所以重复的明文分组不会在密文中暴露出这种重复关系。
图2 CBC模式示意图
在产生第一个密文分组时,需要有一个IV与第一个明文分组异或。解密时,IV和解密算法对第一个密文分组的输出进行异或以恢复第一个明文分组。IV和密钥一样对于收发双方都是已知的,为了使安全性最高,IV应像密钥一样被保护。
在.NET平台提供的分组加密类默认使用的是CBC模式,但是可以根据需要更改此默认设置。
3. 数据加解密
在实现数据加解密主要涉及到System.Security.Cryptography下的RijndaelManaged和CryptoStream类。前面提到.NET平台的分组加密类默认使用的是CBC模式,所以首先要生成密钥Key和IV。在生成RijndaelManaged实例时默认会生成一组长度为16字节随机的Key和IV,在本示例中为了省去通信双方的密钥交换过程,直接指定了Key和IV,加解密都相同。具体看代码,看注释。
数据加密
1 //创建RijndaelManaged实例
2 RijndaelManaged RMCrypto = new RijndaelManaged();
3 //byte[] key = RMCrypto.Key;
4 //byte[] IV = RMCrypto.IV;
5 //初始化Key,IV
6 byte[] Key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
7 byte[] IV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
8
9 Console.WriteLine("connecte successed! Enter the message to send:");
10 string sMessage = Console.ReadLine();
11 //把明文消息转换成UTF8编码的字节流,避免乱码
12 byte[] messageByte = Encoding.UTF8.GetBytes(sMessage);
13 //实例化一个MemoryStream用于存放加密后的数据流
14 MemoryStream mStream = new MemoryStream();
15 //创建用于加密的CryptoStream实例
16 CryptoStream CryptStream = new CryptoStream(mStream,
17 RMCrypto.CreateEncryptor(Key, IV),
18 CryptoStreamMode.Write);
19 //把明文消息字节流写入到CryptoStream中,进行加密处理
20 CryptStream.Write(messageByte,0,messageByte.Length);
21 //把CryptoStream中的数据更新到MemoryStream中
22 CryptStream.FlushFinalBlock();
23 //把加密后的数据流转换成字节流
24 byte[] encryptoByte = mStream.ToArray();
数据解密
1 //创建一个MemoryStream实例,存放收到的加密数据字节流
2 MemoryStream encryptoStream = new MemoryStream(encryptoByte);
3 //创建RijndaelManaged实例
4 RijndaelManaged RMCrypto = new RijndaelManaged();
5 //byte[] key = RMCrypto.Key;
6 //byte[] IV = RMCrypto.IV;
7 //初始化Key,IV
8 byte[] Key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
9 byte[] IV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
10
11
12 //创建用于解密的CryptoStream实例
13 CryptoStream CryptStream = new CryptoStream(encryptoStream,
14 RMCrypto.CreateDecryptor(Key, IV),
15 CryptoStreamMode.Read);
16
17 //创建StreamReader实例,从CryptoStream中读出数据,
18 //StreamReader默认使用UTF8编码读出的数据
19 StreamReader SReader = new StreamReader(CryptStream);
20
21 //输出解密后的消息.
22 Console.WriteLine("The decrypted original message: {0}",SReader.ReadToEnd());
4. 数据传输
数据传输使用的是TCP连接,.net平台也对Socket进行了很好的封装,使网络IO操作非常方便。在密文数据发送前被编码成Base64形式的字符串,一个是方便加密数据的正常显示,另一方面是便于数据接收端在接收字节流的数据时便于转码成字符串。Base64是用64个可打印的ASCII码字符来表示二进制数据,所以Base64字符串与字节流的转换是一对一的转换,即一个字符对应一个字节,这样在进行字节流与字符串间的转换时不会因编码方式的不同出现偏差,造成后续的解密操作出现异常。
客户端
1 //创建TCP连接
2 TcpClient TCP = new TcpClient("localhost", 11000);
3
4 //从TCP连接中获得网络数据流
5 NetworkStream NetStream = TCP.GetStream();
6
7 //便于显示,将加密后的数据字节流转成Base64编码的字符串
8 string encryptBase64 = Convert.ToBase64String(encryptoByte);
9 //将字符串转成字节流
10 encryptoByte = Encoding.ASCII.GetBytes(encryptBase64);
11
12 //把加密后的数据写入到NetworkStream中,发送到服务端。
13 NetStream.Write(encryptoByte, 0, encryptoByte.Length);
14 Console.WriteLine("The encryptoed message: {0}", encryptBase64);
15 Console.WriteLine("The message was sent.");
服务端
1 //初始化TCPListen绑定IP地址和监听端口
2 TcpListener TCPListen = new TcpListener(IPAddress.Any, 11000);
3
4 //开始监听
5 TCPListen.Start();
6
7 //每隔五秒钟,检查是否有连接
8 while (!TCPListen.Pending())
9 {
10 Console.WriteLine("Still listening. Will try in 5 seconds.");
11 Thread.Sleep(5000);
12 }
13
14 //接受TCP连接.
15 TcpClient TCP = TCPListen.AcceptTcpClient();
16
17 //为此连接创建NetworkStream.
18 NetworkStream NetStream = TCP.GetStream();
19
20 //循环从NetworkStream中读出数据
21 string encryptoString = "";
22 int bytes;
23 while (true)
24 {
25 byte[] byteMessage = new byte[10];
26 bytes = NetStream.Read(byteMessage, 0, 10);
27 if (bytes <= 0)
28 {
29 break;
30 }
31 //加密后的数据是通过Base64编码成字符串后发送,可直接通过ASCII编码将字节转成ASCII码字符
32 //组装成完整的Bas64编码的字符串
33 encryptoString += Encoding.ASCII.GetString(byteMessage,0,bytes);
34 }
35 Console.WriteLine("The Encryptoed Message: {0}", encryptoString);
36 //把Base64编码的字符串转换成字节流
37 byte[] encryptoByte = Convert.FromBase64String(encryptoString);
因CryptoStream类使用的派生自Stream的类进行初始化,所以在本示例程序中可以直接使用NetworStream替代MemoryStream创建CryptoStream示例。示例程序见MSDN-加密数据。示例程序使用MemoryStream是便于获得加密后的数据。
此文非原创
C#实现网络传输数据加密的更多相关文章
- c#网络传输
接着前面简单讲的,给大家聊聊服务开发. 网络传输 先说网络传输开发,总体来说,可以看成4中模型 我们把传输过程看做网线,那么在通过传输的过程中.2边就涉及池化问题,也就是我们常见的异步传输. 在业务端 ...
- ASP.NET知识总结(1.网络传输层)
1.网络传输层 1应用层(HTTP.FTP.SMTP)报文Message 2传输层(TCP.UDP)报文段Segment,为运行在不同主机上的应用程序进程间提供数据 传输服务.通过套接字(Socket ...
- atitit.二进制数据无损转字符串网络传输
atitit.二进制数据无损转字符串网络传输 1. gbk的网络传输问题,为什么gbk不能使用来传输二进制数据 1 2. base64 2 3. iso-8859-1 (推荐) 2 4. utf-8 ...
- Android网络传输中必用的两个加密算法:MD5 和 RSA (附java完成测试代码)
MD5和RSA是网络传输中最常用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,只能加密而不能解密.比如明 ...
- Android IOS WebRTC 音视频开发总结(五七)-- 网络传输上的一种QoS方案
本文主要介绍一种QoS的解决方案,文章来自博客园RTC.Blacker,欢迎关注微信公众号blacker,更多详见www.rtc.help QoS出现的背景: 而当网络发生拥塞的时候,所有的数据流都有 ...
- udp 视频包网络传输花屏
视频数据传输在传输层可以选择TCP或者UDP,TCP面向连接,传输中断,发送端是知道的.TCP传输的好处是不丢包,坏处是网络不太好的情况下会越堵越严重.UDP非面向连接,发送端只管发送数据,接收端有没 ...
- 网络传输速度bps与下载文件所需时间的换算
相信很多同志都非常关注自己家的计算机上网的宽带是多少.关心单位上网的宽带是多少! 但是很多同志都经常误解网络传输速度,以至于责备网络接入商(电信.网通.铁通等单位)欺骗用户,限制上网的速度! 本文,就 ...
- App安全之网络传输安全
移动端App安全如果按CS结构来划分的话,主要涉及客户端本身数据安全,Client到Server网络传输的安全,客户端本身安全又包括代码安全和数据存储安全.所以当我们谈论App安全问题的时候一般来说在 ...
- Android网络传输中必用的两个加密算法:MD5 和 RSA (附java完毕測试代码)
MD5和RSA是网络传输中最经常使用的两个算法,了解这两个算法原理后就能大致知道加密是怎么一回事了.但这两种算法使用环境有差异,刚好互补. 一.MD5算法 首先MD5是不可逆的,仅仅能加密而不能解密. ...
随机推荐
- C++编程对缓冲区的理解
本文转自:http://www.vckbase.com/index.php/wv/1592 什么是缓冲区 缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空 ...
- IOC(依赖注入)原理
IoC,直观地讲,就是容器控制程序之间的关系,而非传统实现中,由程序代码直接操控.这也就是所谓"控制反转"的概念所在.控制权由应用代码中转到了外部容器,控制权的转移是所谓反转.Io ...
- B - Broken Keyboard (a.k.a. Beiju Text)
Problem B Broken Keyboard (a.k.a. Beiju Text) You're typing a long text with a broken keyboard. Well ...
- Steps to disable DRLs with GM Tech2 scanner
It is possible to get daytime running time disabled manually. But the problem can be easily settled ...
- MSP430常见问题之IO端口类
Q1:请问430 的I/O 中断能不能可靠的响应60ns 的脉冲信号, 就是来了一个60ns 的脉冲,430 的中断会有丢失吗?A1:端口支持的最高8M的时钟,无法响应这么快的频率. Q2:430是3 ...
- 转:OpenResty最佳实践(推荐了解lua语法)
看点: 1. Lua 语法的说明, 排版清晰易懂. 转: https://moonbingbing.gitbooks.io/openresty-best-practices/content/lua/m ...
- fatal error LNK1168: cannot open Debug/opreat.exe for writing
问题:LINK : fatal error LNK1168: cannot open Debug/opreat.exe for writing Error executing li ...
- 锋利的jQuery第2版学习笔记4、5章
第4章,jQuery中的事件和动画 注意:使用的jQuery版本为1.7.1 jQuery中的事件 JavaScript中通常使用window.onload方法,jQuery中使用$(document ...
- Javascript之登陆验证
匹配中文字符的正则表达式: [\u4e00-\u9fa5] 匹配双字节字符(包括汉字在内):[^\x00-\xff] 匹配空行的正则表达式:\n[\s| ]*\r 匹配网址URL的正则表达式:http ...
- ssh git设置命令行
#列出key ls -al ~/.ssh #生成key ssh-keygen -t rsa -b -C "your_email@example.com" #判断ssh-agent可 ...