來到2015年的冬天,同事大A、朋友小B以及同學小C想要和遠在瑞士想滑雪的史丹利說秘密,為了避免這些親朋好友彼此知道對方的內容,也許我們可以用對稱加密演算法(Symmetric-key algorithm),事前各準備3把對稱加密金鑰,分別提供給同事同事大A、朋友小B以及同學小C作為加密訊息使用。
但如果史丹利有100個同事、300個FB朋友,100個高中及大學同學?呼~一次管理500把對稱金鑰會讓史丹利白頭髮多長很多根。為了解決對稱金鑰交換時被竊取以及對稱加密的金鑰管理性問題,在密碼學的發展中演化出一種公開金鑰加密演算法(public-key cryptography)。
史丹利只要將1把公開金鑰給500個親朋好友用來訊息加密,由於公開金鑰加密系統的特性,加密後的密文只能用私密金鑰解開,因此500個親朋好友彼此之間或截獲訊息的人沒辦法知道秘密,史丹利要讀取密文時也只要拿出1把私人金鑰就可以解開。
這麼好的方法,2015年的圖靈獎就頒給了1976年發明公開金鑰演算法的Whitfield Diffe及Martin Hellman。
http://www.acm.org/media-center/2016/march/turing-award-2015
公開金鑰加密演算法運算式
私密金鑰解密(公開金鑰加密(明文))=明文
常見的公開金鑰加密演算法有ECC(橢圓曲線加密)以及廣泛使用在商業中的RSA。
還有綁架病毒Crypt0L0cker就是用上了rsa2048。
2002的圖靈獎也頒給了RSA加密演算法的三個發明人,麻省理工教授Ron Rivest、以色列密碼學家Adi Shamir、南加大教授Leonard Adleman,RSA就是以他們的姓氏首字母縮寫組合成。
簡單畫RSA加解密的流程圖:
1.首先是接收端的史丹利產生公開及私密金鑰
2.將公開金鑰交給加密端的前女友:住在內湖的蘇西。
3.蘇西使用公開金鑰將說給史丹利的事情(明文)加密。
4.密文透過網際網路傳輸給史丹利。
5.史丹利收到後,使用私密金鑰將蘇西的密文解密,就可以知道前女友蘇西的叮嚀了。
我們前面曾在[Day22] 資料傳輸安全(機密性) RSA x AES 混搭風運用過RSA加解密,但當時是用Xmlformatstring交換金鑰,今天我們改用憑證的方式。
我們使用Windows內建的憑證工具Makecert.exe來建立RSA憑證:
建立一個是RSA 1024加密演算法的憑證。
makecert -r -pe -n "CN=Stanley1024" -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
建立一個是RSA 2048加密演算法的憑證
makecert -r -pe -n "CN=Stanley2048" -b 01/01/2000 -e 01/01/2036 -eku 1.3.6.1.5.5.7.3.1 -ss my -len 2048 -sr localMachine -sky exchange -sp "Microsoft RSA SChannel Cryptographic Provider" -sy 12
接著匯出儲存公開金鑰的憑證
因為剛剛把憑證儲存到localMachine,所以要啟動local computer certificate ManagerWindows
+ R
+ certlm.msc
啟動local computer certificate
點開憑證 > personal > 選剛剛的憑證名稱Stanley1024或2048 > 右鍵ALL Tasks > 匯出
記得不要匯出私密金鑰
選擇編碼方式
選擇目錄
匯入成功
匯出成功後,我們會有兩個憑證
因為私密金鑰就在史丹利電腦內,我們如果要使用她,必須到local machine中的憑證堆搜尋,簡單寫一段方法
X509Certificate2 getCertificate(string certificateName)
{
X509Store x509 = new X509Store(StoreName.My, StoreLocation.LocalMachine);
x509.Open(OpenFlags.ReadOnly);
//搜尋憑證名稱
X509Certificate2Collection cert = x509.Certificates.Find(X509FindType.FindBySubjectName, certificateName,
false);
if (cert.Count > 0)
{
return cert[0];
}
else
{
throw new Exception(string.Format($"Certificate '{certificateName}' not found in localMachine"));
}
}
加密方法(使用憑證)
private string RsaEncryption(string plainttext, string Path)
{
string ciphertext = "";
X509Certificate2 cert = new X509Certificate2(Path);
using (RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key)
{
byte[] bytesData = Encoding.UTF8.GetBytes(plainttext);
byte[] bytesEncrypted = csp.Encrypt(bytesData, false);
ciphertext = Convert.ToBase64String(bytesEncrypted);
}
return ciphertext;
}
解密方法(使用本機儲存的私密金鑰)
private string RsaDecryption(string ciphertext, string CerName)
{
string plainttext = string.Empty;
X509Certificate2 cert = getCertificate(CerName);
using (RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PrivateKey)
{
byte[] bytesEncrypted = Convert.FromBase64String(ciphertext);
byte[] bytesDecrypted = csp.Decrypt(bytesEncrypted, false);
plainttext = Encoding.UTF8.GetString(bytesDecrypted);
}
return plainttext;
}
分別測試看看RSA 2014及2028的加解密,加密的部分會從憑證檔案(.cer)讀取公開金鑰,解密則直接使用使用本機儲存的私密金鑰。
string data = "天氣涼了,要穿衣服!";
//RSA1024
string CliperText = RsaEncryption(data, @"C:\temp\test\testFileRSA.cer");
string PlaintText = RsaDecryption(CliperText, "stanley1024");
Console.WriteLine($"加密結果:{CliperText}");
Console.WriteLine($"解密結果:{PlaintText}");
//RSA2048
CliperText = RsaEncryption(data, @"C:\temp\test\testFileRSA(2048).cer");
PlaintText = RsaDecryption(CliperText, "stanley2048");
Console.WriteLine($"加密結果:{CliperText}");
Console.WriteLine($"解密結果:{PlaintText}");
測試結果:
RSA加解密:
天氣涼了,要穿衣服!
哈!蘇西是前女友兼現任老婆,很兇悍,所以史丹利要多穿衣服。
Wiki
2009年12月12日,編號為RSA-768(768 bits, 232 digits)數也被成功分解。這一事件威脅了現通行的1024-bit金鑰的安全性,普遍認為用戶應儘快升級到2048-bit或以上。
Wiki公開金鑰加密
https://zh.wikipedia.org/wiki/%E5%85%AC%E5%BC%80%E5%AF%86%E9%92%A5%E5%8A%A0%E5%AF%86
Visual C#: RSA encryption using certificate
https://social.technet.microsoft.com/wiki/contents/articles/30291.visual-c-rsa-encryption-using-certificate.aspx
How to generate 2048 Bit Certificate with Makecert.exe?
https://blogs.msdn.microsoft.com/avkashchauhan/2011/09/21/how-to-generate-2048-bit-certificate-with-makecert-exe/
冰天雪地的
2015.12攝於Grindelwald 格林德瓦,瑞士