zoukankan      html  css  js  c++  java
  • C#对称加密

    .NET库的System.Security.Cryptography命名空间中,包含多种加密数据的类,涉及多种加密算法。加密方法主要分为两大类:对称加密和不对称加密。

    对称加密 

    私钥算法以块为单位加密数据,一次加密一个数据块。因此对称加密支持数据流,是加密流数据的理想方式。
    .NET类库使用的私钥算法有RC2、DES、TripleDES和Rijndael。这些算法通过加密将n字节的输入块转换为加密字节的输出块。如果要加密或解密字节序列,必须逐块进行。由于n很小(对于RC2、DES和TripleDES算法,n的值为8字节、16字节或24字节,默认值为16字节;对于Rijndael算法,n的值为32字节),因此每次加密的块的大小必须大于n。实际上,一次读入的数据块是否符合私钥算法要求的块的大小,如果不符合应该如何填充使其符合要求等情况,.NET类库提供的算法类本身会自动处理,编写程序时不需要考虑这些问题。

     为了保证数据的安全,.NET基类库中提供的私钥算法类使用称作密码块链(CBC,Cipher Block Chaining)的链模式,算法使用一个密钥和一个初始化向量(IV,Initialization Vector)对数据执行加密转换。密钥和初始化向量IV一起决定如何加密数据,以及如何将数据解密为原始数据。通信双方都必须知道这个密钥和初始化向量才能够加密和解密数据。

    初始化向量IV的作用:防止随机产生的明文和密文相同

    对称加密算法的优点是保密强度高,加、解密速度快,适合加密大量数据。攻击者如果对加密后的数据进行破译,惟一的办法就是对每个可能的密钥执行穷举搜索。而采用这种加密技术,即使使用最快的计算机执行这种搜索,耗费的时间也相当长。如果使用较大的密钥,破译将会更加困难。在实际应用中,加密数据采用的密钥一般都有时效性,比如几天更换一次密钥和IV,如果攻击者采用穷举法试图破译加密后的数据,等到好不容易试出了密钥,加密者早已采用新的密钥对网络中传输的数据进行加密了,因此利用穷举搜索的方法破译加密后的数据实际上是没有意义的。 

    .NET Framework中,公共语言运行时CLR(Common Language Runtime)使用面向流的设计实现对称加密,该设计的核心是CryptoStream,实现CryptoStream的任何被加密的对象都可以和实现Stream的任何对象链接起来。实现对称加密算法的类有四种:
    DESCryptoServiceProvider 
    RC2CryptoServiceProvider 
    RijndaelManaged 
    TripleDESCryptoServiceProvider 

    下面是TripleDES的一个基本操作

    private void buttonOK_Click(object sender, EventArgs e)
            {
                string str = textBoxInput.Text;
                //加密
                try
                {
                    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
                    //随机生成密钥Key和初始化向量IV(也可以自己设定)
                    tdes.GenerateKey();
                    tdes.GenerateIV();
                    textBoxKey.Text = Encoding.UTF8.GetString(tdes.Key);
                    //得到加密后的字节流
                    byte[] encryptedBytes = EncryptText(str, tdes.Key, tdes.IV);
                    //显示加密后的字符串
                    textBoxEncrypt.Text = Encoding.UTF8.GetString(encryptedBytes);
                    //解密
                    string decryptString = DecryptText(encryptedBytes, tdes.Key, tdes.IV);
                    //显示解密后的字符串
                    textBoxDecrypt.Text = decryptString;
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message, "出错");
                }
            }
            private byte[] EncryptText(string str, byte[] Key, byte[] IV)
            {
                //创建一个内存流
                MemoryStream memoryStream = new MemoryStream();
                //使用传递的私钥和IV创建加密流
                CryptoStream cryptoStream = new CryptoStream(memoryStream,
                    new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV),
                    CryptoStreamMode.Write);
                //将传递的字符串转换为字节数组
                byte[] toEncrypt = Encoding.UTF8.GetBytes(str);
                try
                {
                    //将字节数组写入加密流,并清除缓冲区
                    cryptoStream.Write(toEncrypt, 0, toEncrypt.Length);
                    cryptoStream.FlushFinalBlock();
                    //得到加密后的字节数组
                    byte[] encryptedBytes = memoryStream.ToArray();
                    return encryptedBytes;
                }
                catch (CryptographicException err)
                {
                    throw new Exception("加密出错:" + err.Message);
                }
                finally
                {
                    cryptoStream.Close();
                    memoryStream.Close();
                }
            }
            private string DecryptText(byte[] dataBytes, byte[] Key, byte[] IV)
            {
                //根据加密后的字节数组创建一个内存流
                MemoryStream memoryStream = new MemoryStream(dataBytes);
                //使用传递的私钥、IV和内存流创建解密流
                CryptoStream cryptoStream = new CryptoStream(memoryStream,
                    new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV),
                    CryptoStreamMode.Read);
                //创建一个字节数组保存解密后的数据
                byte[] decryptBytes = new byte[dataBytes.Length];
                try
                {
                    //从解密流中将解密后的数据读到字节数组中
                    cryptoStream.Read(decryptBytes, 0, decryptBytes.Length);
                    //得到解密后的字符串
                    string decryptedString = Encoding.UTF8.GetString(decryptBytes);
                    return decryptedString;
                }
                catch (CryptographicException err)
                {
                    throw new Exception("解密出错:" + err.Message);
                }
                finally
                {
                    cryptoStream.Close();
                    memoryStream.Close();
                }
            }

  • 相关阅读:
    request-log-analyzer日志分析
    ubuntu下git输出的颜色变化
    vundle安装 给vim插上翅膀
    安装ruby
    【HDU1944】S-Nim-博弈论:SG函数
    【HDU1944】S-Nim-博弈论:SG函数
    我对SG函数的理解
    我对SG函数的理解
    【POJ2154】Color-Polya定理+欧拉函数
    【POJ2154】Color-Polya定理+欧拉函数
  • 原文地址:https://www.cnblogs.com/fujinliang/p/2574091.html
Copyright © 2011-2022 走看看