C#实现网络传输数据加密

时间:2022-06-01 12:55:10

标签:

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

数据解密