iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 23
1
Security

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

[Day23] 資料傳輸安全(機密性) RSA x AES 混搭風(下)

昨天(Day22-資料傳輸安全(機密性) RSA x AES 混搭風(上))我們將RSA x AES 混搭風所需要的測試檔案以及AES加解密程式準備好,順便讓來自不同家族的RSA和AES了解彼此人生目標以及婚後的生活,今天來讓RSA x AES在眾人的祝福下,在一起~在一起~在一起。

  • RSA:非對稱金鑰家族
  • AES:對稱金鑰家族

檔案接收端產生一組RSA公鑰及私鑰


因為測試的請款檔案是預備從商店端傳送到收單銀行,因此習慣上會定期由收單銀行端產生一組公私鑰。
私密金鑰(private key)銀行自己妥善保管,而公開金鑰(public key)則交給商店進行加密。

這邊我們呼叫C# RSA加密解演算法物件的ToXmlString,利用輸入的參數True或false就可以產生公鑰或私鑰。

  • ToXmlString(true):私密金鑰(private key)
  • ToXmlString(false):公開金鑰(public key)

後面介紹RSA時,我們再改成憑證的方式儲存RSA公私鑰,這邊先簡單使用xmlstring。

public void TestGenRsaKey()
{
    //建立RSA演算法物件
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
    //顯示私密金鑰(FromXmlString),這一把要妥善保存。
    Console.WriteLine($"private key:{rsa.ToXmlString(true)}");
    //我是分隔線
    Console.WriteLine("====================================");
    //顯示公開金鑰(FromXmlString),這一把要交給商店。
    Console.WriteLine($"public key:{rsa.ToXmlString(false)}");
}

執行結果:
http://ithelp.ithome.com.tw/upload/images/20170107/20103434MymN3ctKB6.png

私密金鑰(private key)

<RSAKeyValue> <Modulus>1YH2PKyMSjX/1Giw+y3/aIqXfqHas9llRJMyJrx++5tylWFsmP/UH3DvuUKoteEnGZKLxyug0scZ12kRKyyXXq6cYenV6TpZ7Ai2Wnxc9pHMJXO26GIdtgFRy93wFnMni0QCZ43YRyJ+SOzW+VnyUMGWD/a43eQucW+uju2a5V8=</Modulus>
  <Exponent>AQAB</Exponent>
  <P>5ztUfQSfJpVXuGisil3uxbGOLj3iJgA92mKkp8Jz7cR3Yt/RbMvivbJV6Di7HGJkKdeLP8dOHJvlySSB5xJJgw==</P>
  <Q>7GCdUlF37/0IARjjVUKbKJjTiO2ETnwW2I9Sm+lJJr1Q+qTHmG1sErJqFqWWXjmOnxKR9VXTemtlWEk3goRZ9Q==</Q>
  <DP>wprYPG9LUjmWHglaTQlJDvCj7J8AWWMSq10hnl61GoKix3/+zUW6ilQwoMQ+FWFpUx2ogADI6KL7/RDQkxx86Q==</DP>
  <DQ>H398V0TN46fnEiZb3Lekb1N2FK/5ym+Up8TpcCc0/TmK+etNQY2LMi6eHmhwUhv/WkkiM/v80zpOZeZTxEuYpQ==</DQ>
  <InverseQ>lRuu2nbptZizRNHncOXxOzXXInRa/Ay/m2IDLNecB2M7IrRRFxfQMT3ZxwVL29jO6QjhmRma5hyP/rCircKqNw==</InverseQ>
<D>P9wZXFh3tZKlLFEL7nT5mbkqStP6aCSz52jnbTKgAH2kLg3vv2t1dNoAuba4Y34uhbWRXUctWR34GrfwTKuPslRGs0EZzi6pdswSDDAJI61cGMGCMKB0znf0rdBedSScC8mJA4dVlQxpWs1ivENOv9irBXbnL9EbzpdFSRetdlE=</D>
</RSAKeyValue>

公開金鑰(public key)

<RSAKeyValue>
  <Modulus>1YH2PKyMSjX/1Giw+y3/aIqXfqHas9llRJMyJrx++5tylWFsmP/UH3DvuUKoteEnGZKLxyug0scZ12kRKyyXXq6cYenV6TpZ7Ai2Wnxc9pHMJXO26GIdtgFRy93wFnMni0QCZ43YRyJ+SOzW+VnyUMGWD/a43eQucW+uju2a5V8=</Modulus>
  <Exponent>AQAB</Exponent>
</RSAKeyValue>

有沒有發現產生私密金鑰時,公開金鑰也在其中。

測試檔案傳送端加密功能


1.首先商家要先產生這次的會議金鑰(Session key)
2.商家使用會議金鑰(Session key)對檔案內容進行加密。
3.商家使用收單銀行的公開金鑰(public key)對會議金鑰(Session key)進行加密。
4.將步驟2.3檔案合併

http://ithelp.ithome.com.tw/upload/images/20170107/20103434xDyjmKHe1S.jpg

[TestMethod]
public void TestEncryption()
{
    //建立檔案
    CreateFile();
    //建立RSA演算法物件
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

    string publicKey = @"<RSAKeyValue>
  <Modulus>1YH2PKyMSjX/1Giw+y3/aIqXfqHas9llRJMyJrx++5tylWFsmP/UH3DvuUKoteEnGZKLxyug0scZ12kRKyyXXq6cYenV6TpZ7Ai2Wnxc9pHMJXO26GIdtgFRy93wFnMni0QCZ43YRyJ+SOzW+VnyUMGWD/a43eQucW+uju2a5V8=</Modulus>
  <Exponent>AQAB</Exponent>
</RSAKeyValue>";

    //載入公開金鑰(FromXmlString)
    rsa.FromXmlString(publicKey);

    //AES加密
    //讀取會議金鑰(session key)資料
    string SessionKey = "我是金鑰我是機密別和人說我是金鑰";
    string IV = "00000000";
    byte[] bSK = Encoding.Unicode.GetBytes(SessionKey);
    byte[] bEncryptSK = rsa.Encrypt(bSK, false);

    //AES檔案加密
    string filecontent = System.IO.File.ReadAllText(@"C:\temp\transaction.txt");
    string Encrypfilecontent = AESEncryption(SessionKey, IV, filecontent);

    //寫出合併後的檔案(Session key(Encrypted) + filecontent(Encrypted))
    using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\temp\transaction(Encrypted).txt", false))
    {
        file.WriteLine(Convert.ToBase64String(bEncryptSK));
        file.WriteLine("\t");
        file.WriteLine(Encrypfilecontent);
    }
}

加密前檔案:

http://ithelp.ithome.com.tw/upload/images/20170107/20103434AwNCjr3lgf.png

加密後檔案:
http://ithelp.ithome.com.tw/upload/images/20170107/20103434kG68njGcZz.png

測試檔案接收端解密功能


1.銀行將加密後的檔案拆開為加密後的會議金鑰(Session key)及加密後的檔案內容兩部分。
2.銀行使用自己保管的私密金鑰(private key)對會議金鑰(Session key)進行解密。
3.使用步驟2解開的會議金鑰(Session key)對加密後的檔案內容進行解密。

http://ithelp.ithome.com.tw/upload/images/20170107/20103434nntJG7qdVT.jpg

[TestMethod]
public void TestDecryption()
{
    //建立RSA演算法物件
    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

    //private key(FromXmlString)
    string privateKey = @"<RSAKeyValue>
  <Modulus>1YH2PKyMSjX/1Giw+y3/aIqXfqHas9llRJMyJrx++5tylWFsmP/UH3DvuUKoteEnGZKLxyug0scZ12kRKyyXXq6cYenV6TpZ7Ai2Wnxc9pHMJXO26GIdtgFRy93wFnMni0QCZ43YRyJ+SOzW+VnyUMGWD/a43eQucW+uju2a5V8=</Modulus>
  <Exponent>AQAB</Exponent>
  <P>5ztUfQSfJpVXuGisil3uxbGOLj3iJgA92mKkp8Jz7cR3Yt/RbMvivbJV6Di7HGJkKdeLP8dOHJvlySSB5xJJgw==</P>
  <Q>7GCdUlF37/0IARjjVUKbKJjTiO2ETnwW2I9Sm+lJJr1Q+qTHmG1sErJqFqWWXjmOnxKR9VXTemtlWEk3goRZ9Q==</Q>
  <DP>wprYPG9LUjmWHglaTQlJDvCj7J8AWWMSq10hnl61GoKix3/+zUW6ilQwoMQ+FWFpUx2ogADI6KL7/RDQkxx86Q==</DP>
  <DQ>H398V0TN46fnEiZb3Lekb1N2FK/5ym+Up8TpcCc0/TmK+etNQY2LMi6eHmhwUhv/WkkiM/v80zpOZeZTxEuYpQ==</DQ>
  <InverseQ>lRuu2nbptZizRNHncOXxOzXXInRa/Ay/m2IDLNecB2M7IrRRFxfQMT3ZxwVL29jO6QjhmRma5hyP/rCircKqNw==</InverseQ>
<D>P9wZXFh3tZKlLFEL7nT5mbkqStP6aCSz52jnbTKgAH2kLg3vv2t1dNoAuba4Y34uhbWRXUctWR34GrfwTKuPslRGs0EZzi6pdswSDDAJI61cGMGCMKB0znf0rdBedSScC8mJA4dVlQxpWs1ivENOv9irBXbnL9EbzpdFSRetdlE=</D>
</RSAKeyValue>
";
    //載入私密金鑰
    rsa.FromXmlString(privateKey);

    //讀取加密後的本文資料
    string AllText = System.IO.File.ReadAllText(@"C:\temp\transaction(Encrypted).txt");

    //使用分隔符號拆解
    if (!AllText.Contains("\t"))
    {
        Console.WriteLine("明文與簽章資料缺少分隔符號\t");
        return;
    }
    byte[] skText = Convert.FromBase64String(AllText.Split('\t')[0]);
    string DataText = AllText.Split('\t')[1];

    //(1)先解出Session key
    byte[] bEncryptSK = rsa.Decrypt(skText, false);

    //顯示Session key
    Console.WriteLine(Encoding.Unicode.GetString(bEncryptSK));

    //(2)解密檔案
    string content = AESDecryption(Encoding.Unicode.GetString(bEncryptSK), "00000000", DataText);

    //顯示檔案內容
    Console.WriteLine(content);

    //(3)重新寫出檔案給BIZ應用程式處理
    using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\temp\transaction(OK).txt", false))
    {
        file.WriteLine(content);
    }
}

執行結果:
http://ithelp.ithome.com.tw/upload/images/20170107/20103434NJZS5R3jA4.png

檔案解密成功:
http://ithelp.ithome.com.tw/upload/images/20170107/201034349mwUfPtQTb.png


從Day18起,我們用了6天時間複習檔案傳輸時的資料保護,有著重在資料完整性(data integrity),也有重點放在機密性(Confidentiality)與識別來源上的機制,希望我們在行駛到高速公路前,選擇一台更多備配有主被動安全的車輛,如果天有不測風雲之時,也能有更多面向保護車內乘客的安全。

[Day18] 資料傳輸安全(完整性)校驗值與雜湊值
[Day19] 資料傳輸安全(完整性)MAC訊息驗證碼 (上)
[Day20] 資料傳輸安全(完整性)MAC訊息驗證碼 (下)
[Day21] 資料傳輸安全(完整性)數位簽章
[Day22] 資料傳輸安全(機密性) RSA x AES 混搭風(上)

哈!明天我們來簡單複習加密通道。


托斯卡尼警車營運中
http://ithelp.ithome.com.tw/upload/images/20170107/20103434eSgj9w9vla.jpg
2011.10 攝於Toscana,Italy


上一篇
[Day22] 資料傳輸安全(機密性) RSA x AES 混搭風(上)
下一篇
[Day24] 資料傳輸安全(通道加密)
系列文
資料安全與簡單加密演算法見面會 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

1
小茶
iT邦新手 4 級 ‧ 2017-01-07 20:47:14

Stanley大大,已經是第23天囉(標題好像有誤 XDD/images/emoticon/emoticon39.gif
每篇內容都好精采喔!!
謝謝Stanley大大的教學文章

謝謝小茶~
小茶大的文章也很棒!
哈!我們要一起衝線。加油!

0
GW
iT邦新手 4 級 ‧ 2019-03-15 16:21:29

Stanley大,我想要讓不同台電腦(用戶)間使用同一組金鑰,目前是使用Powershell建立憑證再匯出公私鑰,程式使用X509引用作RSA加解密,長度限制則是用分段加解密的方式處理。

想請教如果不使用將公私鑰匯出文字檔的方式保存,該怎麼從程式中保存由RSACryptoServiceProvider創建的公私鑰並可以傳給其他用戶(不同台電腦)呢?

現在的想法是使用金鑰容器保存,然後再匯出,只是這樣過程好像變得有些複雜。

我要留言

立即登入留言