相關推薦:《》
加密模組提供了 HTTP 或 HTTPS 連線過程中封裝安全憑證的方法。也提供了 OpenSSL 的雜湊,hmac, 加密(cipher), 解密(decipher), 簽名(sign) 和 驗證(verify) 方法的封裝。本文將詳細介紹加密crypto
crypto
【crypto.setEngine(engine[, flags])】
為某些/所有 OpenSSL 函數載入並設定引擎(根據引數 flags 來設定)。
engine 可能是 id,或者是指向引擎共用庫的路徑。
flags是可選引數,預設值是ENGINE_METHOD_ALL ,可以是以下一個或多個引數的組合(在constants裡定義)
ENGINE_METHOD_RSA ENGINE_METHOD_DSA ENGINE_METHOD_DH ENGINE_METHOD_RAND ENGINE_METHOD_ECDH ENGINE_METHOD_ECDSA ENGINE_METHOD_CIPHERS ENGINE_METHOD_DIGESTS ENGINE_METHOD_STORE ENGINE_METHOD_PKEY_METH ENGINE_METHOD_PKEY_ASN1_METH ENGINE_METHOD_ALL ENGINE_METHOD_NONE
【crypto.getCiphers()】
返回支援的加密演演算法名陣列
var crypto = require('crypto'); console.log(crypto.getCiphers()); //[ 'aes-128-cbc', 'aes-128-ccm', 'aes-128-cfb', 'aes-128-cfb1', 'aes-128-cfb8', 'aes-128-ctr', 'aes-128-ecb', 'aes-128-gcm', 'aes-128-ofb', 'aes-128-xts', 'aes-192-cbc', 'aes-192-ccm', 'aes-192-cfb', 'aes-192-cfb1', 'aes-192-cfb8', 'aes-192-ctr', 'aes-192-ecb', 'aes-192-gcm', 'aes-192-ofb', 'aes-256-cbc', 'aes-256-ccm', 'aes-256-cfb', 'aes-256-cfb1', 'aes-256-cfb8', 'aes-256-ctr', 'aes-256-ecb', 'aes-256-gcm', 'aes-256-ofb', 'aes-256-xts', 'aes128', 'aes192', 'aes256', 'bf', 'bf-cbc', 'bf-cfb', 'bf-ecb', 'bf-ofb', 'blowfish', 'camellia-128-cbc', 'camellia-128-cfb', 'camellia-128-cfb1', 'camellia-128-cfb8', 'camellia-128-ecb', 'camellia-128-ofb', 'camellia-192-cbc', 'camellia-192-cfb', 'camellia-192-cfb1', 'camellia-192-cfb8', 'camellia-192-ecb', 'camellia-192-ofb', 'camellia-256-cbc', 'camellia-256-cfb', 'camellia-256-cfb1', 'camellia-256-cfb8', 'camellia-256-ecb', 'camellia-256-ofb', 'camellia128', 'camellia192', 'camellia256', 'cast', 'cast-cbc', 'cast5-cbc', 'cast5-cfb', 'cast5-ecb', 'cast5-ofb', 'des', 'des-cbc', 'des-cfb', 'des-cfb1', 'des-cfb8', 'des-ecb', 'des-ede', 'des-ede-cbc', 'des-ede-cfb', 'des-ede-ofb', 'des-ede3', 'des-ede3-cbc', 'des-ede3-cfb', 'des-ede3-cfb1', 'des-ede3-cfb8', 'des-ede3-ofb', 'des-ofb', 'des3', 'desx', 'desx-cbc', 'id-aes128-CCM', 'id-aes128-GCM', 'id-aes128-wrap', 'id-aes192-CCM', 'id-aes192-GCM', 'id-aes192-wrap', 'id-aes256-CCM', 'id-aes256-GCM', 'id-aes256-wrap', 'id-smime-alg-CMS3DESwrap', 'idea', 'idea-cbc', 'idea-cfb', 'idea-ecb', 'idea-ofb', ... 15 more items ]
【crypto.getCiphers()】
返回支援的雜湊演演算法名陣列。
var crypto = require('crypto'); console.log(crypto.getHashes()); //[ 'DSA', 'DSA-SHA', 'DSA-SHA1', 'DSA-SHA1-old', 'RSA-MD4', 'RSA-MD5', 'RSA-MDC2', 'RSA-RIPEMD160', 'RSA-SHA', 'RSA-SHA1', 'RSA-SHA1-2', 'RSA-SHA224', 'RSA-SHA256', 'RSA-SHA384', 'RSA-SHA512', 'dsaEncryption', 'dsaWithSHA', 'dsaWithSHA1', 'dss1', 'ecdsa-with-SHA1', 'md4', 'md4WithRSAEncryption', 'md5', 'md5WithRSAEncryption', 'mdc2', 'mdc2WithRSA', 'ripemd', 'ripemd160', 'ripemd160WithRSA', 'rmd160', 'sha', 'sha1', 'sha1WithRSAEncryption', 'sha224', 'sha224WithRSAEncryption', 'sha256', 'sha256WithRSAEncryption', 'sha384', 'sha384WithRSAEncryption', 'sha512', 'sha512WithRSAEncryption', 'shaWithRSAEncryption', 'ssl2-md5', 'ssl3-md5', 'ssl3-sha1', 'whirlpool' ]
【crypto.getCurves()】
返回支援的橢圓曲線名陣列。
var crypto = require('crypto'); console.log(crypto.getCurves()); //[ 'Oakley-EC2N-3', 'Oakley-EC2N-4', 'brainpoolP160r1', 'brainpoolP160t1', 'brainpoolP192r1', 'brainpoolP192t1', 'brainpoolP224r1', 'brainpoolP224t1', 'brainpoolP256r1', 'brainpoolP256t1', 'brainpoolP320r1', 'brainpoolP320t1', 'brainpoolP384r1', 'brainpoolP384t1', 'brainpoolP512r1', 'brainpoolP512t1', 'c2pnb163v1', 'c2pnb163v2', 'c2pnb163v3', 'c2pnb176v1', 'c2pnb208w1', 'c2pnb272w1', 'c2pnb304w1', 'c2pnb368w1', 'c2tnb191v1', 'c2tnb191v2', 'c2tnb191v3', 'c2tnb239v1', 'c2tnb239v2', 'c2tnb239v3', 'c2tnb359v1', 'c2tnb431r1', 'prime192v1', 'prime192v2', 'prime192v3', 'prime239v1', 'prime239v2', 'prime239v3', 'prime256v1', 'secp112r1', 'secp112r2', 'secp128r1', 'secp128r2', 'secp160k1', 'secp160r1', 'secp160r2', 'secp192k1', 'secp224k1', 'secp224r1', 'secp256k1', 'secp384r1', 'secp521r1', 'sect113r1', 'sect113r2', 'sect131r1', 'sect131r2', 'sect163k1', 'sect163r1', 'sect163r2', 'sect193r1', 'sect193r2', 'sect233k1', 'sect233r1', 'sect239k1', 'sect283k1', 'sect283r1', 'sect409k1', 'sect409r1', 'sect571k1', 'sect571r1', 'wap-wsg-idm-ecid-wtls1', 'wap-wsg-idm-ecid-wtls10', 'wap-wsg-idm-ecid-wtls11', 'wap-wsg-idm-ecid-wtls12', 'wap-wsg-idm-ecid-wtls3', 'wap-wsg-idm-ecid-wtls4', 'wap-wsg-idm-ecid-wtls5', 'wap-wsg-idm-ecid-wtls6', 'wap-wsg-idm-ecid-wtls7', 'wap-wsg-idm-ecid-wtls8', 'wap-wsg-idm-ecid-wtls9' ]
MD5
MD5是一種常用的雜湊演演算法,用於給任意資料一個「簽名」。這個簽名通常用一個十六進位制的字串表示:
【crypto.createHash(algorithm)】
建立並返回一個雜湊物件,使用指定的演演算法來生成雜湊摘要。
引數 algorithm 取決於平臺上 OpenSSL 版本所支援的演演算法。例如,'sha1', 'md5', 'sha256', 'sha512' 等等
【hash.update(data[, input_encoding])】
根據 data 來更新雜湊內容,編碼方式根據 input_encoding 來定,有 'utf8', 'ascii' 或 'binary'。如果沒有傳入值,預設編碼方式是'utf8'。如果 data 是 Buffer, input_encoding 將會被忽略。
因為它是流式資料,所以可以使用不同的資料呼叫很多次。
【hash.digest([encoding])】
計算傳入的資料的雜湊摘要。encoding 可以是 'hex', 'binary' 或 'base64',如果沒有指定encoding ,將返回 buffer。
[注意]呼叫 digest() 後不能再用 hash 物件。
var crypto = require('crypto'); var hash = crypto.createHash('md5'); // 可任意多次呼叫update(): hash.update('Hello, world!'); hash.update('Hello, nodejs!'); console.log(hash.digest('hex')); // 7e1977739c748beac0c0fd14fd26a544
Hmac
Hmac演演算法也是一種雜湊演演算法,它可以利用MD5或SHA1等雜湊演演算法。不同的是,Hmac還需要一個金鑰:
【crypto.createHmac(algorithm, key)】
建立並返回一個 hmac 物件,用指定的演演算法和祕鑰生成 hmac 圖譜。
它是可讀寫的流 stream 。寫入的資料來用計算 hmac。當寫入流結束後,使用 read() 方法來獲取計算後的值。也支援老的 update 和 digest 方法。
引數 algorithm 取決於平臺上 OpenSSL 版本所支援的演演算法,參見前面的 createHash。key是 hmac 演演算法中用的 key
【hmac.update(data)】
根據 data 更新 hmac 物件。因為它是流式資料,所以可以使用新資料呼叫多次。
【hmac.digest([encoding])】
計算傳入資料的 hmac 值。encoding可以是 'hex', 'binary' 或 'base64',如果沒有指定encoding ,將返回 buffer。
[注意]呼叫 digest() 後不能再用 hmac 物件
var crypto = require('crypto'); var hmac = crypto.createHmac('sha256', 'match'); hmac.update('Hello, world!'); hmac.update('Hello, nodejs!'); //e82a58066cae2fae4f44e58be1d589b66a5d102c2e8846d796607f02a88c1649 console.log(hmac.digest('hex'));
AES
AES是一種常用的對稱加密演演算法,加解密都用同一個金鑰。crypto模組提供了AES支援,但是需要自己封裝好函數,便於使用:
【crypto.createCipher(algorithm, password)】
使用傳入的演演算法和祕鑰來生成並返回加密物件。
algorithm 取決於 OpenSSL,例如'aes192'等。password 用來派生 key 和 IV,它必須是一個'binary' 編碼的字串或者一個buffer。
它是可讀寫的流 stream 。寫入的資料來用計算 hmac。當寫入流結束後,使用 read() 方法來獲取計算後的值。也支援老的update 和 digest 方法。
【cipher.update(data[, input_encoding][, output_encoding])】
根據 data 來更新雜湊內容,編碼方式根據 input_encoding 來定,有 'utf8', 'ascii' or 'binary'。如果沒有傳入值,預設編碼方式是'binary'。如果data 是 Buffer,input_encoding 將會被忽略。
output_encoding 指定了輸出的加密資料的編碼格式,它可用是 'binary', 'base64' 或 'hex'。如果沒有提供編碼,將返回 buffer 。
返回加密後的內容,因為它是流式資料,所以可以使用不同的資料呼叫很多次。
【cipher.final([output_encoding])】
返回加密後的內容,編碼方式是由 output_encoding 指定,可以是 'binary', 'base64' 或 'hex'。如果沒有傳入值,將返回 buffer。
[注意]cipher 物件不能在 final() 方法之後呼叫。
var 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; } var data = 'Hello, this is a secret message!'; var key = 'Password!'; var encrypted = aesEncrypt(data, key); //8a944d97bdabc157a5b7a40cb180e713f901d2eb454220d6aaa1984831e17231f87799ef334e3825123658c80e0e5d0c console.log(encrypted);
【crypto.createDecipher(algorithm, password)】
根據傳入的演演算法和金鑰,建立並返回一個解密物件。這是 createCipher() 的映象
【decipher.update(data[, input_encoding][, output_encoding])】
使用引數 data 更新需要解密的內容,其編碼方式是 'binary','base64' 或 'hex'。如果沒有指定編碼方式,則把 data 當成 buffer 物件。
如果 data 是 Buffer,則忽略 input_encoding 引數。
引數 output_decoding 指定返回文字的格式,是 'binary', 'ascii' 或 'utf8' 之一。如果沒有提供編碼格式,則返回 buffer。
【decipher.final([output_encoding])】
返回剩餘的解密過的內容,引數 output_encoding 是 'binary', 'ascii' 或 'utf8',如果沒有指定編碼方式,返回 buffer。
[注意]decipher物件不能在 final() 方法之後使用。
var crypto = require('crypto'); 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 = '8a944d97bdabc157a5b7a40cb180e713f901d2eb454220d6aaa1984831e17231f87799ef334e3825123658c80e0e5d0c'; var decrypted = aesDecrypt(encrypted, key); console.log(decrypted);//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格式
【crypto.createCipheriv(algorithm, key, iv)】
建立並返回一個加密物件,用指定的演演算法,key 和 iv。
algorithm 引數和 createCipher() 一致。key 在演演算法中用到.iv 是一個initialization vector.
key 和 iv 必須是 'binary' 的編碼字串或buffers.
【crypto.createDecipheriv(algorithm, key, iv)】
根據傳入的演演算法,金鑰和 iv,建立並返回一個解密物件。這是 createCipheriv() 的映象。
const crypto = require('crypto'); function aesEncryptiv(data, key,iv) { const cipher = crypto.createCipher('aes192', key, iv); var crypted = cipher.update(data, 'utf8', 'hex'); crypted += cipher.final('hex'); return crypted; } function aesDecryptiv(encrypted, key,iv) { const decipher = crypto.createDecipher('aes192', key, iv); 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 iv = 'match'; var encrypted = aesEncryptiv(data, key, iv); var decrypted = aesDecryptiv(encrypted, key, iv); //Hello, this is a secret message! console.log(data); //8a944d97bdabc157a5b7a40cb180e713f901d2eb454220d6aaa1984831e17231f87799ef334e3825123658c80e0e5d0c console.log(encrypted); //Hello, this is a secret message! console.log(decrypted);
Diffie-Hellman
【crypto.createDiffieHellman(prime[, prime_encoding][, generator][, generator_encoding])】
使用傳入的 prime 和 generator 建立 Diffie-Hellman 祕鑰互動物件。
generator 可以是數位,字串或Buffer。如果沒有指定 generator,使用 2
prime_encoding 和 generator_encoding 可以是 'binary', 'hex', 或 'base64'。
如果沒有指定 prime_encoding, 則 Buffer 為 prime。如果沒有指定 generator_encoding ,則 Buffer 為 generator。
【diffieHellman.generateKeys([encoding])】
生成祕鑰和公鑰,並返回指定格式的公鑰。這個值必須傳給其他部分。編碼方式: 'binary', 'hex', 或 'base64'。如果沒有指定編碼方式,將返回 buffer。
【diffieHellman.getPrime([encoding])】
用引數 encoding 指明的編碼方式返回 Diffie-Hellman 質數,編碼方式為: 'binary', 'hex', 或 'base64'。 如果沒有指定編碼方式,將返回 buffer。
【diffieHellman.getGenerator([encoding])】
用引數 encoding 指明的編碼方式返回 Diffie-Hellman 生成器,編碼方式為: 'binary', 'hex', 或 'base64'. 如果沒有指定編碼方式 ,將返回 buffer。
【diffieHellman.computeSecret(other_public_key[, input_encoding][, output_encoding])】
使用 other_public_key 作為第三方公鑰來計算並返回共用祕密(shared secret)。祕鑰用input_encoding 編碼。編碼方式為:'binary', 'hex', 或 'base64'。如果沒有指定編碼方式 ,預設為 buffer。
如果沒有指定返回編碼方式,將返回 buffer。
DH演演算法
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演演算法如下:
var crypto = require('crypto'); // xiaoming's keys: var ming = crypto.createDiffieHellman(512); var ming_keys = ming.generateKeys(); var prime = ming.getPrime(); var generator = ming.getGenerator(); //Prime: 8df777257625c66821af697652f28e93af05b9f779af919111b89816faa11c36fcf9df04c76811471a6099800213c4fe8e3fbec8d2f90bd00795e4b7fd241603 console.log('Prime: ' + prime.toString('hex')); //Generator: 02 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); //Secret of Xiao Ming: 4237157ab4c9211f78ffdb67d127d749cec91780d594b81a7e75f1fb591fecb84f33ae6591e1edda4bc9685b503010fe8f9928c6ed69e4ff9fdb44adb9ba1539 console.log('Secret of Xiao Ming: ' + ming_secret.toString('hex')); //Secret of Xiao Hong: 4237157ab4c9211f78ffdb67d127d749cec91780d594b81a7e75f1fb591fecb84f33ae6591e1edda4bc9685b503010fe8f9928c6ed69e4ff9fdb44adb9ba1539 console.log('Secret of Xiao Hong: ' + hong_secret.toString('hex'))
[注意]每次輸出都不一樣,因為素數的選擇是隨機的。
更多程式設計相關知識,請存取:!!
以上就是淺談nodejs中的crypto加密模組的詳細內容,更多請關注TW511.COM其它相關文章!