<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### crypto 單向數據加密 crypto模塊的目的是為了提供通用的加密和哈希算法。用純JavaScript代碼實現這些功能不是不可能,但速度會非常慢。Nodejs用C/C++實現這些算法后,通過cypto這個模塊暴露為JavaScript接口,這樣用起來方便,運行速度也快。 ### MD5和SHA1 MD5是一種常用的哈希算法,用于給任意數據一個“簽名”。這個簽名通常用一個十六進制的字符串表示: ~~~ const crypto = require('crypto'); const hash = crypto.createHash('md5'); // 可任意多次調用update(): hash.update('Hello, world!'); hash.update('Hello, nodejs!'); console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544 ~~~ `update()`方法默認字符串編碼為`UTF-8`,也可以傳入Buffer。 如果要計算SHA1,只需要把`'md5'`改成`'sha1'`,就可以得到SHA1的結果`1f32b9c9932c02227819a4151feed43e131aca40`。 還可以使用更安全的`sha256`和`sha512`。 ### Hmac Hmac算法也是一種哈希算法,它可以利用MD5或SHA1等哈希算法。不同的是,Hmac還需要一個密鑰: ~~~ const crypto = require('crypto'); const hmac = crypto.createHmac('sha256', 'secret-key'); hmac.update('Hello, world!'); hmac.update('Hello, nodejs!'); console.log(hmac.digest('hex')); // 80f7e22570... ~~~ 只要密鑰發生了變化,那么同樣的輸入數據也會得到不同的簽名,因此,可以把Hmac理解為用隨機數“增強”的哈希算法。 ### AES AES是一種常用的對稱加密算法,加解密都用同一個密鑰。crypto模塊提供了AES支持,但是需要自己封裝好函數,便于使用: ~~~ const crypto = require('crypto'); function aesEncrypt(data, key) { const cipher = crypto.createCipher('aes192', key); var crypted = cipher.update(data, 'utf8', 'hex'); crypted += cipher.final('hex'); return crypted; } function aesDecrypt(encrypted, key) { const decipher = crypto.createDecipher('aes192', key); var decrypted = decipher.update(encrypted, 'hex', 'utf8'); decrypted += decipher.final('utf8'); return decrypted; } var data = 'Hello, this is a secret message!'; var key = 'Password!'; var encrypted = aesEncrypt(data, key); var decrypted = aesDecrypt(encrypted, key); console.log('Plain text: ' + data); console.log('Encrypted text: ' + encrypted); console.log('Decrypted text: ' + decrypted); ~~~ 運行結果如下: ~~~ Plain text: Hello, this is a secret message! Encrypted text: 8a944d97bdabc157a5b7a40cb180e7... Decrypted text: Hello, this is a secret message! ~~~ 可以看出,加密后的字符串通過解密又得到了原始內容。 注意到AES有很多不同的算法,如`aes192`,`aes-128-ecb`,`aes-256-cbc`等,AES除了密鑰外還可以指定IV(Initial Vector),不同的系統只要IV不同,用相同的密鑰加密相同的數據得到的加密結果也是不同的。加密結果通常有兩種表示方法:hex和base64,這些功能Nodejs全部都支持,但是在應用中要注意,如果加解密雙方一方用Nodejs,另一方用Java、PHP等其它語言,需要仔細測試。如果無法正確解密,要確認雙方是否遵循同樣的AES算法,字符串密鑰和IV是否相同,加密后的數據是否統一為hex或base64格式。 ### Diffie-Hellman DH算法是一種密鑰交換協議,它可以讓雙方在不泄漏密鑰的情況下協商出一個密鑰來。DH算法基于數學原理,比如小明和小紅想要協商一個密鑰,可以這么做: 1. 小明先選一個素數和一個底數,例如,素數`p=23`,底數`g=5`(底數可以任選),再選擇一個秘密整數`a=6`,計算`A=g^a mod p=8`,然后大聲告訴小紅:`p=23,g=5,A=8`; 2. 小紅收到小明發來的`p`,`g`,`A`后,也選一個秘密整數`b=15`,然后計算`B=g^b mod p=19`,并大聲告訴小明:`B=19`; 3. 小明自己計算出`s=B^a mod p=2`,小紅也自己計算出`s=A^b mod p=2`,因此,最終協商的密鑰`s`為`2`。 在這個過程中,密鑰`2`并不是小明告訴小紅的,也不是小紅告訴小明的,而是雙方協商計算出來的。第三方只能知道`p=23`,`g=5`,`A=8`,`B=19`,由于不知道雙方選的秘密整數`a=6`和`b=15`,因此無法計算出密鑰`2`。 用crypto模塊實現DH算法如下: ~~~ const crypto = require('crypto'); // xiaoming's keys: var ming = crypto.createDiffieHellman(512); var ming_keys = ming.generateKeys(); var prime = ming.getPrime(); var generator = ming.getGenerator(); console.log('Prime: ' + prime.toString('hex')); console.log('Generator: ' + generator.toString('hex')); // xiaohong's keys: var hong = crypto.createDiffieHellman(prime, generator); var hong_keys = hong.generateKeys(); // exchange and generate secret: var ming_secret = ming.computeSecret(hong_keys); var hong_secret = hong.computeSecret(ming_keys); // print secret: console.log('Secret of Xiao Ming: ' + ming_secret.toString('hex')); console.log('Secret of Xiao Hong: ' + hong_secret.toString('hex')); ~~~ 運行后,可以得到如下輸出: ~~~ $ node dh.js Prime: a8224c...deead3 Generator: 02 Secret of Xiao Ming: 695308...d519be Secret of Xiao Hong: 695308...d519be ~~~ 注意每次輸出都不一樣,因為素數的選擇是隨機的。 ### RSA RSA算法是一種非對稱加密算法,即由一個私鑰和一個公鑰構成的密鑰對,通過私鑰加密,公鑰解密,或者通過公鑰加密,私鑰解密。其中,公鑰可以公開,私鑰必須保密。 RSA算法是1977年由Ron Rivest、Adi Shamir和Leonard Adleman共同提出的,所以以他們三人的姓氏的頭字母命名。 當小明給小紅發送信息時,可以用小明自己的私鑰加密,小紅用小明的公鑰解密,也可以用小紅的公鑰加密,小紅用她自己的私鑰解密,這就是非對稱加密。相比對稱加密,非對稱加密只需要每個人各自持有自己的私鑰,同時公開自己的公鑰,不需要像AES那樣由兩個人共享同一個密鑰。 在使用Node進行RSA加密前,我們先要準備好私鑰和公鑰。 首先,在命令行執行以下命令以生成一個RSA密鑰對: ~~~ openssl genrsa -aes256 -out rsa-key.pem 2048 ~~~ 根據提示輸入密碼,這個密碼是用來加密RSA密鑰的,加密方式指定為AES256,生成的RSA的密鑰長度是2048位。執行成功后,我們獲得了加密的`rsa-key.pem`文件。 第二步,通過上面的`rsa-key.pem`加密文件,我們可以導出原始的私鑰,命令如下: ~~~ openssl rsa -in rsa-key.pem -outform PEM -out rsa-prv.pem ~~~ 輸入第一步的密碼,我們獲得了解密后的私鑰。 類似的,我們用下面的命令導出原始的公鑰: ~~~ openssl rsa -in rsa-key.pem -outform PEM -pubout -out rsa-pub.pem ~~~ 這樣,我們就準備好了原始私鑰文件`rsa-prv.pem`和原始公鑰文件`rsa-pub.pem`,編碼格式均為PEM。 下面,使用`crypto`模塊提供的方法,即可實現非對稱加解密。 首先,我們用私鑰加密,公鑰解密: ~~~ const fs = require('fs'), crypto = require('crypto'); // 從文件加載key: function loadKey(file) { // key實際上就是PEM編碼的字符串: return fs.readFileSync(file, 'utf8'); } let prvKey = loadKey('./rsa-prv.pem'), pubKey = loadKey('./rsa-pub.pem'), message = 'Hello, world!'; // 使用私鑰加密: let enc_by_prv = crypto.privateEncrypt(prvKey, Buffer.from(message, 'utf8')); console.log('encrypted by private key: ' + enc_by_prv.toString('hex')); let dec_by_pub = crypto.publicDecrypt(pubKey, enc_by_prv); console.log('decrypted by public key: ' + dec_by_pub.toString('utf8')); ~~~ 執行后,可以得到解密后的消息,與原始消息相同。 接下來我們使用公鑰加密,私鑰解密: ~~~ // 使用公鑰加密: let enc_by_pub = crypto.publicEncrypt(pubKey, Buffer.from(message, 'utf8')); console.log('encrypted by public key: ' + enc_by_pub.toString('hex')); // 使用私鑰解密: let dec_by_prv = crypto.privateDecrypt(prvKey, enc_by_pub); console.log('decrypted by private key: ' + dec_by_prv.toString('utf8')); ~~~ 執行得到的解密后的消息仍與原始消息相同。 如果我們把`message`字符串的長度增加到很長,例如1M,這時,執行RSA加密會得到一個類似這樣的錯誤:`data too large for key size`,這是因為RSA加密的原始信息必須小于Key的長度。那如何用RSA加密一個很長的消息呢?實際上,RSA并不適合加密大數據,而是先生成一個隨機的AES密碼,用AES加密原始信息,然后用RSA加密AES口令,這樣,實際使用RSA時,給對方傳的密文分兩部分,一部分是AES加密的密文,另一部分是RSA加密的AES口令。對方用RSA先解密出AES口令,再用AES解密密文,即可獲得明文。 ### 證書 crypto模塊也可以處理數字證書。數字證書通常用在SSL連接,也就是Web的https連接。一般情況下,https連接只需要處理服務器端的單向認證,如無特殊需求(例如自己作為Root給客戶發認證證書),建議用反向代理服務器如Nginx等Web服務器去處理證書。 ### 參考源碼 [crypto常用算法](https://github.com/michaelliao/learn-javascript/tree/master/samples/node/crypto) *****
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看