<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【W(wǎng)eb技術(shù)】667- 玩轉(zhuǎn)混合加密

          共 17871字,需瀏覽 36分鐘

           ·

          2020-08-01 02:43

          數(shù)據(jù)加密,是一門歷史悠久的技術(shù),指通過加密算法和加密密鑰將明文轉(zhuǎn)變?yōu)槊芪?,而解密則是通過解密算法和解密密鑰將密文恢復(fù)為明文。它的核心是密碼學(xué)。

          數(shù)據(jù)加密仍是計算機(jī)系統(tǒng)對信息進(jìn)行保護(hù)的一種最可靠的辦法。它利用密碼技術(shù)對信息進(jìn)行加密,實(shí)現(xiàn)信息隱蔽,從而起到保護(hù)信息的安全的作用。

          本文阿寶哥將介紹如何對數(shù)據(jù)進(jìn)行混合加密,即使用對稱加密算法與非對稱加密算法對數(shù)據(jù)進(jìn)行加密,從而進(jìn)一步保證數(shù)據(jù)的安全性。閱讀完本文,你將了解以下內(nèi)容:

          • 什么是對稱加密、對稱加密的過程、對稱加密的優(yōu)缺點(diǎn)及 AES 對稱加密算法的使用;
          • 什么是非對稱加密、非對稱加密的過程、非對稱加密的優(yōu)缺點(diǎn)及 RSA 非對稱加密算法的使用;
          • 什么是混合加密、混合加密的過程及如何實(shí)現(xiàn)混合加密。

          在最后的 阿寶哥有話說 環(huán)節(jié),阿寶哥還將簡單介紹一下什么是消息摘要算法和什么是 MD5 算法及其用途與缺陷。

          好的,現(xiàn)在讓我們步入正題。為了讓剛接觸混合加密的小伙伴更好地了解并掌握混合加密,阿寶哥將乘坐 “時光機(jī)” 帶大家來到某個發(fā)版的夜晚...

          那一晚我們團(tuán)隊的小伙伴正在等服務(wù)端數(shù)據(jù)升級,為了讓大家 “忘記” 這個漫漫的升級過程,阿寶哥就立馬組織了一場關(guān)于混合加密的技術(shù)分享會。在阿寶哥 “威逼利誘” 之下,團(tuán)隊的小伙伴們很快就到齊了,之后阿寶哥以以下對話拉開了分享會的序幕:

          幾分鐘過后,小哥講完了,基本關(guān)鍵點(diǎn)都有回答上來,但還遺漏了一些內(nèi)容。為了讓小伙伴們更好地理解對稱加密,阿寶哥對小哥表述的內(nèi)容進(jìn)行了重新梳理,下面讓我們來一起認(rèn)識一下對稱加密。

          一、對稱加密

          1.1 什么是對稱加密

          對稱密鑰算法(英語:Symmetric-key algorithm)又稱為對稱加密、私鑰加密、共享密鑰加密,是密碼學(xué)中的一類加密算法。這類算法在加密和解密時使用相同的密鑰,或是使用兩個可以簡單地相互推算的密鑰。

          1.2 對稱加密的優(yōu)點(diǎn)

          算法公開、計算量小、加密速度快、加密效率高,適合對大量數(shù)據(jù)進(jìn)行加密的場景。 比如 HLS(HTTP Live Streaming)普通加密場景中,一般會使用 AES-128 對稱加密算法對 TS 切片進(jìn)行加密,以保證多媒體資源安全。

          1.3 對稱加密的過程

          發(fā)送方使用密鑰將明文數(shù)據(jù)加密成密文,然后發(fā)送出去,接收方收到密文后,使用同一個密鑰將密文解密成明文讀取。

          1.4 對稱加密的使用示例

          常見的對稱加密算法有 AES、ChaCha20、3DES、Salsa20、DES、Blowfish、IDEA、RC5、RC6、Camellia。這里我們以常見的 AES 算法為例,來介紹一下 AES(Advanced Encryption Standard)對稱加密與解密的過程。

          下面阿寶哥將使用 crypto-js 這個庫來介紹 AES 算法的加密與解密,該庫提供了 CryptoJS.AES.encrypt() 方法用于實(shí)現(xiàn) AES 加密,而 AES 解密對應(yīng)的方法是 CryptoJS.AES.decrypt()。

          基于上述兩個方法阿寶哥進(jìn)一步封裝了 aesEncrypt()aesDecrypt() 這兩個方法,它們分別用于 AES 加密與解密,其具體實(shí)現(xiàn)如下所示:

          1.4.1 AES 加密方法
          //?AES加密
          function?aesEncrypt(content)?{
          ??let?text?=?CryptoJS.enc.Utf8.parse(JSON.stringify(content));
          ??let?encrypted?=?CryptoJS.AES.encrypt(text,?key,?{
          ????iv:?iv,
          ????mode:?CryptoJS.mode.CBC,
          ????padding:?CryptoJS.pad.Pkcs7,
          ??});
          ??return?encrypted.toString();
          }
          1.4.2 AES 解密方法
          //?AES解密
          function?aesDecrypt(content)?{
          ??let?decrypt?=?CryptoJS.AES.decrypt(content,?key,?{
          ????iv:?iv,
          ????mode:?CryptoJS.mode.CBC,
          ????padding:?CryptoJS.pad.Pkcs7,
          ??});
          ??return?decrypt.toString(CryptoJS.enc.Utf8);
          }
          1.4.3 AES 加密與解密示例

          在以上示例中,我們在頁面上創(chuàng)建了 3 個 textarea,分別用于存放明文、加密后的密文和解密后的明文。當(dāng)用戶點(diǎn)擊 加密 按鈕時,會對用戶輸入的明文進(jìn)行 AES 加密,完成加密后,會把密文顯示在密文對應(yīng)的 textarea 中,當(dāng)用戶點(diǎn)擊 解密 按鈕時,會對密文進(jìn)行 AES 解密,完成解密后,會把解密后的明文顯示在對應(yīng)的 textarea 中。

          以上示例對應(yīng)的完整代碼如下所示:



          ??
          ????
          ????
          ????AES?對稱加密與解密示例
          ????
          ??
          ??
          ????

          阿寶哥:AES 對稱加密與解密示例(CBC 模式)


          ????
          ??????
          ????????

          ①明文加密?=>?加密


          ????????
          ??????

          ??????
          ????????

          ②密文解密?=>?解密


          ????????
          ??????

          ??????
          ????????

          ③解密后的明文


          ????????
          ??????

          ????

          ????
          ????
          ????
          ????
          ????
          ????
          ????
          ????
          ????
          ??

          在上面的示例中,我們通過 AES 對稱加密算法,對 “我是阿寶哥” 明文進(jìn)行加密,從而實(shí)現(xiàn)信息隱蔽。

          那么使用對稱加密算法就可以解決我們前面的問題么?答案是否定,這是因為對稱加密存在一些的缺點(diǎn)。

          1.5 對稱加密的缺點(diǎn)

          通過使用對稱加密算法,我們已經(jīng)把明文加密成密文。雖然這解決了數(shù)據(jù)的安全性,但同時也帶來了另一個新的問題。因為對稱加密算法,加密和解密時使用的是同一個密鑰,所以對稱加密的安全性就不僅僅取決于加密算法本身的強(qiáng)度,更取決于密鑰是否被安全的傳輸或保管。

          另外對于實(shí)際應(yīng)用場景,為了避免單一的密鑰被攻破,從而導(dǎo)致所有的加密數(shù)據(jù)被破解,對于不同的數(shù)據(jù),我們一般會使用不同的密鑰進(jìn)行加密,這樣雖然提高了安全性,但也增加了密鑰管理的難度。

          由于對稱加密存在以上的問題,因此它并不是一種好的解決方案。為了找到更好的方案,阿寶哥開始了另一輪新的對話。

          二、非對稱加密

          2.1 什么是非對稱加密

          非對稱加密算法需要兩個密鑰:公開密鑰(publickey:簡稱公鑰)和私有密鑰(privatekey:簡稱私鑰)。公鑰與私鑰是一對,如果用公鑰對數(shù)據(jù)進(jìn)行加密,只有用對應(yīng)的私鑰才能解密。 因為加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。

          2.2 非對稱加密的優(yōu)點(diǎn)

          安全性更高,公鑰是公開的,私鑰是自己保存的,不需要將私鑰提供給別人。

          2.3 非對稱加密的過程

          2.4 非對稱加密的使用示例

          常見的非對稱加密算法有 RSA、Elgamal、背包算法、Rabin、D-H、ECC(橢圓曲線加密算法)。這里我們以常見的 RSA 算法為例,來介紹一下 RSA 非對稱加密與解密的過程。

          RSA 是 1977 年由羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。當(dāng)時他們?nèi)硕荚诼槭±砉W(xué)院工作。RSA 就是他們?nèi)诵帐祥_頭字母拼在一起組成的。

          下面阿寶哥將使用 jsencrypt 這個庫來介紹 RSA 算法的加密與解密,該庫提供了 encrypt() 方法用于實(shí)現(xiàn) RSA 加密,而 RSA 解密對應(yīng)的方法是 decrypt()。

          2.4.1 創(chuàng)建公私鑰

          使用 jsencrypt 這個庫之前,我們需要先生成公鑰和私鑰。接下來阿寶哥以 macOS 系統(tǒng)為例,來介紹一下如何生成公私鑰。

          首先我們先來生成私鑰,在命令行輸入以下命令:

          $?openssl?genrsa?-out?rsa_1024_priv.pem?1024

          在該命令成功運(yùn)行之后,在當(dāng)前目錄下會生成一個 rsa_1024_priv.pem 文件,該文件的內(nèi)容如下:

          -----BEGIN?RSA?PRIVATE?KEY-----
          MIICWwIBAAKBgQDocWYwnJ4DYur0BjxFjJkLv4QRJpTJnwjiwxkuJZe1HTIIuLbu
          /yHyHLhc2MAHKL0Ob+8tcKXKsL1oxs467+q0jA+glOUtBXFcUnutWBbnf9qIDkKP
          ...
          bKkRJNJ2PpfWA45Vdq6u+izrn9e2TabKjWIfTfT/ZQ==
          -----END?RSA?PRIVATE?KEY-----

          然后我們來生成公鑰,同樣在命令行輸入以下命令:

          $?openssl?rsa?-pubout?-in?rsa_1024_priv.pem?-out?rsa_1024_pub.pem

          在該命令成功運(yùn)行之后,在當(dāng)前目錄下會生成一個 rsa_1024_pub.pem 文件,該文件的內(nèi)容如下:

          -----BEGIN?PUBLIC?KEY-----
          MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDocWYwnJ4DYur0BjxFjJkLv4QR
          JpTJnwjiwxkuJZe1HTIIuLbu/yHyHLhc2MAHKL0Ob+8tcKXKsL1oxs467+q0jA+g
          lOUtBXFcUnutWBbnf9qIDkKP2uoDdZ//LUeW7jibVrVJbXU2hxB8bQpBkltZf/xs
          cyhRIeiXxs13vlSHVwIDAQAB
          -----END?PUBLIC?KEY-----
          2.4.2 創(chuàng)建 RSA 加密器和解密器

          創(chuàng)建完公私鑰之后,我們就可以進(jìn)一步創(chuàng)建 RSA 加密器和解密器,具體代碼如下:

          const?PUBLIC_KEY?=?`-----BEGIN?PUBLIC?KEY-----
          MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDocWYwnJ4DYur0BjxFjJkLv4QR
          ...
          cyhRIeiXxs13vlSHVwIDAQAB
          -----END?PUBLIC?KEY-----`
          ;

          const?PRIVATE_KEY?=?`-----BEGIN?RSA?PRIVATE?KEY-----
          MIICWwIBAAKBgQDocWYwnJ4DYur0BjxFjJkLv4QRJpTJnwjiwxkuJZe1HTIIuLbu
          ...
          bKkRJNJ2PpfWA45Vdq6u+izrn9e2TabKjWIfTfT/ZQ==
          -----END?RSA?PRIVATE?KEY-----`
          ;

          const?encryptor?=?new?JSEncrypt();?//?RSA加密器
          encryptor.setPublicKey(PUBLIC_KEY);

          const?decryptor?=?new?JSEncrypt();?//?RSA解密器
          decryptor.setPrivateKey(PRIVATE_KEY);
          2.4.3 RSA 加密與解密示例(下圖標(biāo)題為 RSA非對稱加密)

          在以上示例中,我們在頁面上創(chuàng)建了 3 個 textarea,分別用于存放明文、加密后的密文和解密后的明文。當(dāng)用戶點(diǎn)擊 加密 按鈕時,會對用戶輸入的明文進(jìn)行 RSA 加密,完成加密后,會把密文顯示在密文對應(yīng)的 textarea 中,當(dāng)用戶點(diǎn)擊 解密 按鈕時,會對密文進(jìn)行 RSA 解密,完成解密后,會把解密后的明文顯示在對應(yīng)的 textarea 中。

          以上示例對應(yīng)的完整代碼如下所示:


          <html>
          ??<head>
          ????<meta?charset="UTF-8"?/>
          ????<meta?name="viewport"?content="width=device-width,?initial-scale=1.0"?/>
          ????<title>RSA?非對稱加密與解密示例title>
          ????<style>
          ??????.block?{
          ????????flex:?1;
          ??????}
          ????
          style>
          ??head>
          ??<body>
          ????<h3>阿寶哥:RSA 非對稱加密與解密示例h3>
          ????<div?style="display:?flex;">
          ??????<div?class="block">
          ????????<p>①明文加密?=>?<button?onclick="encrypt()">加密button>p>
          ????????<textarea?id="plaintext"?rows="5"?cols="15">textarea>
          ??????div>
          ??????<div?class="block">
          ????????<p>②密文解密?=>?<button?onclick="decrypt()">解密button>p>
          ????????<textarea?id="ciphertext"?rows="5"?cols="15">textarea>
          ??????div>
          ??????<div?class="block">
          ????????<p>③解密后的明文p>
          ????????<textarea?id="decryptedCiphertext"?rows="5"?cols="15">textarea>
          ??????div>
          ????div>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/2.3.1/jsencrypt.min.js">script>
          ????<script>
          ??????const?PUBLIC_KEY?=?`-----BEGIN?PUBLIC?KEY-----
          MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDocWYwnJ4DYur0BjxFjJkLv4QR
          JpTJnwjiwxkuJZe1HTIIuLbu/yHyHLhc2MAHKL0Ob+8tcKXKsL1oxs467+q0jA+g
          lOUtBXFcUnutWBbnf9qIDkKP2uoDdZ//LUeW7jibVrVJbXU2hxB8bQpBkltZf/xs
          cyhRIeiXxs13vlSHVwIDAQAB
          -----END?PUBLIC?KEY-----`
          ;
          ??????const?PRIVATE_KEY?=?`-----BEGIN?RSA?PRIVATE?KEY-----
          MIICWwIBAAKBgQDocWYwnJ4DYur0BjxFjJkLv4QRJpTJnwjiwxkuJZe1HTIIuLbu
          /yHyHLhc2MAHKL0Ob+8tcKXKsL1oxs467+q0jA+glOUtBXFcUnutWBbnf9qIDkKP
          2uoDdZ//LUeW7jibVrVJbXU2hxB8bQpBkltZf/xscyhRIeiXxs13vlSHVwIDAQAB
          AoGAKOarYKpuc5IYXdArEuHmnFaa2pm7XK8LVTuXVrNuuoPkpfw61Fs4ke3T0yKg
          x6G3gq7Xm1tTEROAgMtaxqwo1D5n1H0nkyDFggLB0K9Ws0frp7HENtSQwdNSry1A
          iD8TLxkhoWo7BS0VViLT1gKOfnw4YeMJP+CcOQ+DQjCsUMECQQD0Nc0vKBTlK6GT
          28gcIMVoQy2KicjiH222A9/TLCNAQ9DEeZDYEptuTfrlbggfWdgQ3nc6CyvGf6c5
          6uBPi/+5AkEA86oqqZPi7ekkUVHx0VSkp0mTlD1tAPhDE8cLX8vyImGExS+tTznz
          ROyzm3T1M1PisdQIU8Wd5rqvHP6dB0enjwJAauhKpMQ1MYYCPApQ9g9anCQcgbOD
          34nGq5HSoE2IOQ/3Cqv1PsIWjRlSJrIemCrqrafWJfDR/xnPCUnLXMd68QJAPNwG
          1d4zMvslcA5ImOFMUuBEtST2geSAVINFqwK0krPKxrmWzxAJW/DHF5AJ4m0UVRhB
          kDLusn90V4iczgGurwJAZUz6w01OeoLhsOuWNvkbTq+IV0NQ5GAEGA721Ck5zp86
          bKkRJNJ2PpfWA45Vdq6u+izrn9e2TabKjWIfTfT/ZQ==
          -----END?RSA?PRIVATE?KEY-----`
          ;

          ??????const?encryptor?=?new?JSEncrypt();?//?RSA加密器
          ??????encryptor.setPublicKey(PUBLIC_KEY);

          ??????const?decryptor?=?new?JSEncrypt();?//?RSA解密器
          ??????decryptor.setPrivateKey(PRIVATE_KEY);

          ??????const?plaintextEle?=?document.querySelector("#plaintext");
          ??????const?ciphertextEle?=?document.querySelector("#ciphertext");
          ??????const?decryptedCiphertextEle?=?document.querySelector(
          ????????"#decryptedCiphertext"
          ??????);

          ??????function?encrypt()?{
          ????????let?plaintext?=?plaintextEle.value;
          ????????ciphertextEle.value?=?encryptor.encrypt(plaintext);
          ??????}

          ??????function?decrypt()?{
          ????????let?ciphertext?=?ciphertextEle.value;
          ????????decryptedCiphertextEle.value?=?decryptor.decrypt(ciphertext);
          ??????}
          ????
          script>
          ??body>
          html>

          在上面的示例中,我們通過 RSA 非對稱加密算法,對 “我是阿寶哥” 明文進(jìn)行加密,從而實(shí)現(xiàn)信息隱蔽。

          那么使用非對稱加密算法就可以解決我們前面的問題么?答案是否定,這是因為非對稱加密也存在一些的缺點(diǎn)。

          2.5 非對稱加密的缺點(diǎn)

          非對稱加密算法加密和解密花費(fèi)時間長、速度慢,只適合對少量數(shù)據(jù)進(jìn)行加密。因為我們要提供的是通用的解決方案,即要同時考慮到少量數(shù)據(jù)和大量數(shù)據(jù)的情況,所以非對稱加密也不是一個好的解決方案。為了解決問題,阿寶哥又重新開啟了一輪新的對話。

          三、混合加密

          3.1 什么是混合加密

          混合加密是結(jié)合 對稱加密非對稱加密 各自優(yōu)點(diǎn)的一種加密方式。其具體的實(shí)現(xiàn)思路是先使用 對稱加密算法 對數(shù)據(jù)進(jìn)行加密,然后使用非對稱加密算法對 對稱加密的密鑰 進(jìn)行非對稱加密,之后再把加密后的密鑰和加密后的數(shù)據(jù)發(fā)送給接收方。

          為了讓小伙伴們更加直觀理解上述的過程,阿寶哥花了點(diǎn)心思畫了一張圖,用來進(jìn)一步說明混合加密的過程,下面我們就一起來看圖吧。

          3.2 混合加密的過程

          3.3 混合加密的實(shí)現(xiàn)

          了解完 “混合加密數(shù)據(jù)傳輸流程”,阿寶哥跟小伙伴一起來實(shí)現(xiàn)一下上述的混合加密流程。這里我們會基于前面介紹過的對稱加密和非對稱加密的示例進(jìn)行開發(fā),即以下示例會直接利用前面非對稱加密示例中用到的公私鑰。

          3.3.1 創(chuàng)建生成隨機(jī) AES 密鑰的函數(shù)
          function?getRandomAESKey()?{
          ??return?(
          ????Math.random().toString(36).substring(2,?10)?+
          ????Math.random().toString(36).substring(2,?10)
          ??);
          }
          3.3.2 創(chuàng)建 AES 加密和解密函數(shù)
          //?AES加密
          function?aesEncrypt(key,?iv,?content)?{
          ??let?text?=?CryptoJS.enc.Utf8.parse(JSON.stringify(content));
          ??let?encrypted?=?CryptoJS.AES.encrypt(text,?key,?{
          ????iv:?iv,
          ????mode:?CryptoJS.mode.CBC,
          ????padding:?CryptoJS.pad.Pkcs7,
          ??});
          ??return?encrypted.toString();
          }

          //?AES解密
          function?aesDecrypt(key,?iv,?content)?{
          ??let?decrypt?=?CryptoJS.AES.decrypt(content,?key,?{
          ????iv:?iv,
          ????mode:?CryptoJS.mode.CBC,
          ????padding:?CryptoJS.pad.Pkcs7,
          ??});
          ??return?decrypt.toString(CryptoJS.enc.Utf8);
          }
          3.3.3 創(chuàng)建 RSA 加密器和解密器
          const?PUBLIC_KEY?=?`-----BEGIN?PUBLIC?KEY-----
          MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDocWYwnJ4DYur0BjxFjJkLv4QR
          ...
          cyhRIeiXxs13vlSHVwIDAQAB
          -----END?PUBLIC?KEY-----`
          ;

          const?PRIVATE_KEY?=?`-----BEGIN?RSA?PRIVATE?KEY-----
          MIICWwIBAAKBgQDocWYwnJ4DYur0BjxFjJkLv4QRJpTJnwjiwxkuJZe1HTIIuLbu
          ...
          bKkRJNJ2PpfWA45Vdq6u+izrn9e2TabKjWIfTfT/ZQ==
          -----END?RSA?PRIVATE?KEY-----`
          ;

          const?rsaEncryptor?=?new?JSEncrypt();?//?RSA加密器
          rsaEncryptor.setPublicKey(PUBLIC_KEY);

          const?rsaDecryptor?=?new?JSEncrypt();?//?RSA解密器
          rsaDecryptor.setPrivateKey(PRIVATE_KEY);
          3.3.4 創(chuàng)建混合加密加密和解密函數(shù)
          function?hybirdEncrypt(data)?{
          ??const?iv?=?getRandomAESKey();
          ??const?key?=?getRandomAESKey();
          ??const?encryptedData?=?aesEncrypt(key,?iv,?data);
          ??const?encryptedIv?=?rsaEncryptor.encrypt(iv);
          ??const?encryptedKey?=?rsaEncryptor.encrypt(key);
          ??return?{
          ????iv:?encryptedIv,
          ????key:?encryptedKey,
          ????data:?encryptedData,
          ???};
          }

          function?hybirdDecrypt(encryptedResult)?{
          ??const?iv?=?rsaDecryptor.decrypt(encryptedResult.iv);
          ??const?key?=?rsaDecryptor.decrypt(encryptedResult.key);
          ??const?data?=?encryptedResult.data;
          ??return?aesDecrypt(key,?iv,?data);
          }
          3.3.5 混合加密與解密示例

          以上步驟完成之后,我們基本已經(jīng)完成了混合加密的功能,在看完整代碼之前,我們先來看一下實(shí)際的運(yùn)行效果:

          備注:密文解密下方對應(yīng)的 textarea 文本框中,除了加密的數(shù)據(jù)之外,還會包含使用 RSA 加密過的 AES CBC 模式中的 iv 和 key。

          在以上示例中,我們在頁面上創(chuàng)建了 3 個 textarea,分別用于存放明文、加密后的數(shù)據(jù)和解密后的明文。當(dāng)用戶點(diǎn)擊 加密 按鈕時,會對用戶輸入的明文進(jìn)行混合加密,完成加密后,會把加密的數(shù)據(jù)顯示在密文對應(yīng)的 textarea 中,當(dāng)用戶點(diǎn)擊 解密 按鈕時,會對密文進(jìn)行 混合解密,即先使用 RSA 私鑰解密 AES 的 key 和 iv,然后再使用它們對 AES 加密過的密文進(jìn)行 AES 解密,完成解密后,會把解密后的明文顯示在對應(yīng)的 textarea 中。

          以上示例對應(yīng)的完整代碼如下所示:


          <html>
          ??<head>
          ????<meta?charset="UTF-8"?/>
          ????<meta?name="viewport"?content="width=device-width,?initial-scale=1.0"?/>
          ????<title>混合加密與解密示例title>
          ????<style>
          ??????.block?{
          ????????flex:?1;
          ??????}
          ????
          style>
          ??head>
          ??<body>
          ????<h3>阿寶哥:混合加密與解密示例h3>
          ????<div?style="display:?flex;">
          ??????<div?class="block">
          ????????<p>①明文加密?=>?<button?onclick="encrypt()">加密button>p>
          ????????<textarea?id="plaintext"?rows="5"?cols="15">textarea>
          ??????div>
          ??????<div?class="block">
          ????????<p>②密文解密?=>?<button?onclick="decrypt()">解密button>p>
          ????????<textarea?id="ciphertext"?rows="5"?cols="15">textarea>
          ??????div>
          ??????<div?class="block">
          ????????<p>③解密后的明文p>
          ????????<textarea?id="decryptedCiphertext"?rows="5"?cols="15">textarea>
          ??????div>
          ????div>
          ????
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/core.min.js">script>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/enc-base64.min.js">script>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/md5.min.js">script>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/evpkdf.min.js">script>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/cipher-core.min.js">script>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/aes.min.js">script>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/pad-pkcs7.min.js">script>
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.0.0/enc-utf8.min.js">script>
          ????
          ????<script?src="https://cdn.bootcdn.net/ajax/libs/jsencrypt/2.3.1/jsencrypt.min.js">script>
          ????<script>
          ??????const?PUBLIC_KEY?=?`-----BEGIN?PUBLIC?KEY-----
          MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDocWYwnJ4DYur0BjxFjJkLv4QR
          JpTJnwjiwxkuJZe1HTIIuLbu/yHyHLhc2MAHKL0Ob+8tcKXKsL1oxs467+q0jA+g
          lOUtBXFcUnutWBbnf9qIDkKP2uoDdZ//LUeW7jibVrVJbXU2hxB8bQpBkltZf/xs
          cyhRIeiXxs13vlSHVwIDAQAB
          -----END?PUBLIC?KEY-----`
          ;
          ??????const?PRIVATE_KEY?=?`-----BEGIN?RSA?PRIVATE?KEY-----
          MIICWwIBAAKBgQDocWYwnJ4DYur0BjxFjJkLv4QRJpTJnwjiwxkuJZe1HTIIuLbu
          /yHyHLhc2MAHKL0Ob+8tcKXKsL1oxs467+q0jA+glOUtBXFcUnutWBbnf9qIDkKP
          2uoDdZ//LUeW7jibVrVJbXU2hxB8bQpBkltZf/xscyhRIeiXxs13vlSHVwIDAQAB
          AoGAKOarYKpuc5IYXdArEuHmnFaa2pm7XK8LVTuXVrNuuoPkpfw61Fs4ke3T0yKg
          x6G3gq7Xm1tTEROAgMtaxqwo1D5n1H0nkyDFggLB0K9Ws0frp7HENtSQwdNSry1A
          iD8TLxkhoWo7BS0VViLT1gKOfnw4YeMJP+CcOQ+DQjCsUMECQQD0Nc0vKBTlK6GT
          28gcIMVoQy2KicjiH222A9/TLCNAQ9DEeZDYEptuTfrlbggfWdgQ3nc6CyvGf6c5
          6uBPi/+5AkEA86oqqZPi7ekkUVHx0VSkp0mTlD1tAPhDE8cLX8vyImGExS+tTznz
          ROyzm3T1M1PisdQIU8Wd5rqvHP6dB0enjwJAauhKpMQ1MYYCPApQ9g9anCQcgbOD
          34nGq5HSoE2IOQ/3Cqv1PsIWjRlSJrIemCrqrafWJfDR/xnPCUnLXMd68QJAPNwG
          1d4zMvslcA5ImOFMUuBEtST2geSAVINFqwK0krPKxrmWzxAJW/DHF5AJ4m0UVRhB
          kDLusn90V4iczgGurwJAZUz6w01OeoLhsOuWNvkbTq+IV0NQ5GAEGA721Ck5zp86
          bKkRJNJ2PpfWA45Vdq6u+izrn9e2TabKjWIfTfT/ZQ==
          -----END?RSA?PRIVATE?KEY-----`
          ;

          ??????const?rsaEncryptor?=?new?JSEncrypt();?//?RSA加密器
          ??????rsaEncryptor.setPublicKey(PUBLIC_KEY);

          ??????const?rsaDecryptor?=?new?JSEncrypt();?//?RSA解密器
          ??????rsaDecryptor.setPrivateKey(PRIVATE_KEY);

          ??????const?plaintextEle?=?document.querySelector("#plaintext");
          ??????const?ciphertextEle?=?document.querySelector("#ciphertext");
          ??????const?decryptedCiphertextEle?=?document.querySelector(
          ????????"#decryptedCiphertext"
          ??????);

          ??????function?getRandomAESKey()?{
          ????????return?(
          ??????????Math.random().toString(36).substring(2,?10)?+
          ??????????Math.random().toString(36).substring(2,?10)
          ????????);
          ??????}

          ??????//?AES加密
          ??????function?aesEncrypt(key,?iv,?content)?{
          ????????let?text?=?CryptoJS.enc.Utf8.parse(JSON.stringify(content));
          ????????let?encrypted?=?CryptoJS.AES.encrypt(text,?key,?{
          ??????????iv:?iv,
          ??????????mode:?CryptoJS.mode.CBC,
          ??????????padding:?CryptoJS.pad.Pkcs7,
          ????????});
          ????????return?encrypted.toString();
          ??????}

          ??????//?AES解密
          ??????function?aesDecrypt(key,?iv,?content)?{
          ????????let?decrypt?=?CryptoJS.AES.decrypt(content,?key,?{
          ??????????iv:?iv,
          ??????????mode:?CryptoJS.mode.CBC,
          ??????????padding:?CryptoJS.pad.Pkcs7,
          ????????});
          ????????return?decrypt.toString(CryptoJS.enc.Utf8);
          ??????}

          ??????function?hybirdEncrypt(data)?{
          ????????const?iv?=?getRandomAESKey();
          ????????const?key?=?getRandomAESKey();
          ????????const?encryptedData?=?aesEncrypt(key,?iv,?data);
          ????????const?encryptedIv?=?rsaEncryptor.encrypt(iv);
          ????????const?encryptedKey?=?rsaEncryptor.encrypt(key);
          ????????return?{
          ??????????iv:?encryptedIv,
          ??????????key:?encryptedKey,
          ??????????data:?encryptedData,
          ????????};
          ??????}

          ??????function?hybirdDecrypt(encryptedResult)?{
          ????????const?iv?=?rsaDecryptor.decrypt(encryptedResult.iv);
          ????????const?key?=?rsaDecryptor.decrypt(encryptedResult.key);
          ????????const?data?=?encryptedResult.data;
          ????????return?aesDecrypt(key,?iv,?data);
          ??????}

          ??????function?encrypt()?{
          ????????let?plaintext?=?plaintextEle.value;
          ????????const?encryptedResult?=?hybirdEncrypt(plaintext);
          ????????ciphertextEle.value?=?JSON.stringify(encryptedResult);
          ??????}

          ??????function?decrypt()?{
          ????????let?ciphertext?=?ciphertextEle.value;
          ????????const?encryptedResult?=?JSON.parse(ciphertext);
          ????????decryptedCiphertextEle.value?=?hybirdDecrypt(encryptedResult).replace(/\"/g,'');
          ??????}
          ????
          script>
          ??body>
          html>

          3.4 混合加密方案分析

          通過這個示例,相信大家對混合加密已經(jīng)有了一定的了解。但在實(shí)際 Web 項目中,我們一般不會在客戶端進(jìn)行數(shù)據(jù)解密,而是會把數(shù)據(jù)提交到服務(wù)端,然后由服務(wù)端進(jìn)行數(shù)據(jù)解密和數(shù)據(jù)處理。

          HTTP 協(xié)議對大多數(shù) Web 開發(fā)者來說,都不會陌生。HTTP 協(xié)議是基于請求和響應(yīng),具體如下圖所示:

          在對數(shù)據(jù)安全要求較高的場景或傳輸敏感數(shù)據(jù)時,我們就可以考慮利用前面的混合加密方案對提交到服務(wù)端的數(shù)據(jù)進(jìn)行混合加密,當(dāng)服務(wù)端接收到對應(yīng)的加密數(shù)據(jù)時,再使用對應(yīng)的解密算法對加密的數(shù)據(jù)進(jìn)行解密,從而進(jìn)一步進(jìn)行數(shù)據(jù)處理。

          但是如果服務(wù)端也要返回敏感數(shù)據(jù)時,應(yīng)該怎么辦呢?這里阿寶哥給大家介紹一種方案,該方案只需使用一對公私鑰。當(dāng)然該方案僅供大家參考,如果你有好的方案,歡迎給阿寶哥留言或跟阿寶哥交流喲。

          下面我們來看一下該方案的具體操作流程:

          ① 生成一個唯一的 reqId(請求 ID),用于標(biāo)識當(dāng)前請求;

          ② 分別生成一個隨機(jī)的 AES Key 和 AES IV(采用 AES CBC 模式);

          ③ 采用 RSA 非對稱加密算法,分別對 AES Key 和 AES IV 進(jìn)行 RSA 非對稱加密;

          ④ 采用隨機(jī)生成的 AES Key 和 AES IV 對敏感數(shù)據(jù)進(jìn)行 AES 對稱加密;

          ⑤ 把 reqId 作為 key,AES Key 和 AES IV 組成的對象作為 value 保存到 Map 或 {} 對象中;

          ⑥ 把 reqId、加密后的 AES Key、AES IV 和加密后的數(shù)據(jù)保存到對象中提交到服務(wù)端;

          ⑦ 當(dāng)服務(wù)端接收到數(shù)據(jù)后,對接收的數(shù)據(jù)進(jìn)行解密,然后使用客戶端傳過來的解密后的 AES Key 和 AES IV 對響應(yīng)數(shù)據(jù)進(jìn)行 AES 對稱加密;

          ⑧ 服務(wù)端在完成數(shù)據(jù)加密后,把 reqId 和加密后的數(shù)據(jù)包裝成響應(yīng)對象,返回給客戶端;

          ⑨ 當(dāng)客戶端成功接收服務(wù)端的響應(yīng)后,先獲取 reqId,進(jìn)而從保存 AES Key 和 IV 的 Map 獲取該 reqId 對應(yīng)的 AES 加密信息;

          ⑩ 客戶端使用當(dāng)前 reqId 對應(yīng)的加密信息,對服務(wù)端返回的數(shù)據(jù)進(jìn)行解密,當(dāng)完成解密之后,從 Map 或 {} 對象中刪除已有記錄。

          現(xiàn)在我們來對上述流程做個簡單分析,首先 AES 加密信息都是隨機(jī)生成的且根據(jù)每個請求獨(dú)立地保存到內(nèi)存中,把 AES 加密信息中的 Key 和 IV 提交到服務(wù)端的時候都會使用 RSA 非對稱加密算法進(jìn)行加密。

          在服務(wù)端返回數(shù)據(jù)的時候,會使用當(dāng)前請求對應(yīng)的 AES 加密信息對返回的結(jié)果進(jìn)行加密,同時返回當(dāng)前請求對應(yīng)的 reqId(請求 ID)。即服務(wù)端不需要再生成新的 AES 加密信息,來對響應(yīng)數(shù)據(jù)進(jìn)行加密,這樣就不需要在響應(yīng)對象中傳遞 AES 加密信息。

          該方案看似挺完美的,由于我們加密的信息還是存在內(nèi)存中,如果使用開發(fā)者工具對 Web 應(yīng)用進(jìn)行調(diào)試時,那么還是可以看到每個請求對應(yīng)的加密信息。那么這個問題該如何解決呢?能不能防止使用開發(fā)者工具對我們的 Web 應(yīng)用進(jìn)行調(diào)試,答案是有的。

          不過這里阿寶哥就不繼續(xù)展開了,后面可能會單獨(dú)寫一篇文章來介紹如何防止使用開發(fā)者工具調(diào)試 Web 應(yīng)用,感興趣的小伙伴可以給我留言喲。

          四、阿寶哥有話說

          4.1 什么是消息摘要算法

          其實(shí)在日常工作中,除了對稱加密和非對稱加密算法之外。還有一種用得比較廣的消息摘要算法。消息摘要算法是密碼學(xué)算法中非常重要的一個分支,它通過對所有數(shù)據(jù)提取指紋信息以實(shí)現(xiàn)數(shù)據(jù)簽名、數(shù)據(jù)完整性校驗等功能,由于其不可逆性,有時候會被用做敏感信息的加密。消息摘要算法也被稱為哈希(Hash)算法或散列算法。

          任何消息經(jīng)過散列函數(shù)處理后,都會獲得唯一的散列值,這一過程稱為 “消息摘要”,其散列值稱為 “數(shù)字指紋”,其算法自然就是 “消息摘要算法”了。 換句話說,如果其數(shù)字指紋一致,就說明其消息是一致的。

          (圖片來源 —— https://zh.wikipedia.org/wiki/散列函數(shù))

          消息摘要算法的主要特征是加密過程不需要密鑰,并且經(jīng)過加密的數(shù)據(jù)無法被解密,目前可以解密逆向的只有 CRC32 算法,只有輸入相同的明文數(shù)據(jù)經(jīng)過相同的消息摘要算法才能得到相同的密文。 消息摘要算法不存在密鑰的管理與分發(fā)問題,適合于分布式網(wǎng)絡(luò)上使用。消息摘要算法主要應(yīng)用在 “數(shù)字簽名” 領(lǐng)域,作為對明文的摘要算法。著名的摘要算法有 RSA 公司的 MD5 算法和 SHA-1 算法及其大量的變體。

          消息摘要算法擁有以下特點(diǎn):

          • 無論輸入的消息有多長,計算出來的消息摘要的長度總是固定的。 例如應(yīng)用 MD5 算法摘要的消息有 128 個比特位,用 SHA-1 算法摘要的消息最終有 160 個比特位的輸出,SHA-1的變體可以產(chǎn)生 192 個比特位和 256 個比特位的消息摘要。一般認(rèn)為,摘要的最終輸出越長,該摘要算法就越安全。
          • 消息摘要看起來是 “隨機(jī)的”。 這些比特看上去是胡亂的雜湊在一起的,可以用大量的輸入來檢驗其輸出是否相同,一般,不同的輸入會有不同的輸出,而且輸出的摘要消息可以通過隨機(jī)性檢驗。一般地,只要輸入的消息不同,對其進(jìn)行摘要以后產(chǎn)生的摘要消息也必不相同;但相同的輸入必會產(chǎn)生相同的輸出。
          • 消息摘要函數(shù)是單向函數(shù),即只能進(jìn)行正向的信息摘要,而無法從摘要中恢復(fù)出任何的消息,甚至根本就找不到任何與原信息相關(guān)的信息。
          • 好的摘要算法,沒有人能從中找到 “碰撞” 或者說極度難找到,雖然 “碰撞” 是肯定存在的(碰撞即不同的內(nèi)容產(chǎn)生相同的摘要)。

          4.2 什么是 MD5 算法

          MD5(Message Digest Algorithm 5,消息摘要算法版本5),它由 MD2、MD3、MD4 發(fā)展而來,由 Ron Rivest(RSA 公司)在 1992 年提出,目前被廣泛應(yīng)用于數(shù)據(jù)完整性校驗、數(shù)據(jù)(消息)摘要、數(shù)據(jù)簽名等。MD2、MD4、MD5 都產(chǎn)生 16 字節(jié)(128 位)的校驗值,一般用 32 位十六進(jìn)制數(shù)表示。MD2 的算法較慢但相對安全,MD4 速度很快,但安全性下降,MD5 比 MD4 更安全、速度更快。

          隨著計算機(jī)技術(shù)的發(fā)展和計算水平的不斷提高,MD5 算法暴露出來的漏洞也越來越多。1996 年后被證實(shí)存在弱點(diǎn),可以被加以破解,對于需要高度安全性的數(shù)據(jù),專家一般建議改用其他算法,如 SHA-2。2004 年,證實(shí) MD5 算法無法防止碰撞(collision),因此不適用于安全性認(rèn)證,如 SSL 公開密鑰認(rèn)證或是數(shù)字簽名等用途。

          4.2.1 MD5 特點(diǎn)
          • 穩(wěn)定、運(yùn)算速度快。
          • 壓縮性:輸入任意長度的數(shù)據(jù),輸出長度固定(128 比特位)。
          • 運(yùn)算不可逆:已知運(yùn)算結(jié)果的情況下,無法通過通過逆運(yùn)算得到原始字符串。
          • 高度離散:輸入的微小變化,可導(dǎo)致運(yùn)算結(jié)果差異巨大。
          4.2.2 MD5 散列

          128 位的 MD5 散列在大多數(shù)情況下會被表示為 32 位十六進(jìn)制數(shù)字。以下是一個 43 位長的僅 ASCII 字母列的MD5 散列:

          MD5("The?quick?brown?fox?jumps?over?the?lazy?dog")
          =?9e107d9d372bb6826bd81d3542a419d6

          即使在原文中作一個小變化(比如把 dog 改為 cog,只改變一個字符)其散列也會發(fā)生巨大的變化:

          MD5("The?quick?brown?fox?jumps?over?the?lazy?cog")
          =?1055d3e698d289f2af8663725127bd4b

          接著我們再來舉幾個 MD5 散列的例子:

          ?????????MD5("")?->?d41d8cd98f00b204e9800998ecf8427e?
          MD5("semlinker")?->?688881f1c8aa6ffd3fcec471e0391e4d
          ???MD5("kakuqo")?->?e18c3c4dd05aef020946e6afbf9e04ef
          4.2.3 MD5 算法的用途

          文件分發(fā)防篡改

          在互聯(lián)網(wǎng)上分發(fā)軟件安裝包時,出于安全性考慮,為了防止軟件被篡改,比如在軟件安裝程序中添加木馬程序。軟件開發(fā)者通常會使用消息摘要算法,比如 MD5 算法產(chǎn)生一個與文件匹配的數(shù)字指紋,這樣接收者在接收到文件后,就可以利用一些現(xiàn)成的工具來檢查文件完整性。

          消息傳輸防篡改

          假設(shè)在網(wǎng)絡(luò)上你需要發(fā)送電子文檔給你的朋友,在文件發(fā)送前,先對文檔的內(nèi)容進(jìn)行 MD5 運(yùn)算,得出該電子文檔的 “數(shù)字指紋”,并把該 “數(shù)字指紋” 隨電子文檔一同發(fā)送給對方。當(dāng)對方接收到電子文檔之后,也使用 MD5 算法對文檔的內(nèi)容進(jìn)行哈希運(yùn)算,在運(yùn)算完成后也會得到一個對應(yīng) “數(shù)字指紋”,當(dāng)該指紋與你所發(fā)送文檔的 “數(shù)字指紋” 一致時,表示文檔在傳輸過程中未被篡改。

          4.2.4 MD5 算法的缺陷

          哈希碰撞是指不同的輸入?yún)s產(chǎn)生了相同的輸出,好的哈希算法,應(yīng)該沒有人能從中找到 “碰撞” 或者說極度難找到,雖然 “碰撞” 是肯定存在的。

          2005 年山東大學(xué)的王小云教授發(fā)布算法可以輕易構(gòu)造 MD5 碰撞實(shí)例,此后 2007 年,有國外學(xué)者在王小云教授算法的基礎(chǔ)上,提出了更進(jìn)一步的 MD5 前綴碰撞構(gòu)造算法 “chosen prefix collision”,此后還有專家陸續(xù)提供了MD5 碰撞構(gòu)造的開源的庫。

          2009 年,中國科學(xué)院的謝濤和馮登國僅用了 220.96 的碰撞算法復(fù)雜度,破解了 MD5 的碰撞抵抗,該攻擊在普通計算機(jī)上運(yùn)行只需要數(shù)秒鐘。

          MD5 碰撞很容易構(gòu)造,基于 MD5 來驗證數(shù)據(jù)完整性已不可靠,考慮到近期谷歌已成功構(gòu)造了 SHA-1(英語:Secure Hash Algorithm 1,中文名:安全散列算法1)的碰撞實(shí)例,對于數(shù)據(jù)完整性,應(yīng)使用 SHA256 或更強(qiáng)的算法代替。

          其實(shí) MD5 的相關(guān)知識還有挺多,比如 MD5 密文反向查詢、密碼加鹽和實(shí)現(xiàn)內(nèi)容資源防盜鏈等。這里阿寶哥就不繼續(xù)展開了,感興趣的小伙伴可以閱讀阿寶哥之前寫的 ”一文讀懂 MD5 算法“ 這篇文章。

          五、參考資源

          • 百度百科 - 數(shù)據(jù)加密
          • 百度百科 - 對稱加密
          推薦閱讀




          玩轉(zhuǎn)前端 Video 播放器

          玩轉(zhuǎn)前端 Video 播放器

          玩轉(zhuǎn)前端文件上傳

          玩轉(zhuǎn)前端文件上傳

          玩轉(zhuǎn)前端二進(jìn)制

          玩轉(zhuǎn)前端二進(jìn)制

          聚焦全棧,專注分享 TypeScript、Web API、Deno 等技術(shù)干貨。


          瀏覽 32
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99三级视频| 嫩草 www天堂资源在线观看 | 豆花视频黄网站在线观看 | 男女啪啪免费网址 | 我要看黄色一级片 |