Chinaunix首页 | 论坛 | 博客
  • 博客访问: 989882
  • 博文数量: 78
  • 博客积分: 1473
  • 博客等级: 上尉
  • 技术积分: 2124
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-23 12:50
文章分类

全部博文(78)

文章存档

2016年(6)

2015年(2)

2014年(13)

2013年(4)

2012年(53)

分类: 嵌入式

2012-06-23 21:28:48

 

 

在使用.NET框架提供的加密算法实现类来执行加密任务时,需要准备加密密钥和初始化向量(Initialization VectorIV)。基于对称加密的特点,在加密数据之后一定要保存好密钥和初始化向量,因为解密要用到它们。但是对于不同的数据加密,要使用不同的密钥和初始化向量,理论上每次新的加密过程都应该使用全新的密钥和初始化向量。

通常需要将加密密钥和初始化向量传递给另一个人,这时候需要使用非对称加密算法来加密密钥和初始化向量,然后在网络上传输。本节主要演示如何使用加密实践类,更多的应用内容会在本书的第四部分介绍。

那么如何创建加密密钥和初始化向量呢?有两种基本方法,一种是使用加密算法实现类的构造函数,另一种是使用GenerateIV()GenerateKey()方法生成密钥和初始化向量。

使用构造函数创建密钥和初始化向量

先测试构造函数的方法,如代码清单6-5

代码清单6-5  使用构造函数创建密钥和初始化向量

using System;

using System.Text;

using System.Security.Cryptography;

namespace Encription

{

    classProgram

    {

        staticvoid Main(string[] args)

        {

            AesCryptoServiceProvider acsp = new AesCryptoServiceProvider();

            WriteKeyAndIV(acsp);

            AesManaged am = newAesManaged();

            WriteKeyAndIV(am);

            DESCryptoServiceProvider dsp = new DESCryptoServiceProvider();

            WriteKeyAndIV(dsp);

            TripleDESCryptoServiceProvider tdsp = new TripleDESCryptoServiceProvider();

            WriteKeyAndIV(tdsp);

            RijndaelManaged rm = new RijndaelManaged();

            WriteKeyAndIV(rm);

            Console.Read();

        }

        staticvoid WriteKeyAndIV(SymmetricAlgorithm sa)

        {

            Console.WriteLine(GetStringFromByte(sa.Key));

            Console.WriteLine("*******");

            Console.WriteLine(GetStringFromByte(sa.IV));

            Console.WriteLine("--------------------------");

        }

        staticstring GetStringFromByte(byte[] bytes)

        {

            string s="";

            for (int i = 0; i < bytes.Length; i++)

            {

                s += bytes[i].ToString()+" ";

            }

            return s;

        }

    }

}

以上代码中一共有三个方法,Main方法用来初始化.NET提供的5种对称加密实例;WriteKeyAndIV方法用来输出每个实例的密钥和初始化向量;GetStringFromByte方法用来输出byte数组的原始值。现在看输出结果,是不是如预料的,已经初始化了加密密钥和初始化向量呢?如图6-11所示。

 

6-11  代码清单6-5输出结果

如图6-11所示,在控制台输出了每个加密实例的密钥和初始化向量。

使用GenerateIV()GenerateKey()方法

当需要多个密钥或者多个初始化向量的时候,就要采用GenerateIV()GenerateKey()方法。下面对代码清单6-5做简要的修改,如代码清单6-6所示。

代码清单6-6  使用GenerateIV()GenerateKey()方法

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Security.Cryptography;

namespace Encription

{

    classProgram

    {

        staticvoid Main(string[] args)

        {

            AesCryptoServiceProvider acsp = new AesCryptoServiceProvider();

            WriteKeyAndIV(acsp);

            acsp.GenerateIV();

            acsp.GenerateKey();

            WriteKeyAndIV(acsp);

            Console.Read();

        }

        staticvoid WriteKeyAndIV(SymmetricAlgorithm sa)

        {

          

            Console.WriteLine(GetStringFromByte(sa.Key));

            Console.WriteLine("*******");

            Console.WriteLine(GetStringFromByte(sa.IV));

            Console.WriteLine("--------------------------");

        }

        staticstring GetStringFromByte(byte[] bytes)

        {

            string s="";

            for (int i = 0; i < bytes.Length; i++)

            {

                s += bytes[i].ToString()+" ";

            }

            return s;

        }

    }

}

   修改很简单,Main方法中只保留了AesCryptoServiceProvider实例,再初始化该实例后,又调用它的GenerateIVGenerateKey方法,看是否产生了新的加密密钥和初始化向量。结果如图6-12所示。

6-12  代码清单6-6运行结果

如图6-12所示,可以看到使用GenerateIVGenerateKey方法后,生成了新的密钥和初始化向量。

   准备工作完成了,下面要开始真正的加密之旅了。对称加密需要和CryptoStream类的实例配合,使用加密流来实现数据加密(.NET中的内存流、文件流、网络流都可以使用)。为了示例更明了,以AesCryptoServiceProvider类为例,使用内存流来演示如何使用对称加密类加密、解密数据。先看代码清单6-7

代码清单6-7  加密解密数据示例

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Security.Cryptography;

using System.IO;

namespace Sample

{

    classProgram

    {

        staticAesCryptoServiceProvider acsp = newAesCryptoServiceProvider();

        staticvoid Main(string[] args)

        {

            byte[] key = acsp.Key;

            byte[] iv = acsp.IV;

            string s = @"xuanhun加密测试";

            byte[] sbyt = Encoding.Default.GetBytes(s);

            byte []Enb = Encript(sbyt, key, iv);

            byte []Deb = Decript(Enb, key, iv);

            Console.WriteLine(Encoding.Default.GetString(Enb));

            Console.WriteLine(Encoding.Default.GetString(Deb));

            Console.Read();

        }

 

        publicstaticbyte[] Encript(byte[] s1, byte[] key, byte[] iv)

        {

            MemoryStream mstream = newMemoryStream();

            CryptoStream cstream = newCryptoStream(mstream, acsp.CreateEncryptor(key, iv), CryptoStreamMode.Write);

            cstream.Write(s1, 0, s1.Length);

            cstream.FlushFinalBlock();

           byte[] outb1 = mstream.ToArray();

            cstream.Close();

            mstream.Close();

            return outb1;

        }

 

        publicstaticbyte[] Decript(byte[] s2, byte[] key, byte[] iv)

        {

            MemoryStream mtream2 = newMemoryStream();

            CryptoStream deStreame = newCryptoStream(mtream2, acsp.CreateDecryptor(key, iv), CryptoStreamMode.Write);

            deStreame.Write(s2, 0, s2.Length);

            deStreame.FlushFinalBlock();

            byte[] outs2 = mtream2.ToArray();

            mtream2.Close();

            deStreame.Close();

            return outs2;

        }

 

        publicstaticbyte[] GetByteFromstring(string s)

        {

            returnEncoding.Default.GetBytes(s);

        }

    }

}

以上代码首先创建了AesCryptoServiceProvider实例,然后在Main方法中使用了局部变量keyiv来保存该实例的加密密钥和初始化向量,字符串s是要加密的原始字符串。局部变量sbyte保存了将字符串s转化为byte数组后的结果。加密解密过程都是围绕该byte数组进行的。

  Main方法中调用两个静态方法EncriptDecript方法,分别用来实现加密和解密。在Encript方法中,首先初始化内存流MemoryStream的实例mstream,然后以mstream为参数创建CryptoStream实例。CryptoStream构造函数需要3个参数:第一个是流实例,第二个是加密或者解密器,在加密函数中使用CreateEncryptor方法做参数,在解密方法中使用CreateDecryptor做参数;CreateEncryptorCreateDecryptor方法需要传入准备好的加密密钥和初始化向量。第三个参数是CryptoStreamMode枚举,该枚举有两个值WriteRead,用来指示流的操作。比如在网络流中,加密并输出数据时要设置Write属性,接收并解密的一方要设置Read属性。本例中把加密和解密的数据都写入内存流,所以都设置了Write属性。在初始化CryptoStream实例之后,调用该实例的Write方法,将加密后的数据写入内存流。然后再调用内存流的ToArray方法读出加密数据,返回到Main方法中,通过Encoding.Default.GetString方法,获得加密后的字符串。解密过程与此类似,不再赘述。

现在看改程序的运行结果,如图6-13所示。

6-13  代码清单6-7运行结果

如图6-7所示,已经成功实现了简单的对称加密解密过程。.NET中的其他对称加密实现类的使用方法与此类似。

 

----------------------注:本文部分内容改编自《.NET安全揭秘》

阅读(1488) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~