• 对称加密(4) NET对称加密实践


    对称加密(4) NET对称加密实践

     

    在使用.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)

            {

             

       using (MemoryStream msEncrypt = new MemoryStream())             

    {                 using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, acsp.CreateEncryptor(key, iv), CryptoStreamMode.Write))                 {                    

     using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))                    

     {                         //Write all data to the stream.                        

     var s = Convert.ToBase64String(s1);                       

      swEncrypt.Write(s);                     

    }                     

      byte[] outb1  = msEncrypt.ToArray();                      

     return outb1;              

       }            

     }

            }

     

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

            {

               

        using (MemoryStream msDecrypt = new MemoryStream(s2))
                    {
                        using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, acsp.CreateDecryptor(key, iv), CryptoStreamMode.Read))
                        {
                            using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                            {
                                var s= Convert.FromBase64String(srDecrypt.ReadToEnd());
     
                                return s;
                            }
                        }
                    }

            }

     

            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安全揭秘》

     


    作者:玄魂
    出处:http://www.cnblogs.com/xuanhun/
    原文链接:http://www.cnblogs.com/xuanhun/ 更多内容,请访问我的个人站点 对编程,安全感兴趣的,加qq群:hacking-1群:303242737,hacking-2群:147098303,nw.js,electron交流群 313717550。
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    关注我:关注玄魂的微信公众号

  • 相关阅读:
    超市帐单系统
    JavaOOP
    拦截器的工作原理是什么?
    struts2
    500错误
    idea添加struts框架后报错
    2019春第九周作业
    2019春第八周作业
    2019春第七周作业
    2019春第六周作业
  • 原文地址:https://www.cnblogs.com/xuanhun/p/2559537.html
Copyright © 2020-2023  润新知