# 加密(Crypto)
~~~
穩定度: 2 - 不穩定;正在討論未來版本的API變動。會盡量減少重大變動的發生。詳見下文。
~~~
使用 `require('crypto')` 來調用該模塊。
crypto模塊提供在HTTPS或HTTP連接中封裝安全憑證的方法.
它提供OpenSSL中的一系列哈希方法,包括hmac、cipher、decipher、簽名和驗證等方法的封裝。
### crypto.getCiphers()
返回一個數組,包含支持的加密算法的名字。
實例:
~~~
var ciphers = crypto.getCiphers();
console.log(ciphers); // ['AES-128-CBC', 'AES-128-CBC-HMAC-SHA1', ...]
~~~
### crypto.getHashes()
返回一個包含所支持的哈希算法的數組。
實例:
~~~
var hashes = crypto.getHashes();
console.log(hashes); // ['sha', 'sha1', 'sha1WithRSAEncryption', ...]
~~~
### crypto.createCredentials(details)
創建一個加密憑證對象,接受一個可選的參數對象:
- `pfx` : 一個字符串或者buffer對象,代表經PFX或者PKCS12編碼產生的私鑰、證書以及CA證書
- `key` : 一個字符串,代表經PEM編碼產生的私鑰
- `passphrase` : 私鑰或者pfx的密碼
- `cert` : 一個字符串,代表經PEM編碼產生的證書
- `ca` : 一個字符串或者字符串數組,表示可信任的經PEM編碼產生的CA證書列表
- `crl` : 一個字符串或者字符串數組,表示經PEM編碼產生的CRL(證書吊銷列表 Certificate Revocation List)
- `ciphers`: 一個字符串,表示需要使用或者排除的加密算法 可以在 [http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT](http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT) 查看更多關于加密算法格式的資料。
如果沒有指定`ca`,node.js會使用[http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt](http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt)提供的公共可信任的CA列表。
### crypto.createHash(algorithm)
創建并返回一個哈希對象,一個使用所給算法的用于生成摘要的加密哈希。
`algorithm` 取決與平臺上所安裝的 OpenSSL 版本所支持的算法。比如 `'sha1'`、`'md5'`、`'sha256'`、`'sha512'` 等等。在最近的發行版本中,`openssl list-message-digest-algorithms` 會顯示可用的摘要算法。
例子:這段程序會計算出一個文件的 sha1 摘要值。
~~~
s.on('end', function() {
var d = shasum.digest('hex');
console.log(d + ' ' + filename);
});
~~~
### 類: Hash
創建數據哈希摘要的類。
它是一個既可讀又可寫的[流](#)。所寫入的數據會被用作計算哈希。當流的可寫端終止后,使用 `read()` 方法來獲取計算得的哈希摘要。同時也支持舊有的 `update` 和 `digest` 方法。
通過 `crypto.createHash` 返回。
### hash.update(data, [input_encoding])
通過提供的數據更新哈希對象,可以通過`input_encoding`指定編碼為`'utf8'`、`'ascii'`或者 `'binary'`。如果沒有指定編碼,將作為二進制數據(buffer)處理。
因為它是流式數據,所以可以使用不同的數據調用很多次。
### hash.digest([encoding])
計算傳入的所有數據的摘要值。`encoding`可以是`'hex'`、`'binary'`或者`'base64'`,如果沒有指定,會返回一個buffer對象。
注意:`hash` 對象在 `digest()` 方法被調用后將不可用。
### crypto.createHmac(algorithm, key)
創建并返回一個hmac對象,也就是通過給定的加密算法和密鑰生成的加密圖譜(cryptographic)。
它是一個既可讀又可寫的流([stream](#))。寫入的數據會被用于計算hmac。寫入終止后,可以使用`read()`方法獲取計算后的摘要值。之前版本的`update`和`digest`方法仍然支持。
`algorithm`在OpenSSL支持的算法列表中被拋棄了——見上方createHash部分。`key`是hmac算法用到的密鑰。
### Class: Hmac
用于創建hmac加密圖譜(cryptographic)的類。
由`crypto.createHmac`返回。
### hmac.update(data)
通過提供的數據更新hmac對象。因為它是流式數據,所以可以使用新數據調用很多次。
### hmac.digest([encoding])
計算傳入的所有數據的hmac摘要值。`encoding`可以是`'hex'`、`'binary'`或者`'base64'`,如果沒有指定,會返回一個buffer對象。
注意: `hmac`對象在調用`digest()`之后就不再可用了。
### crypto.createCipher(algorithm, password)
用給定的算法和密碼,創建并返回一個cipher加密算法的對象。(譯者:cipher 就是加密算法的意思, ssl 的 cipher 主要是對稱加密算法和不對稱加密算法的組合。)
`algorithm`算法是依賴OpenSSL庫的, 例如: `'aes192'`算法等。在最近發布的版本, 執行命令 `openssl list-cipher-algorithms` 就會顯示出所有可用的加密算法,`password`是用來派生key和IV的,它必須是一個 `'binary'` 2進制格式的字符串或者是一個[buffer](#)。(譯者:key表示密鑰,IV表示向量在加密過程和解密過程都要使用)
它是一個既可讀又可寫的[流](#)。所寫入的數據會被用作計算哈希。當流的可寫端終止后,使用 `read()` 方法來獲取計算得的哈希摘要。同時也支持舊有的 `update` 和 `digest` 方法。
### crypto.createCipheriv(algorithm, key, iv)
用給定的算法、密碼和向量,創建并返回一個cipher加密算法的對象。
`algorithm`算法和`createCipher()` 方法的參數相同. `key`密鑰是一個被算法使用的原始密鑰,`iv`是一個[初始化向量](http://en.wikipedia.org/wiki/Initialization_vector)。
`key`密鑰和`iv`向量必須是`'binary'`2進制格式的字符串或[buffers](#).
### Class: Cipher
這個類是用來加密數據的。
這個類由 `crypto.createCipher` 和 `crypto.createCipheriv` 返回。
Cipher加密對象是 [streams](#),他是具有 readable 可讀和 writable 可寫的。寫入的純文本數據是用來在可讀流一側加密數據的。 以前版本的`update` 和`final`方法也還是支持的。
### cipher.update(data, [input_encoding], [output_encoding])
用`data`參數更新cipher加密對象, 它的編碼`input_encoding`必須是下列給定編碼的 `'utf8'`, `'ascii'` or `'binary'` 中一種。如果沒有編碼參數,那么打他參數必須是一個buffer。
參數 `output_encoding`輸出編碼指定了加密數據的輸出格式,可以是`'binary'`, `'base64'` 或者`'hex'`,如果沒有提供這個參數,buffer將會返回。
返回加密內容,并且Returns the enciphered contents, 用新數據作為流的話,它可以被調用多次。
### cipher.final([output_encoding])
返回剩余的加密內容,`output_encoding`為`'binary'`, `'base64'` 或 `'hex'`中的任意一個。 如果沒有提供編碼格式,則返回一個buffer對象。
注: 調用`final()`函數后`cipher` 對象不能被使用。
### cipher.setAutoPadding(auto_padding=true)
對于將輸入數據自動填充到塊大小的功能,你可以將其禁用。如果`auto_padding`是false, 那么整個輸入數據的長度必須是加密器的塊大小的整倍數,否則`final`會失敗。這對非標準的填充很有用,例如使用`0x0`而不是PKCS的填充。這個函數必須在`cipher.final`之前調用。
### crypto.createDecipher(algorithm, password)
根據給定的算法和密鑰,創建并返回一個解密器對象。這是上述[createCipher()](#)的一個鏡像。
### crypto.createDecipheriv(algorithm, key, iv)
Creates and returns a decipher object, with the given algorithm, key and iv. This is the mirror of the [createCipheriv()](#) above. 根據給定的算法,密鑰和初始化向量,創建并返回一個解密器對象。這是上述[createCipheriv()](#)的一個鏡像。
### Class: Decipher
解密數據的類。
由`crypto.createDecipher`和`crypto.createDecipheriv`返回。
解密器對象是可讀寫的[流](#)對象。用被寫入的加密數據生成可讀的平文數據。解碼器對象也支持The legacy `update`和 `final`函數。
### decipher.update(data, [input_encoding], [output_encoding])
用`data`來更新解密器,其中`data`以`'binary'`, `'base64'` 或 `'hex'`進行編碼。如果沒有指明編碼方式,則默認`data`是一個buffer對象。
`output_decoding`指明了用以下哪種編碼方式返回解密后的平文:`'binary'`, `'ascii'` 或 `'utf8'`。如果沒有指明編碼方式,則返回一個buffer對象。
### decipher.final([output_encoding])
返回剩余的加密內容,`output_encoding`為`'binary'`, `'ascii'` 或 `'utf8'`中的任意一個。如果沒有指明編碼方式,則返回一個buffer對象。
注: 調用`final()`函數后不能使用`decipher` 對象。
### decipher.setAutoPadding(auto_padding=true)
如果數據以非標準的塊填充方式被加密,那么你可以禁用自動填充來防止`decipher.final`對數據進行檢查和移除。這只有在輸入數據的長度是加密器塊大小的整倍數時才有效。這個函數必須在將數據流傳遞給`decipher.update`之前調用。
### crypto.createSign(algorithm)
根據給定的算法,創建并返回一個signing對象。在最近的OpenSSL發布版本中,`openssl list-public-key-algorithms`會列出可用的簽名算法,例如`'RSA-SHA256'`。
### Class: Sign
生成數字簽名的類
由`crypto.createSign`返回。
Sign對象是可寫的[流](#)對象。被寫入的數據用來生成數字簽名。當所有的數據都被寫入后,`sign` 函數會返回數字簽名。Sign對象也支持The legacy `update`函數。
### sign.update(data)
用`data`來更新sign對象。 This can be called many times with new data as it is streamed.
### sign.sign(private_key, [output_format])
根據所有傳送給sign的更新數據來計算電子簽名。`private_key`是一個包含了簽名私鑰的字符串,而該私鑰是用PEM編碼的。
返回一個數字簽名,該簽名的格式可以是`'binary'`, `'hex'`或 `'base64'`. 如果沒有指明編碼方式,則返回一個buffer對象。
注:調用`sign()`后不能使用`sign`對象。
### crypto.createVerify(algorithm)
根據指明的算法,創建并返回一個驗證器對象。這是上述簽名器對象的鏡像。
### Class: Verify
用來驗證數字簽名的類。
由 `crypto.createVerify`返回。
驗證器對象是可寫的[流](#)對象. 被寫入的數據會被用來驗證提供的數字簽名。在所有的數據被寫入后,如果提供的數字簽名有效,`verify`函數會返回真。驗證器對象也支持 The legacy `update`函數。
### verifier.update(data)
用數據更新驗證器對象。This can be called many times with new data as it is streamed.
### verifier.verify(object, signature, [signature_format])
用`object`和`signature`來驗證被簽名的數據。 `object`是一個字符串,這個字符串包含了一個被PEM編碼的對象,這個對象可以是RSA公鑰,DSA公鑰或者X.509 證書。 `signature`是之前計算出來的數字簽名,其中的 `signature_format`可以是`'binary'`, `'hex'` 或 `'base64'`. 如果沒有指明編碼方式,那么默認是一個buffer對象。
根據數字簽名對于數據和公鑰的有效性,返回true或false。
注: 調用`verify()`函數后不能使用`verifier`對象。
### crypto.createDiffieHellman(prime_length)
創建一個迪菲-赫爾曼密鑰交換(Diffie-Hellman key exchange)對象,并根據給定的位長度生成一個質數。所用的生成器是`s`。
### crypto.createDiffieHellman(prime, [encoding])
根據給定的質數創建一個迪菲-赫爾曼密鑰交換(Diffie-Hellman key exchange)對象。 所用的生成器是`2`。編碼方式可以是`'binary'`, `'hex'`或 `'base64'`。如果沒有指明編碼方式,則默認是一個buffer對象。
### Class: DiffieHellman
創建迪菲-赫爾曼密鑰交換(Diffie-Hellman key exchanges)的類。
由`crypto.createDiffieHellman`返回。
### diffieHellman.generateKeys([encoding])
生成迪菲-赫爾曼(Diffie-Hellman)算法的公鑰和私鑰,并根據指明的編碼方式返回公鑰。這個公鑰可以轉交給第三方。編碼方式可以是 `'binary'`, `'hex'`或 `'base64'`. 如果沒有指明編碼方式,則返回一個buffer對象。
### diffieHellman.computeSecret(other_public_key, [input_encoding], [output_encoding])
以`other_public_key`作為第三方公鑰來計算共享秘密,并返回這個共享秘密。參數中的密鑰會以`input_encoding`編碼方式來解讀,而共享密鑰則會用`output_encoding`進行編碼。編碼方式可以是`'binary'`, `'hex'`或 `'base64'`。如果沒有提供輸入的編碼方式,則默認為一個buffer對象。
如果沒有指明輸出的編碼方式,則返回一個buffer對象。
### diffieHellman.getPrime([encoding])
根據指明的編碼格式返回迪菲-赫爾曼(Diffie-Hellman)質數,其中編碼方式可以是`'binary'`, `'hex'` 或 `'base64'`。如果沒有指明編碼方式,則返回一個buffer對象。
### diffieHellman.getGenerator([encoding])
根據指明的編碼格式返回迪菲-赫爾曼(Diffie-Hellman)質數,其中編碼方式可以是`'binary'`, `'hex'` 或 `'base64'`。如果沒有指明編碼方式,則返回一個buffer對象。
### diffieHellman.getPublicKey([encoding])
根據指明的編碼格式返回迪菲-赫爾曼(Diffie-Hellman)公鑰,其中編碼方式可以是`'binary'`, `'hex'` 或 `'base64'`。 如果沒有指明編碼方式,則返回一個buffer對象。
### diffieHellman.getPrivateKey([encoding])
根據指明的編碼格式返回迪菲-赫爾曼(Diffie-Hellman)私鑰,其中編碼方式可以是`'binary'`, `'hex'` 或 `'base64'`。如果沒有指明編碼方式,則返回一個buffer對象。
### diffieHellman.setPublicKey(public_key, [encoding])
設置迪菲-赫爾曼(Diffie-Hellman)公鑰,編碼方式可以是可以是`'binary'`, `'hex'` 或 `'base64'`。如果沒有指明編碼方式,則返回一個buffer對象。
### diffieHellman.setPrivateKey(private_key, [encoding])
設置迪菲-赫爾曼(Diffie-Hellman)私鑰,編碼方式可以是可以是`'binary'`, `'hex'` 或 `'base64'`。如果沒有指明編碼方式,則返回一個buffer對象。
### crypto.getDiffieHellman(group_name)
創建一個預定義的迪菲-赫爾曼密鑰交換(Diffie-Hellman key exchanges)對象。支持以下的D-H組:`'modp1'`, `'modp2'`, `'modp5'` (在[RFC 2412](http://www.rfc-editor.org/rfc/rfc2412.txt)中定義) 和 `'modp14'`, `'modp15'`, `'modp16'`, `'modp17'`, `'modp18'` (在 [RFC 3526](http://www.rfc-editor.org/rfc/rfc3526.txt)中定義)。返回的對象模仿了上述 [crypto.createDiffieHellman()](#)方法所創建的對象的接口,但不會暈允許密鑰交換 (例如像 [diffieHellman.setPublicKey()](#)那樣)。執行這套流程的好處是雙方不需要事先生成或交換組余數,節省了處理和通信時間。
例子 (獲取一個共享秘密):
~~~
/* alice_secret和 bob_secret應該是一樣的 */
console.log(alice_secret == bob_secret);
~~~
### crypto.pbkdf2(password, salt, iterations, keylen, callback)
異步PBKDF2提供了一個偽隨機函數 HMAC-SHA1,根據給定密碼的長度,salt和iterations來得出一個密鑰。回調函數得到兩個參數 `(err, derivedKey)`。
### crypto.pbkdf2Sync(password, salt, iterations, keylen)
同步 PBKDF2 函數。返回derivedKey或拋出一個錯誤。
### crypto.randomBytes(size, [callback])
生成密碼學強度的偽隨機數據。用法:
~~~
// 同步
try {
var buf = crypto.randomBytes(256);
console.log('有 %d 字節的隨機數據: %s', buf.length, buf);
} catch (ex) {
// handle error
}
~~~
### crypto.pseudoRandomBytes(size, [callback])
生成*非*密碼學強度的偽隨機數據。如果數據足夠長的話會返回一個唯一的數據,但這個返回值不一定是不可預料的。基于這個原因,當不可預料性很重要時,這個函數的返回值永遠都不應該被使用,例如在生成加密的密鑰時。
用法與 `crypto.randomBytes`一模一樣。
### crypto.DEFAULT_ENCODING
對于可以接受字符串或buffer對象的函數的默認編碼方式。默認值是`'buffer'`,所以默認使用Buffer對象。這是為了讓crypto模塊與默認`'binary'`為編碼方式的遺留程序更容易兼容。
要注意,新的程序會期待buffer對象,所以使用這個時請只作為暫時的手段。
### Recent API Changes
早在統一的流API概念出現,以及引入Buffer對象來處理二進制數據之前,Crypto模塊就被添加到Node。
因為這樣,與流有關的類中并沒有其它Node類的典型函數,而且很多函數接受和返回默認的二進制編碼的字符串,而不是Buffer對象。在最近的修改中,這些函數都被改成默認使用Buffer對象。
這對于某些(但不是全部)使用場景來講是重大的改變。
例如,如果你現在使用Sign類的默認參數,然后在沒有檢查數據的情況下,將結果傳遞給Verify類,那么程序會照常工作。在以前,你會拿到一個二進制字符串,然后它傳遞給Verify對象;而現在,你會得到一個Buffer對象,然后把它傳遞給Verify對象。
但是,如果你以前是使用那些在Buffer對象上不能正常工作的字符串數據,或者以默認編碼方式將二進制數據傳遞給加密函數的話,那你就要開始提供編碼方式參數來指明你想使用的編碼方式了。如果想準換回舊的風格默認使用二進制字符串,那么你需要把`crypto.DEFAULT_ENCODING`字段設為'binary'。但請注意,因為新的程序很可能會期望buffer對象,所以僅將此當做臨時手段。