对称加密(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 = newTripleDESCryptoServiceProvider();

            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/archive/2012/06/23/2559537.html,如需转载请自行联系原作者

相关文章
|
2月前
|
存储 算法 安全
【加密算法】AES对称加密算法简介
【加密算法】AES对称加密算法简介
|
2月前
|
存储 安全 算法
【接口加密】Java中的接口加密实践
【接口加密】Java中的接口加密实践
|
2月前
|
机器学习/深度学习 算法 安全
【加密算法】RSA非对称加密算法简介
【加密算法】RSA非对称加密算法简介
|
1月前
|
算法 Java 开发工具
使用阿里云KMS产品针对 Springboot 接口参数加密解密功能
针对Springboot里面使用开源工具使用加解密,替换成阿里云KMS产品进行加解密;
144 1
|
2月前
|
机器学习/深度学习 安全 算法
【现代密码学】笔记9-10.3-- 公钥(非对称加密)、混合加密理论《introduction to modern cryphtography》
【现代密码学】笔记9-10.3-- 公钥(非对称加密)、混合加密理论《introduction to modern cryphtography》
26 0
|
2月前
|
存储 安全 Nacos
使用KMS为MSE-Nacos敏感配置加密的最佳实践
本文主要介绍通过KMS密钥管理服务产生的密钥对敏感的AK等数据进行加密之后可以有效解决泄漏带来的安全风险问题,其次通过KMS凭据托管的能力直接将MSE的主AK进行有效管理,保障全链路无AK的业务体验,真正做到安全、可控。
92271 3
|
3月前
|
存储 安全 数据安全/隐私保护
加密的艺术:对称加密的奇妙之处(下)
加密的艺术:对称加密的奇妙之处(下)
加密的艺术:对称加密的奇妙之处(下)
|
Java 数据安全/隐私保护
Java实现最电话号码的简单加密源码
Java实现最电话号码的简单加密源码
18 0
|
2月前
|
算法 安全 Java
Java 实现 RSA 非对称加密算法-加解密和签名验签
Java 实现 RSA 非对称加密算法-加解密和签名验签
|
Java 数据安全/隐私保护
java实现加密电话号码,有具体的加密流程注释
java实现加密电话号码,有具体的加密流程注释
21 0

热门文章

最新文章