iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 27
4
Security

資料安全與簡單加密演算法見面會 系列 第 27

[Day27] 非對稱金鑰加密系統(RSA)

來到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。

RSA


2002的圖靈獎也頒給了RSA加密演算法的三個發明人,麻省理工教授Ron Rivest、以色列密碼學家Adi Shamir、南加大教授Leonard Adleman,RSA就是以他們的姓氏首字母縮寫組合成。

簡單畫RSA加解密的流程圖:

1.首先是接收端的史丹利產生公開及私密金鑰
2.將公開金鑰交給加密端的前女友:住在內湖的蘇西。
3.蘇西使用公開金鑰將說給史丹利的事情(明文)加密。
4.密文透過網際網路傳輸給史丹利。
5.史丹利收到後,使用私密金鑰將蘇西的密文解密,就可以知道前女友蘇西的叮嚀了。

http://ithelp.ithome.com.tw/upload/images/20170111/201034346zInPKC8sK.png

我們前面曾在[Day22] 資料傳輸安全(機密性) RSA x AES 混搭風運用過RSA加解密,但當時是用Xmlformatstring交換金鑰,今天我們改用憑證的方式。

RSA金鑰交換


我們使用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 Manager
Windows + R + certlm.msc 啟動local computer certificate

點開憑證 > personal > 選剛剛的憑證名稱Stanley1024或2048 > 右鍵ALL Tasks > 匯出

http://ithelp.ithome.com.tw/upload/images/20170111/20103434Tyy4pNpmN6.jpg

記得不要匯出私密金鑰

http://ithelp.ithome.com.tw/upload/images/20170111/201034348T3pKZ0MP8.jpg

選擇編碼方式

http://ithelp.ithome.com.tw/upload/images/20170111/20103434CS3vYCEvOS.jpg

選擇目錄

http://ithelp.ithome.com.tw/upload/images/20170111/20103434hSLYWUrEae.jpg

匯入成功

http://ithelp.ithome.com.tw/upload/images/20170111/201034344g3FJcvfrY.jpg

匯出成功後,我們會有兩個憑證

http://ithelp.ithome.com.tw/upload/images/20170111/20103434ykKGmSOdGQ.jpg

RSA加解密


因為私密金鑰就在史丹利電腦內,我們如果要使用她,必須到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}");

測試結果:
http://ithelp.ithome.com.tw/upload/images/20170111/20103434HXyZ5HhTjg.png

RSA加解密:

  • RSA 1024,加密時最大明文長度為117 Byte,解密時最大密文長度為128 Byte;
  • RSA 2048,加密時最大明文長度為245 Byte,解密時最大密文長度為256 Byte;
    超過時,我們得分段處理,不過RSA大部分的用途是在保護對稱加密金鑰,像是會議基碼Session key等。

天氣涼了,要穿衣服!
哈!蘇西是前女友兼現任老婆,很兇悍,所以史丹利要多穿衣服。

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/


冰天雪地的
http://ithelp.ithome.com.tw/upload/images/20170111/20103434fkISyKFblm.jpg
2015.12攝於Grindelwald 格林德瓦,瑞士


上一篇
[Day26]對稱金鑰加密系統(DEA x TDEA x 2TDEA)
下一篇
[Day28] 加密演算法在支付卡的應用(卡片末三碼)
系列文
資料安全與簡單加密演算法見面會 30

尚未有邦友留言

立即登入留言