一說到資料的加密,常常會涉及到這幾個單詞:演算法、原文、密文和密鑰。通常,寄件者把原文通過一個加密的演算法,用密鑰進行加密後將密文發送給接收者,然後接收者再用金鑰組密文進行解密,得到原文。由於常用的密碼編譯演算法都是公開的,所以,對原文的加密的關鍵,就是密鑰了。對於這種加解密都使用同樣的密鑰的演算法,我們稱之為對稱式加密,對稱式加密的代表演算法就是DES家族了。那麼這種對稱式加密有什麼缺陷呢?由於加解密使用相同的密鑰,那麼這個密鑰最少要儲存在兩個地方,如果加密的資料要發給多人,那麼就會有更多的人知道密鑰,這大大增加了密鑰泄露的風險;並且密鑰需要由發送方傳遞給接收方,那麼如何保證密鑰的傳遞的安全,則成了另外一個頭疼的事情。為瞭解決這個問題,相對於對稱式加密,又出現了非對稱式加密。
什麼是非對稱式加密?所謂的非對稱式加密,就是指加密和解密使用不同的密鑰的一類密碼編譯演算法。這類密碼編譯演算法通常有兩個密鑰A和B,使用密鑰A加密資料得到的密文,只有密鑰B可以進行解密操作(即使密鑰A也無法解密),相反,使用了密鑰B加密資料得到的密文,只有密鑰A可以解密。這兩個密鑰分別稱為私密金鑰和公開金鑰,顧名思義,私密金鑰就是你個人保留,不能公開的密鑰,而公開金鑰則是公開給加解密操作的另一方的。根據不同用途,對資料進行加密所使用的密鑰也不相同(有時用公開金鑰加密,私密金鑰解密;有時相反用私密金鑰加密,公開金鑰解密)。非對稱式加密的代表演算法是RSA演算法。
那麼非對稱式加密到底有哪些用途?
第一個用途當然是做資料加密。
請大家想象一下,如果我不想讓除了接收方以外的其他人,知道我發送的資料的內容的話,需要用哪種金鑰組資料進行加密?如果我使用私密金鑰加密,那麼根據非對稱式加密的原理,接收方需要使用公開金鑰來解密,而公開金鑰我已經公開給接收方了,這個方案似乎是可行的,可是這樣做問題就出現在公開金鑰上了。在非對稱式加密中,公開金鑰的公開不僅僅指對接收方的公開,而是指這個密鑰徹底的公開,任何人需要都可以得到,這樣的話你發送的資料就沒有任何秘密可言了。反過來,如果我使用公開金鑰對資料加密,那麼對於接收方來說就需要使用私密金鑰進行資料解密,由於私密金鑰只儲存在接收方手中,這樣其他人就不會得到資料的內容了。這樣看來,在非對稱式加密中,如果需要保護你的資料不被第三者得到,密鑰需要由接收方產生,然後接收方將公開金鑰公開出去,發送方使用這個公開的公開金鑰對資料進行加密後傳輸給接收方,接收方使用自己的私密金鑰進行解密,從而保證了資料的安全性。所以非對稱式加密又稱為公開金鑰加密。
非對稱式加密的執行效率要遠低於對稱式加密,所以我們不會對一個大的檔案或資料使用非對稱式加密演算法。那麼我們如何加密一個大的檔案呢?通常情況我們可以選擇對稱式加密演算法加密檔案,然後使用非對稱演算法加密對稱演算法的密鑰,這樣就保證了對稱演算法密鑰傳遞的安全性。
非對稱式加密的另外一個用途就是用來進行數位簽章。
什麼是數位簽章?數位簽章同我們在合約上的簽字一樣,接收方可以用它來證明收到的資料或檔案是由你發送的。舉個例子:假設發送方需要將一串資料D發送給接收方,那麼接收方如何判斷資料D是發送方發送的呢?
Step 1:發送方先產產生一對密鑰,並將公開金鑰公開給接收方;
Step 2:發送方將資料D用私密金鑰進行加密得到密文M,然後將資料D和密文M一起發送給接收方;
Step 3:接收方得到資料D和密文M後,用公開金鑰將密文M解密得到d;
Step 4:比較D和d,相等則證明D是由發送方發送的。
在實際的操作中,我們並不會直接用私密金鑰去加密要發送的資料或檔案,這是因為非對稱式加密的演算法非常耗時並且密文的長度要大於明文的長度,直接加密系統的開銷非常大。那麼如何實解決這個問題呢?
首先,我們需要瞭解另外一個概念:訊息摘要。所謂的訊息摘要就是通過一種單向演算法計算出來的唯一對應一個檔案或資料的固定長度的值,也被稱作數字摘要。根據不同的演算法,訊息摘要的長度一般為128位或160位。常用的訊息摘要的演算法有MD5和SHA1。一個檔案的訊息摘要就同一個人的指紋一樣,它可以唯一代表這個檔案,如果這個檔案被修改了,那麼它的訊息摘要也一定會發生變化,所以,我們可以通過對一個檔案的訊息摘要進行簽名來代替對它本身進行簽名。並且,我們還可以通過驗證訊息摘要,來確定發送的資料是否完整或曾經被修改過。這樣,上面的例子大致可以變為下面這樣:
Step 1:發送方先產產生一對密鑰,並將公開金鑰公開給接收方;
Step 2:發送方將資料D進行訊息摘要,得到Q;
Step 3:用私密金鑰對Q進行加密得到密文MQ,然後將資料D和密文MQ一起發送給接收方;
Step 4:接收方得到資料D和密文MQ後,用公開金鑰將密文MQ解密得到q1;
Step 5:接收方使用相同的演算法對資料D進行訊息摘要,得到q2;
Step 6:比較q1和q2,相等則證明D是由發送方發送的,且沒有被修改過。
好了,非對稱式加密的使用介紹了一大堆,後面我們來看看如何用C#來實現RSA非對稱式加密。
.Net中的加密操作所涉及的對象都在命名空間System.Security.Cryptography下,所以請先在你的程式中添加using System.Security.Cryptography; 其中,RSA密碼編譯演算法由RSACryptoServiceProvider對象實現。下面的代碼分別實現了資料的加密解密和簽名與驗證。
1: string PublicKey, PrivateKey;
2: RSACryptoServiceProvider rsaProvider;
3: void Initial()
4: {
5: //聲明一個RSA演算法的執行個體,由RSACryptoServiceProvider類型的建構函式指定了密鑰長度為1024位
6: //執行個體化RSACryptoServiceProvider後,RSACryptoServiceProvider會自動產生密鑰資訊。
7: rsaProvider = new RSACryptoServiceProvider(1024);
8: //將RSA演算法的公開金鑰匯出到字串PublicKey中,參數為false表示不匯出私密金鑰
9: PublicKey = rsaProvider.ToXmlString(false);
10: //將RSA演算法的私密金鑰匯出到字串PrivateKey中,參數為true表示匯出私密金鑰
11: PrivateKey = rsaProvider.ToXmlString(true);
12:
13:
14: byte[] EncryptData(byte[] data)
15: {
16: RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
17: //將公開金鑰匯入到RSA對象中,準備加密;
18: rsa.FromXmlString(PublicKey);
19: //對資料data進行加密,並返回加密結果;
20: //第二個參數用來選擇Padding的格式
21: return rsa.Encrypt(data, false);
22: }
23:
24: byte[] DecryptData(byte[] data)
25: {
26: RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
27: //將私密金鑰匯入RSA中,準備解密;
28: rsa.FromXmlString(PrivateKey);
29: //對資料進行解密,並返回解密結果;
30: return rsa.Decrypt(data, false);
31: }
32:
33: byte[] Sign(byte[] data)
34: {
35: RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
36: //匯入私密金鑰,準備簽名
37: rsa.FromXmlString(PrivateKey);
38: //將資料使用MD5進行訊息摘要,然後對摘要進行簽名並返回簽名資料
39: return rsa.SignData(data, "MD5");
40: }
41:
42: bool Verify(byte[] data, byte[] Signature)
43: {
44: RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(1024);
45: //匯入公開金鑰,準備驗證簽名
46: rsa.FromXmlString(PublicKey);
47: //返回資料驗證結果
48: return rsa.VerifyData(data, "MD5", Signature);
49: }