HTTPS工作過程及加密算法

我們都知道HTTPS能夠加密信息,以免敏感信息被第三方獲取。所以很多銀行網(wǎng)站或電子郵箱等等安全級別較高的服務(wù)都會采用HTTPS協(xié)議。
在線SSL服務(wù)器測試

一、HTTPS工作過程

HTTPS其實是有兩部分組成:HTTP + SSL / TLS,也就是在HTTP上又加了一層處理加密信息的模塊。服務(wù)端和客戶端的信息傳輸都會通過TLS進行加密,所以傳輸?shù)臄?shù)據(jù)都是加密后的數(shù)據(jù)。具體是如何進行加密,解密,驗證的,且看下圖。


image

1. 客戶端發(fā)起HTTPS請求

這個沒什么好說的,就是用戶在瀏覽器里輸入一個https網(wǎng)址,然后連接到server的443端口。

2. 服務(wù)端的配置

采用HTTPS協(xié)議的服務(wù)器必須要有一套數(shù)字證書,可以自己制作,也可以向組織申請。區(qū)別就是自己頒發(fā)的證書需要客戶端驗證通過,才可以繼續(xù)訪問,而使用受信任的公司申請的證書則不會彈出提示頁面(startssl就是個不錯的選擇,有1年的免費服務(wù))。這套證書其實就是一對公鑰和私鑰。如果對公鑰和私鑰不太理解,可以想象成一把鑰匙和一個鎖頭,只是全世界只有你一個人有這把鑰匙,你可以把鎖頭給別人,別人可以用這個鎖把重要的東西鎖起來,然后發(fā)給你,因為只有你一個人有這把鑰匙,所以只有你才能看到被這把鎖鎖起來的東西。

3. 傳送證書

這個證書其實就是公鑰,只是包含了很多信息,如證書的頒發(fā)機構(gòu),過期時間等等。

4. 客戶端解析證書

這部分工作是有客戶端的TLS來完成的,首先會驗證公鑰是否有效,比如頒發(fā)機構(gòu),過期時間等等,如果發(fā)現(xiàn)異常,則會彈出一個警告框,提示證書存在問題。如果證書沒有問題,那么就生成一個隨即值。然后用證書對該隨機值進行加密。就好像上面說的,把隨機值用鎖頭鎖起來,這樣除非有鑰匙,不然看不到被鎖住的內(nèi)容。

5. 傳送加密信息

這部分傳送的是用證書加密后的隨機值,目的就是讓服務(wù)端得到這個隨機值,以后客戶端和服務(wù)端的通信就可以通過這個隨機值來進行加密解密了。

6. 服務(wù)段解密信息

服務(wù)端用私鑰解密后,得到了客戶端傳過來的隨機值(私鑰),然后把內(nèi)容通過該值進行對稱加密。所謂對稱加密就是,將信息和私鑰通過某種算法混合在一起,這樣除非知道私鑰,不然無法獲取內(nèi)容,而正好客戶端和服務(wù)端都知道這個私鑰,所以只要加密算法夠彪悍,私鑰夠復(fù)雜,數(shù)據(jù)就夠安全。

7. 傳輸加密后的信息

這部分信息是服務(wù)段用私鑰加密后的信息,可以在客戶端被還原

8. 客戶端解密信息

客戶端用之前生成的私鑰解密服務(wù)段傳過來的信息,于是獲取了解密后的內(nèi)容。整個過程第三方即使監(jiān)聽到了數(shù)據(jù),也束手無策。

二、加密算法

HTTPS一般使用的加密與HASH算法如下:

  • 非對稱加密算法:RSA,DSA/DSS
  • 對稱加密算法:AES,RC4,3DES
  • HASH算法:MD5,SHA1,SHA256

1. 對稱加密(Symmetric Cryptography)

對稱加密是最快速、最簡單的一種加密方式,加密(encryption)與解密(decryption)用的是同樣的密鑰(secret key)。對稱加密有很多種算法,由于它效率很高,所以被廣泛使用在很多加密協(xié)議的核心當中。
對稱加密通常使用的是相對較小的密鑰,一般小于256 bit。因為密鑰越大,加密越強,但加密與解密的過程越慢。如果你只用1 bit來做這個密鑰,那黑客們可以先試著用0來解密,不行的話就再用1解;但如果你的密鑰有1 MB大,黑客們可能永遠也無法破解,但加密和解密的過程要花費很長的時間。密鑰的大小既要照顧到安全性,也要照顧到效率,是一個trade-off。
2000年10月2日,美國國家標準與技術(shù)研究所(NIST--American National Institute of Standards and Technology)選擇了Rijndael算法作為新的高級加密標準(AES--Advanced Encryption Standard)。.NET中包含了Rijndael算法,類名叫RijndaelManaged,下面舉個例子。

加密過程:

private string myData = "hello";     
private string myPassword = "OpenSesame";
private byte[] cipherText;
private byte[] salt = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0 };
        
    private void mnuSymmetricEncryption_Click(object sender, RoutedEventArgs e)
    {
        var key = new Rfc2898DeriveBytes(myPassword, salt);
        // Encrypt the data.
        var algorithm = new RijndaelManaged();
        algorithm.Key = key.GetBytes(16);
        algorithm.IV = key.GetBytes(16);
        var sourceBytes = new System.Text.UnicodeEncoding().GetBytes(myData);
        using (var sourceStream = new MemoryStream(sourceBytes))
        using (var destinationStream = new MemoryStream())
        using (var crypto = new CryptoStream(sourceStream, algorithm.CreateEncryptor(), CryptoStreamMode.Read))
        {
            moveBytes(crypto, destinationStream);
            cipherText = destinationStream.ToArray();
        }
        MessageBox.Show(String.Format("Data:{0}{1}Encrypted and Encoded:{2}", myData, Environment.NewLine, Convert.ToBase64String(cipherText)));
    }
    private void moveBytes(Stream source, Stream dest)
    {
        byte[] bytes = new byte[2048];
        var count = source.Read(bytes, 0, bytes.Length);
        while (0 != count)
        {
            dest.Write(bytes, 0, count);
            count = source.Read(bytes, 0, bytes.Length);
        }
    }

解密過程:

private void mnuSymmetricDecryption_Click(object sender, RoutedEventArgs e)
    {
        if (cipherText == null)
        {
            MessageBox.Show("Encrypt Data First!");
            return;
        }
        var key = new Rfc2898DeriveBytes(myPassword, salt);
        // Try to decrypt, thus showing it can be round-tripped.
        var algorithm = new RijndaelManaged();
        algorithm.Key = key.GetBytes(16);
        algorithm.IV = key.GetBytes(16);
        using (var sourceStream = new MemoryStream(cipherText))
        using (var destinationStream = new MemoryStream())
        using (var crypto = new CryptoStream(sourceStream, algorithm.CreateDecryptor(), CryptoStreamMode.Read))
        {
            moveBytes(crypto, destinationStream);
            var decryptedBytes = destinationStream.ToArray();
            var decryptedMessage = new UnicodeEncoding().GetString(
            decryptedBytes);
            MessageBox.Show(decryptedMessage);
        }
    }

對稱加密的一大缺點是密鑰的管理與分配,換句話說,如何把密鑰發(fā)送到需要解密你的消息的人的手里是一個問題。在發(fā)送密鑰的過程中,密鑰有很大的風險會被黑客們攔截。現(xiàn)實中通常的做法是將對稱加密的密鑰進行非對稱加密,然后傳送給需要它的人。

2. 非對稱加密(Asymmetric Cryptography)

非對稱加密為數(shù)據(jù)的加密與解密提供了一個非常安全的方法,它使用了一對密鑰,公鑰(public key)和私鑰(private key)。私鑰只能由一方安全保管,不能外泄,而公鑰則可以發(fā)給任何請求它的人。非對稱加密使用這對密鑰中的一個進行加密,而解密則需要另一個密鑰。比如,你向銀行請求公鑰,銀行將公鑰發(fā)給你,你使用公鑰對消息加密,那么只有私鑰的持有人--銀行才能對你的消息解密。與對稱加密不同的是,銀行不需要將私鑰通過網(wǎng)絡(luò)發(fā)送出去,因此安全性大大提高。
目前最常用的非對稱加密算法是RSA算法,是Rivest, Shamir, 和Adleman于1978年發(fā)明,他們那時都是在MIT。.NET中也有RSA算法,請看下面的例子:
加密過程:

private byte[] rsaCipherText;
    private void mnuAsymmetricEncryption_Click(object sender, RoutedEventArgs e)
    {
        var rsa = 1;
        // Encrypt the data.
        var cspParms = new CspParameters(rsa);
        cspParms.Flags = CspProviderFlags.UseMachineKeyStore;
        cspParms.KeyContainerName = "My Keys";
        var algorithm = new RSACryptoServiceProvider(cspParms);
        var sourceBytes = new UnicodeEncoding().GetBytes(myData);
        rsaCipherText = algorithm.Encrypt(sourceBytes, true);
        MessageBox.Show(String.Format("Data: {0}{1}Encrypted and Encoded: {2}",
            myData, Environment.NewLine,
            Convert.ToBase64String(rsaCipherText)));
    }

解密過程:

private void mnuAsymmetricDecryption_Click(object sender, RoutedEventArgs e)
    {
        if(rsaCipherText==null)
        {
            MessageBox.Show("Encrypt First!");
            return;
        }
        var rsa = 1;
        // decrypt the data.
        var cspParms = new CspParameters(rsa);
        cspParms.Flags = CspProviderFlags.UseMachineKeyStore;
        cspParms.KeyContainerName = "My Keys";
        var algorithm = new RSACryptoServiceProvider(cspParms);
        var unencrypted = algorithm.Decrypt(rsaCipherText, true);
        MessageBox.Show(new UnicodeEncoding().GetString(unencrypted));
    }

雖然非對稱加密很安全,但是和對稱加密比起來,它非常的慢,所以我們還是要用對稱加密來傳送消息,但對稱加密所使用的密鑰我們可以通過非對稱加密的方式發(fā)送出去。
了解釋這個過程,請看下面的例子:
(1)Alice需要在銀行的網(wǎng)站做一筆交易,她的瀏覽器首先生成了一個隨機數(shù)作為對稱密鑰。
(2) Alice的瀏覽器向銀行的網(wǎng)站請求公鑰。
(3) 銀行將公鑰發(fā)送給Alice。
(4) Alice的瀏覽器使用銀行的公鑰將自己的對稱密鑰加密。
(5) Alice的瀏覽器將加密后的對稱密鑰發(fā)送給銀行。
(6) 銀行使用私鑰解密得到Alice瀏覽器的對稱密鑰。
(7) Alice與銀行可以使用對稱密鑰來對溝通的內(nèi)容進行加密與解密了。

3. 總結(jié)

(1) 對稱加密加密與解密使用的是同樣的密鑰,所以速度快,但由于需要將密鑰在網(wǎng)絡(luò)傳輸,所以安全性不高。
(2) 非對稱加密使用了一對密鑰,公鑰與私鑰,所以安全性高,但加密與解密速度慢。
(3) 解決的辦法是將對稱加密的密鑰使用非對稱加密的公鑰進行加密,然后發(fā)送出去,接收方使用私鑰進行解密得到對稱加密的密鑰,然后雙方可以使用對稱加密來進行溝通。


image

參考來自

朱祁林-博客園
JF Zhu 的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容