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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM