Node.js v25.0.0 文件
- Node.js v25.0.0
-
目錄
- 加密
- 確定加密支援是否不可用
- 非對稱金鑰型別
- 類:
Certificate - 類:
Cipheriv - 類:
Decipheriv - 類:
DiffieHellmandiffieHellman.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])diffieHellman.generateKeys([encoding])diffieHellman.getGenerator([encoding])diffieHellman.getPrime([encoding])diffieHellman.getPrivateKey([encoding])diffieHellman.getPublicKey([encoding])diffieHellman.setPrivateKey(privateKey[, encoding])diffieHellman.setPublicKey(publicKey[, encoding])diffieHellman.verifyError
- 類:
DiffieHellmanGroup - 類:
ECDH- 靜態方法:
ECDH.convertKey(key, curve[, inputEncoding[, outputEncoding[, format]]]) ecdh.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])ecdh.generateKeys([encoding[, format]])ecdh.getPrivateKey([encoding])ecdh.getPublicKey([encoding][, format])ecdh.setPrivateKey(privateKey[, encoding])ecdh.setPublicKey(publicKey[, encoding])
- 靜態方法:
- 類:
Hash - 類:
Hmac - 類:
KeyObject - 類:
Sign - 類:
Verify - 類:
X509Certificatenew X509Certificate(buffer)x509.cax509.checkEmail(email[, options])x509.checkHost(name[, options])x509.checkIP(ip)x509.checkIssued(otherCert)x509.checkPrivateKey(privateKey)x509.fingerprintx509.fingerprint256x509.fingerprint512x509.infoAccessx509.issuerx509.issuerCertificatex509.keyUsagex509.publicKeyx509.rawx509.serialNumberx509.subjectx509.subjectAltNamex509.toJSON()x509.toLegacyObject()x509.toString()x509.validFromx509.validFromDatex509.validTox509.validToDatex509.signatureAlgorithmx509.signatureAlgorithmOidx509.verify(publicKey)
node:crypto模組的方法和屬性crypto.argon2(algorithm, parameters, callback)crypto.argon2Sync(algorithm, parameters)crypto.checkPrime(candidate[, options], callback)crypto.checkPrimeSync(candidate[, options])crypto.constantscrypto.createCipheriv(algorithm, key, iv[, options])crypto.createDecipheriv(algorithm, key, iv[, options])crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding])crypto.createDiffieHellman(primeLength[, generator])crypto.createDiffieHellmanGroup(name)crypto.createECDH(curveName)crypto.createHash(algorithm[, options])crypto.createHmac(algorithm, key[, options])crypto.createPrivateKey(key)crypto.createPublicKey(key)crypto.createSecretKey(key[, encoding])crypto.createSign(algorithm[, options])crypto.createVerify(algorithm[, options])crypto.decapsulate(key, ciphertext[, callback])crypto.diffieHellman(options[, callback])crypto.encapsulate(key[, callback])crypto.fipscrypto.generateKey(type, options, callback)crypto.generateKeyPair(type, options, callback)crypto.generateKeyPairSync(type, options)crypto.generateKeySync(type, options)crypto.generatePrime(size[, options], callback)crypto.generatePrimeSync(size[, options])crypto.getCipherInfo(nameOrNid[, options])crypto.getCiphers()crypto.getCurves()crypto.getDiffieHellman(groupName)crypto.getFips()crypto.getHashes()crypto.getRandomValues(typedArray)crypto.hash(algorithm, data[, options])crypto.hkdf(digest, ikm, salt, info, keylen, callback)crypto.hkdfSync(digest, ikm, salt, info, keylen)crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)crypto.pbkdf2Sync(password, salt, iterations, keylen, digest)crypto.privateDecrypt(privateKey, buffer)crypto.privateEncrypt(privateKey, buffer)crypto.publicDecrypt(key, buffer)crypto.publicEncrypt(key, buffer)crypto.randomBytes(size[, callback])crypto.randomFill(buffer[, offset][, size], callback)crypto.randomFillSync(buffer[, offset][, size])crypto.randomInt([min, ]max[, callback])crypto.randomUUID([options])crypto.scrypt(password, salt, keylen[, options], callback)crypto.scryptSync(password, salt, keylen[, options])crypto.secureHeapUsed()crypto.setEngine(engine[, flags])crypto.setFips(bool)crypto.sign(algorithm, data, key[, callback])crypto.subtlecrypto.timingSafeEqual(a, b)crypto.verify(algorithm, data, key, signature[, callback])crypto.webcrypto
- 注意
- 加密常量
- 加密
-
索引
- 斷言測試
- 非同步上下文跟蹤
- 非同步鉤子
- 緩衝區
- C++ 外掛
- 使用 Node-API 的 C/C++ 外掛
- C++ 嵌入器 API
- 子程序
- 叢集
- 命令列選項
- 控制檯
- 加密
- 偵錯程式
- 已棄用的 API
- 診斷通道
- DNS
- 域
- 環境變數
- 錯誤
- 事件
- 檔案系統
- 全域性物件
- HTTP
- HTTP/2
- HTTPS
- 檢查器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:moduleAPI - 模組:包
- 模組:TypeScript
- 網路
- 作業系統
- 路徑
- 效能鉤子
- 許可權
- 程序
- Punycode
- 查詢字串
- 逐行讀取
- REPL
- 報告
- 單一可執行檔案應用
- SQLite
- 流
- 字串解碼器
- 測試執行器
- 定時器
- TLS/SSL
- 跟蹤事件
- TTY
- UDP/資料報
- URL
- 實用工具
- V8
- 虛擬機器
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- 其他版本
- 選項
Crypto (加密)#
原始碼: lib/crypto.js
node:crypto 模組提供了加密功能,其中包括一組對 OpenSSL 的雜湊、HMAC、加密、解密、簽名和驗證函式的封裝。
const { createHmac } = await import('node:crypto');
const secret = 'abcdefg';
const hash = createHmac('sha256', secret)
.update('I love cupcakes')
.digest('hex');
console.log(hash);
// Prints:
// c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658econst { createHmac } = require('node:crypto');
const secret = 'abcdefg';
const hash = createHmac('sha256', secret)
.update('I love cupcakes')
.digest('hex');
console.log(hash);
// Prints:
// c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e
確定加密支援是否不可用#
Node.js 在構建時可能不包含對 node:crypto 模組的支援。在這種情況下,嘗試從 crypto import 或呼叫 require('node:crypto') 將導致丟擲錯誤。
使用 CommonJS 時,丟擲的錯誤可以使用 try/catch 捕獲。
let crypto;
try {
crypto = require('node:crypto');
} catch (err) {
console.error('crypto support is disabled!');
}
當使用詞法 ESM import 關鍵字時,只有在嘗試載入模組*之前*註冊了 process.on('uncaughtException') 的處理程式(例如,使用預載入模組),才能捕獲該錯誤。
使用 ESM 時,如果程式碼有可能在未啟用加密支援的 Node.js 版本上執行,請考慮使用 import() 函式,而不是詞法 import 關鍵字。
let crypto;
try {
crypto = await import('node:crypto');
} catch (err) {
console.error('crypto support is disabled!');
}
非對稱金鑰型別#
下表列出了 KeyObject API 識別的非對稱金鑰型別
| 金鑰型別 | 描述 | OID |
|---|---|---|
'dh' | Diffie-Hellman | 1.2.840.113549.1.3.1 |
'dsa' | DSA | 1.2.840.10040.4.1 |
'ec' | 橢圓曲線 | 1.2.840.10045.2.1 |
'ed25519' | Ed25519 | 1.3.101.112 |
'ed448' | Ed448 | 1.3.101.113 |
'ml-dsa-44'1 | ML-DSA-44 | 2.16.840.1.101.3.4.3.17 |
'ml-dsa-65'1 | ML-DSA-65 | 2.16.840.1.101.3.4.3.18 |
'ml-dsa-87'1 | ML-DSA-87 | 2.16.840.1.101.3.4.3.19 |
'ml-kem-512'1 | ML-KEM-512 | 2.16.840.1.101.3.4.4.1 |
'ml-kem-768'1 | ML-KEM-768 | 2.16.840.1.101.3.4.4.2 |
'ml-kem-1024'1 | ML-KEM-1024 | 2.16.840.1.101.3.4.4.3 |
'rsa-pss' | RSA PSS | 1.2.840.113549.1.1.10 |
'rsa' | RSA | 1.2.840.113549.1.1.1 |
'slh-dsa-sha2-128f'1 | SLH-DSA-SHA2-128f | 2.16.840.1.101.3.4.3.21 |
'slh-dsa-sha2-128s'1 | SLH-DSA-SHA2-128s | 2.16.840.1.101.3.4.3.22 |
'slh-dsa-sha2-192f'1 | SLH-DSA-SHA2-192f | 2.16.840.1.101.3.4.3.23 |
'slh-dsa-sha2-192s'1 | SLH-DSA-SHA2-192s | 2.16.840.1.101.3.4.3.24 |
'slh-dsa-sha2-256f'1 | SLH-DSA-SHA2-256f | 2.16.840.1.101.3.4.3.25 |
'slh-dsa-sha2-256s'1 | SLH-DSA-SHA2-256s | 2.16.840.1.101.3.4.3.26 |
'slh-dsa-shake-128f'1 | SLH-DSA-SHAKE-128f | 2.16.840.1.101.3.4.3.27 |
'slh-dsa-shake-128s'1 | SLH-DSA-SHAKE-128s | 2.16.840.1.101.3.4.3.28 |
'slh-dsa-shake-192f'1 | SLH-DSA-SHAKE-192f | 2.16.840.1.101.3.4.3.29 |
'slh-dsa-shake-192s'1 | SLH-DSA-SHAKE-192s | 2.16.840.1.101.3.4.3.30 |
'slh-dsa-shake-256f'1 | SLH-DSA-SHAKE-256f | 2.16.840.1.101.3.4.3.31 |
'slh-dsa-shake-256s'1 | SLH-DSA-SHAKE-256s | 2.16.840.1.101.3.4.3.32 |
'x25519' | X25519 | 1.3.101.110 |
'x448' | X448 | 1.3.101.111 |
類:Certificate#
SPKAC 是一種證書籤名請求機制,最初由 Netscape 實現,並作為 HTML5 keygen 元素的一部分正式指定。
<keygen> 自 HTML 5.2 起已被棄用,新專案不應再使用此元素。
node:crypto 模組提供了 Certificate 類來處理 SPKAC 資料。最常見的用法是處理由 HTML5 <keygen> 元素生成的輸出。Node.js 內部使用 OpenSSL 的 SPKAC 實現。
靜態方法:Certificate.exportChallenge(spkac[, encoding])#
spkac<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>spkac字串的編碼。- 返回:<Buffer>
spkac資料結構中的 challenge 元件,包含公鑰和質詢。
const { Certificate } = await import('node:crypto');
const spkac = getSpkacSomehow();
const challenge = Certificate.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 stringconst { Certificate } = require('node:crypto');
const spkac = getSpkacSomehow();
const challenge = Certificate.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 string
靜態方法:Certificate.exportPublicKey(spkac[, encoding])#
spkac<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>spkac字串的編碼。- 返回:<Buffer>
spkac資料結構中的公鑰元件,包含公鑰和質詢。
const { Certificate } = await import('node:crypto');
const spkac = getSpkacSomehow();
const publicKey = Certificate.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>const { Certificate } = require('node:crypto');
const spkac = getSpkacSomehow();
const publicKey = Certificate.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>
靜態方法:Certificate.verifySpkac(spkac[, encoding])#
spkac<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>spkac字串的編碼。- 返回:<boolean> 如果給定的
spkac資料結構有效,則返回true,否則返回false。
import { Buffer } from 'node:buffer';
const { Certificate } = await import('node:crypto');
const spkac = getSpkacSomehow();
console.log(Certificate.verifySpkac(Buffer.from(spkac)));
// Prints: true or falseconst { Buffer } = require('node:buffer');
const { Certificate } = require('node:crypto');
const spkac = getSpkacSomehow();
console.log(Certificate.verifySpkac(Buffer.from(spkac)));
// Prints: true or false
舊版 API#
作為舊版介面,可以建立 crypto.Certificate 類的新例項,如下例所示。
new crypto.Certificate()#
Certificate 類的例項可以使用 new 關鍵字建立,或者透過呼叫 crypto.Certificate() 作為函式來建立。
const { Certificate } = await import('node:crypto');
const cert1 = new Certificate();
const cert2 = Certificate();const { Certificate } = require('node:crypto');
const cert1 = new Certificate();
const cert2 = Certificate();
certificate.exportChallenge(spkac[, encoding])#
spkac<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>spkac字串的編碼。- 返回:<Buffer>
spkac資料結構中的 challenge 元件,包含公鑰和質詢。
const { Certificate } = await import('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const challenge = cert.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 stringconst { Certificate } = require('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const challenge = cert.exportChallenge(spkac);
console.log(challenge.toString('utf8'));
// Prints: the challenge as a UTF8 string
certificate.exportPublicKey(spkac[, encoding])#
spkac<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>spkac字串的編碼。- 返回:<Buffer>
spkac資料結構中的公鑰元件,包含公鑰和質詢。
const { Certificate } = await import('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const publicKey = cert.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>const { Certificate } = require('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
const publicKey = cert.exportPublicKey(spkac);
console.log(publicKey);
// Prints: the public key as <Buffer ...>
certificate.verifySpkac(spkac[, encoding])#
spkac<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>spkac字串的編碼。- 返回:<boolean> 如果給定的
spkac資料結構有效,則返回true,否則返回false。
import { Buffer } from 'node:buffer';
const { Certificate } = await import('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
console.log(cert.verifySpkac(Buffer.from(spkac)));
// Prints: true or falseconst { Buffer } = require('node:buffer');
const { Certificate } = require('node:crypto');
const cert = Certificate();
const spkac = getSpkacSomehow();
console.log(cert.verifySpkac(Buffer.from(spkac)));
// Prints: true or false
類:Cipheriv#
Cipheriv 類的例項用於加密資料。該類可以透過以下兩種方式之一使用:
- 作為可讀可寫的 流,將未加密的純文字資料寫入,以在可讀端產生加密資料,或者
- 使用
cipher.update()和cipher.final()方法來生成加密資料。
crypto.createCipheriv() 方法用於建立 Cipheriv 例項。不應直接使用 new 關鍵字建立 Cipheriv 物件。
示例:將 Cipheriv 物件用作流
const {
scrypt,
randomFill,
createCipheriv,
} = await import('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
if (err) throw err;
// Then, we'll generate a random initialization vector
randomFill(new Uint8Array(16), (err, iv) => {
if (err) throw err;
// Once we have the key and iv, we can create and use the cipher...
const cipher = createCipheriv(algorithm, key, iv);
let encrypted = '';
cipher.setEncoding('hex');
cipher.on('data', (chunk) => encrypted += chunk);
cipher.on('end', () => console.log(encrypted));
cipher.write('some clear text data');
cipher.end();
});
});const {
scrypt,
randomFill,
createCipheriv,
} = require('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
if (err) throw err;
// Then, we'll generate a random initialization vector
randomFill(new Uint8Array(16), (err, iv) => {
if (err) throw err;
// Once we have the key and iv, we can create and use the cipher...
const cipher = createCipheriv(algorithm, key, iv);
let encrypted = '';
cipher.setEncoding('hex');
cipher.on('data', (chunk) => encrypted += chunk);
cipher.on('end', () => console.log(encrypted));
cipher.write('some clear text data');
cipher.end();
});
});
示例:使用 Cipheriv 和管道流
import {
createReadStream,
createWriteStream,
} from 'node:fs';
import {
pipeline,
} from 'node:stream';
const {
scrypt,
randomFill,
createCipheriv,
} = await import('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
if (err) throw err;
// Then, we'll generate a random initialization vector
randomFill(new Uint8Array(16), (err, iv) => {
if (err) throw err;
const cipher = createCipheriv(algorithm, key, iv);
const input = createReadStream('test.js');
const output = createWriteStream('test.enc');
pipeline(input, cipher, output, (err) => {
if (err) throw err;
});
});
});const {
createReadStream,
createWriteStream,
} = require('node:fs');
const {
pipeline,
} = require('node:stream');
const {
scrypt,
randomFill,
createCipheriv,
} = require('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
if (err) throw err;
// Then, we'll generate a random initialization vector
randomFill(new Uint8Array(16), (err, iv) => {
if (err) throw err;
const cipher = createCipheriv(algorithm, key, iv);
const input = createReadStream('test.js');
const output = createWriteStream('test.enc');
pipeline(input, cipher, output, (err) => {
if (err) throw err;
});
});
});
示例:使用 cipher.update() 和 cipher.final() 方法
const {
scrypt,
randomFill,
createCipheriv,
} = await import('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
if (err) throw err;
// Then, we'll generate a random initialization vector
randomFill(new Uint8Array(16), (err, iv) => {
if (err) throw err;
const cipher = createCipheriv(algorithm, key, iv);
let encrypted = cipher.update('some clear text data', 'utf8', 'hex');
encrypted += cipher.final('hex');
console.log(encrypted);
});
});const {
scrypt,
randomFill,
createCipheriv,
} = require('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// First, we'll generate the key. The key length is dependent on the algorithm.
// In this case for aes192, it is 24 bytes (192 bits).
scrypt(password, 'salt', 24, (err, key) => {
if (err) throw err;
// Then, we'll generate a random initialization vector
randomFill(new Uint8Array(16), (err, iv) => {
if (err) throw err;
const cipher = createCipheriv(algorithm, key, iv);
let encrypted = cipher.update('some clear text data', 'utf8', 'hex');
encrypted += cipher.final('hex');
console.log(encrypted);
});
});
cipher.final([outputEncoding])#
outputEncoding<string> 返回值的編碼。- 返回:<Buffer> | <string> 任何剩餘的加密內容。如果指定了
outputEncoding,則返回一個字串。如果未提供outputEncoding,則返回一個Buffer。
一旦呼叫了 cipher.final() 方法,Cipheriv 物件就不能再用於加密資料。多次嘗試呼叫 cipher.final() 將導致丟擲錯誤。
cipher.getAuthTag()#
- 返回:<Buffer> 當使用認證加密模式(目前支援
GCM、CCM、OCB和chacha20-poly1305)時,cipher.getAuthTag()方法返回一個Buffer,其中包含從給定資料計算出的*認證標籤*。
cipher.getAuthTag() 方法只應在使用 cipher.final() 方法完成加密後呼叫。
如果在 cipher 例項建立期間設定了 authTagLength 選項,此函式將返回確切的 authTagLength 位元組。
cipher.setAAD(buffer[, options])#
buffer<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>options<Object>stream.transform選項- 返回:<Cipheriv> 同一個
Cipheriv例項,用於方法鏈式呼叫。
當使用認證加密模式(目前支援 GCM、CCM、OCB 和 chacha20-poly1305)時,cipher.setAAD() 方法設定用於*附加認證資料*(AAD)輸入引數的值。
對於 GCM 和 OCB,plaintextLength 選項是可選的。使用 CCM 時,必須指定 plaintextLength 選項,並且其值必須與明文的位元組長度匹配。請參見 CCM 模式。
cipher.setAAD() 方法必須在 cipher.update() 之前呼叫。
cipher.setAutoPadding([autoPadding])#
autoPadding<boolean> 預設值:true- 返回:<Cipheriv> 同一個
Cipheriv例項,用於方法鏈式呼叫。
當使用分組加密演算法時,Cipheriv 類會自動向輸入資料新增填充,使其達到適當的分組大小。要停用預設填充,請呼叫 cipher.setAutoPadding(false)。
當 autoPadding 為 false 時,整個輸入資料的長度必須是密碼分組大小的倍數,否則 cipher.final() 會丟擲錯誤。停用自動填充對於非標準填充很有用,例如使用 0x0 而不是 PKCS 填充。
cipher.setAutoPadding() 方法必須在 cipher.final() 之前呼叫。
cipher.update(data[, inputEncoding][, outputEncoding])#
data<string> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string> 資料的編碼。outputEncoding<string> 返回值的編碼。- 返回:<Buffer> | <string>
用 data 更新密碼器。如果給定了 inputEncoding 引數,則 data 引數是使用指定編碼的字串。如果未給定 inputEncoding 引數,data 必須是 Buffer、TypedArray 或 DataView。如果 data 是 Buffer、TypedArray 或 DataView,則忽略 inputEncoding。
outputEncoding 指定加密資料的輸出格式。如果指定了 outputEncoding,則返回使用指定編碼的字串。如果沒有提供 outputEncoding,則返回一個 Buffer。
cipher.update() 方法可以多次呼叫以處理新資料,直到呼叫 cipher.final() 為止。在呼叫 cipher.final() 之後再呼叫 cipher.update() 將導致丟擲錯誤。
類:Decipheriv#
Decipheriv 類的例項用於解密資料。該類可以透過以下兩種方式之一使用:
- 作為一個可讀可寫的 流,將加密的純文字資料寫入,以在可讀端產生未加密的資料,或者
- 使用
decipher.update()和decipher.final()方法來生成未加密的資料。
crypto.createDecipheriv() 方法用於建立 Decipheriv 例項。不應直接使用 new 關鍵字建立 Decipheriv 物件。
示例:將 Decipheriv 物件用作流
import { Buffer } from 'node:buffer';
const {
scryptSync,
createDecipheriv,
} = await import('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Key length is dependent on the algorithm. In this case for aes192, it is
// 24 bytes (192 bits).
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.
const decipher = createDecipheriv(algorithm, key, iv);
let decrypted = '';
decipher.on('readable', () => {
let chunk;
while (null !== (chunk = decipher.read())) {
decrypted += chunk.toString('utf8');
}
});
decipher.on('end', () => {
console.log(decrypted);
// Prints: some clear text data
});
// Encrypted with same algorithm, key and iv.
const encrypted =
'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
decipher.write(encrypted, 'hex');
decipher.end();const {
scryptSync,
createDecipheriv,
} = require('node:crypto');
const { Buffer } = require('node:buffer');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Key length is dependent on the algorithm. In this case for aes192, it is
// 24 bytes (192 bits).
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.
const decipher = createDecipheriv(algorithm, key, iv);
let decrypted = '';
decipher.on('readable', () => {
let chunk;
while (null !== (chunk = decipher.read())) {
decrypted += chunk.toString('utf8');
}
});
decipher.on('end', () => {
console.log(decrypted);
// Prints: some clear text data
});
// Encrypted with same algorithm, key and iv.
const encrypted =
'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
decipher.write(encrypted, 'hex');
decipher.end();
示例:使用 Decipheriv 和管道流
import {
createReadStream,
createWriteStream,
} from 'node:fs';
import { Buffer } from 'node:buffer';
const {
scryptSync,
createDecipheriv,
} = await import('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.
const decipher = createDecipheriv(algorithm, key, iv);
const input = createReadStream('test.enc');
const output = createWriteStream('test.js');
input.pipe(decipher).pipe(output);const {
createReadStream,
createWriteStream,
} = require('node:fs');
const {
scryptSync,
createDecipheriv,
} = require('node:crypto');
const { Buffer } = require('node:buffer');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.
const decipher = createDecipheriv(algorithm, key, iv);
const input = createReadStream('test.enc');
const output = createWriteStream('test.js');
input.pipe(decipher).pipe(output);
示例:使用 decipher.update() 和 decipher.final() 方法
import { Buffer } from 'node:buffer';
const {
scryptSync,
createDecipheriv,
} = await import('node:crypto');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.
const decipher = createDecipheriv(algorithm, key, iv);
// Encrypted using same algorithm, key and iv.
const encrypted =
'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
// Prints: some clear text dataconst {
scryptSync,
createDecipheriv,
} = require('node:crypto');
const { Buffer } = require('node:buffer');
const algorithm = 'aes-192-cbc';
const password = 'Password used to generate key';
// Use the async `crypto.scrypt()` instead.
const key = scryptSync(password, 'salt', 24);
// The IV is usually passed along with the ciphertext.
const iv = Buffer.alloc(16, 0); // Initialization vector.
const decipher = createDecipheriv(algorithm, key, iv);
// Encrypted using same algorithm, key and iv.
const encrypted =
'e5f79c5915c02171eec6b212d5520d44480993d7d622a7c4c2da32f6efda0ffa';
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
// Prints: some clear text data
decipher.final([outputEncoding])#
outputEncoding<string> 返回值的編碼。- 返回:<Buffer> | <string> 任何剩餘的解密內容。如果指定了
outputEncoding,則返回一個字串。如果沒有提供outputEncoding,則返回一個Buffer。
一旦呼叫了 decipher.final() 方法,Decipheriv 物件就不能再用於解密資料。多次嘗試呼叫 decipher.final() 將導致丟擲錯誤。
decipher.setAAD(buffer[, options])#
buffer<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>options<Object>stream.transform選項- 返回:<Decipheriv> 同一個 Decipher 例項,用於方法鏈式呼叫。
當使用認證加密模式(目前支援 GCM、CCM、OCB 和 chacha20-poly1305)時,decipher.setAAD() 方法設定用於*附加認證資料*(AAD)輸入引數的值。
對於 GCM,options 引數是可選的。使用 CCM 時,必須指定 plaintextLength 選項,並且其值必須與密文的位元組長度匹配。請參見 CCM 模式。
decipher.setAAD() 方法必須在 decipher.update() 之前呼叫。
當將字串作為 buffer 傳遞時,請考慮將字串用作加密 API 輸入的注意事項。
decipher.setAuthTag(buffer[, encoding])#
buffer<string> | <Buffer> | <ArrayBuffer> | <TypedArray> | <DataView>encoding<string> 當buffer是字串時使用的字串編碼。- 返回:<Decipheriv> 同一個 Decipher 例項,用於方法鏈式呼叫。
當使用認證加密模式(目前支援 GCM、CCM、OCB 和 chacha20-poly1305)時,decipher.setAuthTag() 方法用於傳入接收到的*認證標籤*。如果沒有提供標籤,或者密文被篡改,decipher.final() 將會丟擲異常,表明由於認證失敗,應丟棄該密文。如果標籤長度根據 NIST SP 800-38D 無效,或者與 authTagLength 選項的值不匹配,decipher.setAuthTag() 將丟擲錯誤。
對於 CCM 模式,decipher.setAuthTag() 必須在 decipher.update() 之前呼叫;對於 GCM、OCB 模式和 chacha20-poly1305,則必須在 decipher.final() 之前呼叫。decipher.setAuthTag() 只能呼叫一次。
當將字串作為認證標籤傳遞時,請考慮將字串用作加密 API 輸入的注意事項。
decipher.setAutoPadding([autoPadding])#
autoPadding<boolean> 預設值:true- 返回:<Decipheriv> 同一個 Decipher 例項,用於方法鏈式呼叫。
當資料在沒有標準塊填充的情況下被加密時,呼叫 decipher.setAutoPadding(false) 將停用自動填充,以防止 decipher.final() 檢查和移除填充。
關閉自動填充僅在輸入資料的長度是密碼器塊大小的倍數時才有效。
decipher.setAutoPadding() 方法必須在 decipher.final() 之前呼叫。
decipher.update(data[, inputEncoding][, outputEncoding])#
data<string> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string>data字串的編碼。outputEncoding<string> 返回值的編碼。- 返回:<Buffer> | <string>
用 data 更新解密器。如果給定了 inputEncoding 引數,則 data 引數是使用指定編碼的字串。如果未給定 inputEncoding 引數,data 必須是 Buffer。如果 data 是 Buffer,則忽略 inputEncoding。
outputEncoding 指定加密資料的輸出格式。如果指定了 outputEncoding,則返回使用指定編碼的字串。如果沒有提供 outputEncoding,則返回一個 Buffer。
decipher.update() 方法可以多次呼叫以處理新資料,直到呼叫 decipher.final() 為止。在呼叫 decipher.final() 之後再呼叫 decipher.update() 將導致丟擲錯誤。
即使底層密碼器實現了認證,此函式返回的明文的真實性和完整性此時可能不確定。對於認證加密演算法,真實性通常只有在應用程式呼叫 decipher.final() 時才能確定。
類:DiffieHellman#
DiffieHellman 類是用於建立 Diffie-Hellman 金鑰交換的實用工具。
DiffieHellman 類的例項可以使用 crypto.createDiffieHellman() 函式建立。
import assert from 'node:assert';
const {
createDiffieHellman,
} = await import('node:crypto');
// Generate Alice's keys...
const alice = createDiffieHellman(2048);
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
const bob = createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
// OK
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));const assert = require('node:assert');
const {
createDiffieHellman,
} = require('node:crypto');
// Generate Alice's keys...
const alice = createDiffieHellman(2048);
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
const bob = createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
// OK
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
diffieHellman.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])#
otherPublicKey<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string>otherPublicKey字串的編碼。outputEncoding<string> 返回值的編碼。- 返回:<Buffer> | <string>
使用 otherPublicKey 作為另一方的公鑰計算共享金鑰,並返回計算出的共享金鑰。提供的金鑰使用指定的 inputEncoding 進行解釋,金鑰使用指定的 outputEncoding 進行編碼。如果未提供 inputEncoding,則 otherPublicKey 應為 Buffer、TypedArray 或 DataView。
如果指定了 outputEncoding,則返回一個字串;否則,返回一個 Buffer。
diffieHellman.generateKeys([encoding])#
生成私有和公共 Diffie-Hellman 金鑰值,除非它們已經被生成或計算過,並以指定的 encoding 返回公鑰。此金鑰應傳輸給另一方。如果提供了 encoding,則返回一個字串;否則返回一個 Buffer。
此函式是 DH_generate_key() 的一個薄封裝。特別地,一旦生成或設定了私鑰,呼叫此函式僅更新公鑰,而不會生成新的私鑰。
diffieHellman.getGenerator([encoding])#
以指定的 encoding 返回 Diffie-Hellman 生成器。如果提供了 encoding,則返回一個字串;否則返回一個 Buffer。
diffieHellman.getPrime([encoding])#
以指定的 encoding 返回 Diffie-Hellman 素數。如果提供了 encoding,則返回一個字串;否則返回一個 Buffer。
diffieHellman.getPrivateKey([encoding])#
以指定的 encoding 返回 Diffie-Hellman 私鑰。如果提供了 encoding,則返回一個字串;否則返回一個 Buffer。
diffieHellman.getPublicKey([encoding])#
以指定的 encoding 返回 Diffie-Hellman 公鑰。如果提供了 encoding,則返回一個字串;否則返回一個 Buffer。
diffieHellman.setPrivateKey(privateKey[, encoding])#
privateKey<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>privateKey字串的編碼。
設定 Diffie-Hellman 私鑰。如果提供了 encoding 引數,privateKey 應為一個字串。如果沒有提供 encoding,privateKey 應為一個 Buffer、TypedArray 或 DataView。
此函式不會自動計算相關的公鑰。可以使用 diffieHellman.setPublicKey() 或 diffieHellman.generateKeys() 來手動提供公鑰或自動推導它。
diffieHellman.setPublicKey(publicKey[, encoding])#
publicKey<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>publicKey字串的編碼。
設定 Diffie-Hellman 公鑰。如果提供了 encoding 引數,publicKey 應為一個字串。如果沒有提供 encoding,publicKey 應為一個 Buffer、TypedArray 或 DataView。
diffieHellman.verifyError#
一個位欄位,包含在 DiffieHellman 物件初始化期間執行檢查時產生的任何警告和/或錯誤。
以下值對此屬性有效(定義在 node:constants 模組中):
DH_CHECK_P_NOT_SAFE_PRIMEDH_CHECK_P_NOT_PRIMEDH_UNABLE_TO_CHECK_GENERATORDH_NOT_SUITABLE_GENERATOR
類:DiffieHellmanGroup#
DiffieHellmanGroup 類以一個著名的 modp 組作為其引數。它的工作方式與 DiffieHellman 相同,只是不允許在建立後更改其金鑰。換句話說,它沒有實現 setPublicKey() 或 setPrivateKey() 方法。
const { createDiffieHellmanGroup } = await import('node:crypto');
const dh = createDiffieHellmanGroup('modp16');const { createDiffieHellmanGroup } = require('node:crypto');
const dh = createDiffieHellmanGroup('modp16');
支援以下組:
'modp14'(2048 位, RFC 3526 第 3 節)'modp15'(3072 位, RFC 3526 第 4 節)'modp16'(4096 位, RFC 3526 第 5 節)'modp17'(6144 位, RFC 3526 第 6 節)'modp18'(8192 位, RFC 3526 第 7 節)
以下組仍然支援但已棄用(參見注意事項):
'modp1'(768 位, RFC 2409 第 6.1 節)'modp2'(1024 位, RFC 2409 第 6.2 節)'modp5'(1536 位, RFC 3526 第 2 節)
這些已棄用的組可能會在未來版本的 Node.js 中被移除。
類:ECDH#
ECDH 類是用於建立橢圓曲線 Diffie-Hellman (ECDH) 金鑰交換的實用工具。
ECDH 類的例項可以使用 crypto.createECDH() 函式建立。
import assert from 'node:assert';
const {
createECDH,
} = await import('node:crypto');
// Generate Alice's keys...
const alice = createECDH('secp521r1');
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
const bob = createECDH('secp521r1');
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
// OKconst assert = require('node:assert');
const {
createECDH,
} = require('node:crypto');
// Generate Alice's keys...
const alice = createECDH('secp521r1');
const aliceKey = alice.generateKeys();
// Generate Bob's keys...
const bob = createECDH('secp521r1');
const bobKey = bob.generateKeys();
// Exchange and generate the secret...
const aliceSecret = alice.computeSecret(bobKey);
const bobSecret = bob.computeSecret(aliceKey);
assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex'));
// OK
靜態方法:ECDH.convertKey(key, curve[, inputEncoding[, outputEncoding[, format]]])#
key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>curve<string>inputEncoding<string>key字串的編碼。outputEncoding<string> 返回值的編碼。format<string> 預設值:'uncompressed'- 返回:<Buffer> | <string>
將由 key 和 curve 指定的 EC Diffie-Hellman 公鑰轉換為由 format 指定的格式。format 引數指定點編碼,可以是 'compressed'、'uncompressed' 或 'hybrid'。提供的金鑰使用指定的 inputEncoding 進行解釋,返回的金鑰使用指定的 outputEncoding 進行編碼。
使用 crypto.getCurves() 獲取可用曲線名稱的列表。在最近的 OpenSSL 版本中,openssl ecparam -list_curves 也會顯示每個可用橢圓曲線的名稱和描述。
如果未指定 format,則點將以 'uncompressed' 格式返回。
如果未提供 inputEncoding,則 key 應為一個 Buffer、TypedArray 或 DataView。
示例(解壓縮一個金鑰)
const {
createECDH,
ECDH,
} = await import('node:crypto');
const ecdh = createECDH('secp256k1');
ecdh.generateKeys();
const compressedKey = ecdh.getPublicKey('hex', 'compressed');
const uncompressedKey = ECDH.convertKey(compressedKey,
'secp256k1',
'hex',
'hex',
'uncompressed');
// The converted key and the uncompressed public key should be the same
console.log(uncompressedKey === ecdh.getPublicKey('hex'));const {
createECDH,
ECDH,
} = require('node:crypto');
const ecdh = createECDH('secp256k1');
ecdh.generateKeys();
const compressedKey = ecdh.getPublicKey('hex', 'compressed');
const uncompressedKey = ECDH.convertKey(compressedKey,
'secp256k1',
'hex',
'hex',
'uncompressed');
// The converted key and the uncompressed public key should be the same
console.log(uncompressedKey === ecdh.getPublicKey('hex'));
ecdh.computeSecret(otherPublicKey[, inputEncoding][, outputEncoding])#
otherPublicKey<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string>otherPublicKey字串的編碼。outputEncoding<string> 返回值的編碼。- 返回:<Buffer> | <string>
使用 otherPublicKey 作為另一方的公鑰計算共享金鑰,並返回計算出的共享金鑰。提供的金鑰使用指定的 inputEncoding 進行解釋,返回的金鑰使用指定的 outputEncoding 進行編碼。如果未提供 inputEncoding,則 otherPublicKey 應為一個 Buffer、TypedArray 或 DataView。
如果指定了 outputEncoding,將返回一個字串;否則返回一個 Buffer。
當 otherPublicKey 不在橢圓曲線上時,ecdh.computeSecret 會丟擲 ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY 錯誤。由於 otherPublicKey 通常由遠端使用者透過不安全的網路提供,請務必相應地處理此異常。
ecdh.generateKeys([encoding[, format]])#
生成私有和公共 EC Diffie-Hellman 金鑰值,並以指定的 format 和 encoding 返回公鑰。此金鑰應傳輸給另一方。
format 引數指定點編碼,可以是 'compressed' 或 'uncompressed'。如果未指定 format,則點將以 'uncompressed' 格式返回。
如果提供了 encoding,則返回一個字串;否則返回一個 Buffer。
ecdh.getPublicKey([encoding][, format])#
encoding<string> 返回值的編碼。format<string> 預設值:'uncompressed'- 返回:<Buffer> | <string> 指定
encoding和format的 EC Diffie-Hellman 公鑰。
format 引數指定點編碼,可以是 'compressed' 或 'uncompressed'。如果未指定 format,則點將以 'uncompressed' 格式返回。
如果指定了 encoding,則返回一個字串;否則返回一個 Buffer。
ecdh.setPrivateKey(privateKey[, encoding])#
privateKey<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>privateKey字串的編碼。
設定 EC Diffie-Hellman 私鑰。如果提供了 encoding,則 privateKey 應為一個字串;否則 privateKey 應為一個 Buffer、TypedArray 或 DataView。
如果 privateKey 對建立 ECDH 物件時指定的曲線無效,則會丟擲錯誤。設定私鑰後,相關的公鑰點(金鑰)也會生成並設定在 ECDH 物件中。
ecdh.setPublicKey(publicKey[, encoding])#
publicKey<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string>publicKey字串的編碼。
設定 EC Diffie-Hellman 公鑰。如果提供了 encoding,則 publicKey 應為一個字串;否則應為一個 Buffer、TypedArray 或 DataView。
通常沒有理由呼叫此方法,因為 ECDH 只需要一個私鑰和另一方的公鑰來計算共享金鑰。通常會呼叫 ecdh.generateKeys() 或 ecdh.setPrivateKey()。ecdh.setPrivateKey() 方法會嘗試生成與正在設定的私鑰相關的公鑰點/金鑰。
示例(獲取共享金鑰)
const {
createECDH,
createHash,
} = await import('node:crypto');
const alice = createECDH('secp256k1');
const bob = createECDH('secp256k1');
// This is a shortcut way of specifying one of Alice's previous private
// keys. It would be unwise to use such a predictable private key in a real
// application.
alice.setPrivateKey(
createHash('sha256').update('alice', 'utf8').digest(),
);
// Bob uses a newly generated cryptographically strong
// pseudorandom key pair
bob.generateKeys();
const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');
// aliceSecret and bobSecret should be the same shared secret value
console.log(aliceSecret === bobSecret);const {
createECDH,
createHash,
} = require('node:crypto');
const alice = createECDH('secp256k1');
const bob = createECDH('secp256k1');
// This is a shortcut way of specifying one of Alice's previous private
// keys. It would be unwise to use such a predictable private key in a real
// application.
alice.setPrivateKey(
createHash('sha256').update('alice', 'utf8').digest(),
);
// Bob uses a newly generated cryptographically strong
// pseudorandom key pair
bob.generateKeys();
const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');
// aliceSecret and bobSecret should be the same shared secret value
console.log(aliceSecret === bobSecret);
類:Hash#
Hash 類是用於建立資料雜湊摘要的實用工具。它可以透過以下兩種方式之一使用:
- 作為一個可讀可寫的 流,將資料寫入以在可讀端產生計算出的雜湊摘要,或者
- 使用
hash.update()和hash.digest()方法來生成計算出的雜湊。
crypto.createHash() 方法用於建立 Hash 例項。不應直接使用 new 關鍵字建立 Hash 物件。
示例:將 Hash 物件用作流
const {
createHash,
} = await import('node:crypto');
const hash = createHash('sha256');
hash.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = hash.read();
if (data) {
console.log(data.toString('hex'));
// Prints:
// 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
}
});
hash.write('some data to hash');
hash.end();const {
createHash,
} = require('node:crypto');
const hash = createHash('sha256');
hash.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = hash.read();
if (data) {
console.log(data.toString('hex'));
// Prints:
// 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
}
});
hash.write('some data to hash');
hash.end();
示例:使用 Hash 和管道流
import { createReadStream } from 'node:fs';
import { stdout } from 'node:process';
const { createHash } = await import('node:crypto');
const hash = createHash('sha256');
const input = createReadStream('test.js');
input.pipe(hash).setEncoding('hex').pipe(stdout);const { createReadStream } = require('node:fs');
const { createHash } = require('node:crypto');
const { stdout } = require('node:process');
const hash = createHash('sha256');
const input = createReadStream('test.js');
input.pipe(hash).setEncoding('hex').pipe(stdout);
示例:使用 hash.update() 和 hash.digest() 方法
const {
createHash,
} = await import('node:crypto');
const hash = createHash('sha256');
hash.update('some data to hash');
console.log(hash.digest('hex'));
// Prints:
// 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50const {
createHash,
} = require('node:crypto');
const hash = createHash('sha256');
hash.update('some data to hash');
console.log(hash.digest('hex'));
// Prints:
// 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
hash.copy([options])#
options<Object>stream.transform選項- 返回:<Hash>
建立一個新的 Hash 物件,其中包含當前 Hash 物件內部狀態的深複製。
可選的 options 引數控制流的行為。對於 XOF 雜湊函式(如 'shake256'),可以使用 outputLength 選項來指定所需的輸出長度(以位元組為單位)。
當在其 hash.digest() 方法被呼叫後嘗試複製 Hash 物件時,會丟擲一個錯誤。
// Calculate a rolling hash.
const {
createHash,
} = await import('node:crypto');
const hash = createHash('sha256');
hash.update('one');
console.log(hash.copy().digest('hex'));
hash.update('two');
console.log(hash.copy().digest('hex'));
hash.update('three');
console.log(hash.copy().digest('hex'));
// Etc.// Calculate a rolling hash.
const {
createHash,
} = require('node:crypto');
const hash = createHash('sha256');
hash.update('one');
console.log(hash.copy().digest('hex'));
hash.update('two');
console.log(hash.copy().digest('hex'));
hash.update('three');
console.log(hash.copy().digest('hex'));
// Etc.
hash.digest([encoding])#
計算所有被傳入進行雜湊處理的資料的摘要(使用 hash.update() 方法)。如果提供了 encoding,將返回一個字串;否則返回一個 Buffer。
在 hash.digest() 方法被呼叫後,Hash 物件不能再次使用。多次呼叫會引發錯誤。
hash.update(data[, inputEncoding])#
data<string> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string>data字串的編碼。
用給定的 data 更新雜湊內容,其編碼在 inputEncoding 中給出。如果未提供 encoding,且 data 是一個字串,則強制使用 'utf8' 編碼。如果 data 是一個 Buffer、TypedArray 或 DataView,則忽略 inputEncoding。
當新資料以流式傳輸時,可以多次呼叫此方法。
類:Hmac#
Hmac 類是用於建立加密 HMAC 摘要的實用工具。它可以透過以下兩種方式之一使用:
- 作為一個可讀可寫的 流,將資料寫入以在可讀端產生計算出的 HMAC 摘要,或者
- 使用
hmac.update()和hmac.digest()方法來生成計算出的 HMAC 摘要。
crypto.createHmac() 方法用於建立 Hmac 例項。不應直接使用 new 關鍵字建立 Hmac 物件。
示例:將 Hmac 物件用作流
const {
createHmac,
} = await import('node:crypto');
const hmac = createHmac('sha256', 'a secret');
hmac.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = hmac.read();
if (data) {
console.log(data.toString('hex'));
// Prints:
// 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e
}
});
hmac.write('some data to hash');
hmac.end();const {
createHmac,
} = require('node:crypto');
const hmac = createHmac('sha256', 'a secret');
hmac.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = hmac.read();
if (data) {
console.log(data.toString('hex'));
// Prints:
// 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e
}
});
hmac.write('some data to hash');
hmac.end();
示例:使用 Hmac 和管道流
import { createReadStream } from 'node:fs';
import { stdout } from 'node:process';
const {
createHmac,
} = await import('node:crypto');
const hmac = createHmac('sha256', 'a secret');
const input = createReadStream('test.js');
input.pipe(hmac).pipe(stdout);const {
createReadStream,
} = require('node:fs');
const {
createHmac,
} = require('node:crypto');
const { stdout } = require('node:process');
const hmac = createHmac('sha256', 'a secret');
const input = createReadStream('test.js');
input.pipe(hmac).pipe(stdout);
示例:使用 hmac.update() 和 hmac.digest() 方法
const {
createHmac,
} = await import('node:crypto');
const hmac = createHmac('sha256', 'a secret');
hmac.update('some data to hash');
console.log(hmac.digest('hex'));
// Prints:
// 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77econst {
createHmac,
} = require('node:crypto');
const hmac = createHmac('sha256', 'a secret');
hmac.update('some data to hash');
console.log(hmac.digest('hex'));
// Prints:
// 7fd04df92f636fd450bc841c9418e5825c17f33ad9c87c518115a45971f7f77e
hmac.digest([encoding])#
計算使用 hmac.update() 傳入的所有資料的 HMAC 摘要。如果提供了 encoding,則返回一個字串;否則返回一個 Buffer。
在 hmac.digest() 被呼叫後,Hmac 物件不能再次使用。多次呼叫 hmac.digest() 將導致丟擲錯誤。
hmac.update(data[, inputEncoding])#
data<string> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string>data字串的編碼。
用給定的 data 更新 Hmac 內容,其編碼在 inputEncoding 中給出。如果未提供 encoding,且 data 是一個字串,則強制使用 'utf8' 編碼。如果 data 是一個 Buffer、TypedArray 或 DataView,則忽略 inputEncoding。
當新資料以流式傳輸時,可以多次呼叫此方法。
類:KeyObject#
Node.js 使用 KeyObject 類來表示對稱或非對稱金鑰,每種金鑰都公開不同的函式。crypto.createSecretKey()、crypto.createPublicKey() 和 crypto.createPrivateKey() 方法用於建立 KeyObject 例項。不應直接使用 new 關鍵字建立 KeyObject 物件。
由於具有改進的安全特性,大多數應用程式應考慮使用新的 KeyObject API,而不是將金鑰作為字串或 Buffer 傳遞。
KeyObject 例項可以透過 postMessage() 傳遞給其他執行緒。接收方會獲得一個克隆的 KeyObject,且該 KeyObject 不需要列在 transferList 引數中。
靜態方法:KeyObject.from(key)#
key<CryptoKey>- 返回:<KeyObject>
示例:將 CryptoKey 例項轉換為 KeyObject
const { KeyObject } = await import('node:crypto');
const { subtle } = globalThis.crypto;
const key = await subtle.generateKey({
name: 'HMAC',
hash: 'SHA-256',
length: 256,
}, true, ['sign', 'verify']);
const keyObject = KeyObject.from(key);
console.log(keyObject.symmetricKeySize);
// Prints: 32 (symmetric key size in bytes)const { KeyObject } = require('node:crypto');
const { subtle } = globalThis.crypto;
(async function() {
const key = await subtle.generateKey({
name: 'HMAC',
hash: 'SHA-256',
length: 256,
}, true, ['sign', 'verify']);
const keyObject = KeyObject.from(key);
console.log(keyObject.symmetricKeySize);
// Prints: 32 (symmetric key size in bytes)
})();
keyObject.asymmetricKeyDetails#
- 型別:<Object>
此屬性僅存在於非對稱金鑰上。根據金鑰的型別,此物件包含有關金鑰的資訊。透過此屬性獲得的任何資訊都不能用於唯一標識金鑰或危及金鑰的安全性。
對於 RSA-PSS 金鑰,如果金鑰材料包含 RSASSA-PSS-params 序列,則將設定 hashAlgorithm、mgf1HashAlgorithm 和 saltLength 屬性。
其他金鑰詳細資訊可能會透過此 API 使用其他屬性公開。
keyObject.asymmetricKeyType#
- 型別:<string>
對於非對稱金鑰,此屬性表示金鑰的型別。請參見支援的非對稱金鑰型別。
對於無法識別的 KeyObject 型別和對稱金鑰,此屬性為 undefined。
keyObject.equals(otherKeyObject)#
otherKeyObject<KeyObject> 一個與keyObject進行比較的KeyObject。- 返回:<boolean>
根據金鑰是否具有完全相同的型別、值和引數,返回 true 或 false。此方法不是時間恆定的。
keyObject.export([options])#
對於對稱金鑰,可以使用以下編碼選項:
format<string> 必須是'buffer'(預設) 或'jwk'。
對於公鑰,可以使用以下編碼選項:
對於私鑰,可以使用以下編碼選項:
type<string> 必須是'pkcs1'(僅限 RSA)、'pkcs8'或'sec1'(僅限 EC) 之一。format<string> 必須是'pem'、'der'或'jwk'。cipher<string> 如果指定,私鑰將使用給定的cipher和passphrase透過 PKCS#5 v2.0 基於密碼的加密進行加密。passphrase<string> | <Buffer> 用於加密的密碼短語,參見cipher。
結果型別取決於所選的編碼格式,當為 PEM 時,結果為字串;當為 DER 時,它將是一個包含 DER 編碼資料的緩衝區;當為 JWK 時,它將是一個物件。
當選擇 JWK 編碼格式時,所有其他編碼選項都將被忽略。
PKCS#1、SEC1 和 PKCS#8 型別的金鑰可以透過結合使用 cipher 和 format 選項來加密。PKCS#8 type 可以與任何 format 一起使用,透過指定 cipher 來加密任何金鑰演算法(RSA、EC 或 DH)。PKCS#1 和 SEC1 只能在指定 cipher 且使用 PEM format 時進行加密。為了獲得最大的相容性,請使用 PKCS#8 來處理加密的私鑰。由於 PKCS#8 定義了自己的加密機制,因此在加密 PKCS#8 金鑰時不支援 PEM 級別的加密。有關 PKCS#8 加密,請參見 RFC 5208;有關 PKCS#1 和 SEC1 加密,請參見 RFC 1421。
keyObject.toCryptoKey(algorithm, extractable, keyUsages)#
algorithm<string> | <Algorithm> | <RsaHashedImportParams> | <EcKeyImportParams> | <HmacImportParams>
extractable<boolean>keyUsages<string[]> 參見 金鑰用途。- 返回:<CryptoKey>
將 KeyObject 例項轉換為 CryptoKey。
類:Sign#
Sign 類是用於生成簽名的實用工具。它可以透過以下兩種方式之一使用:
- 作為一個可寫的 流,將要簽名的資料寫入,並使用
sign.sign()方法來生成和返回簽名,或者 - 使用
sign.update()和sign.sign()方法來生成簽名。
crypto.createSign() 方法用於建立 Sign 例項。引數是所用雜湊函式的字串名稱。不應直接使用 new 關鍵字建立 Sign 物件。
示例:將 Sign 和 Verify 物件用作流
const {
generateKeyPairSync,
createSign,
createVerify,
} = await import('node:crypto');
const { privateKey, publicKey } = generateKeyPairSync('ec', {
namedCurve: 'sect239k1',
});
const sign = createSign('SHA256');
sign.write('some data to sign');
sign.end();
const signature = sign.sign(privateKey, 'hex');
const verify = createVerify('SHA256');
verify.write('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature, 'hex'));
// Prints: trueconst {
generateKeyPairSync,
createSign,
createVerify,
} = require('node:crypto');
const { privateKey, publicKey } = generateKeyPairSync('ec', {
namedCurve: 'sect239k1',
});
const sign = createSign('SHA256');
sign.write('some data to sign');
sign.end();
const signature = sign.sign(privateKey, 'hex');
const verify = createVerify('SHA256');
verify.write('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature, 'hex'));
// Prints: true
示例:使用 sign.update() 和 verify.update() 方法
const {
generateKeyPairSync,
createSign,
createVerify,
} = await import('node:crypto');
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
});
const sign = createSign('SHA256');
sign.update('some data to sign');
sign.end();
const signature = sign.sign(privateKey);
const verify = createVerify('SHA256');
verify.update('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature));
// Prints: trueconst {
generateKeyPairSync,
createSign,
createVerify,
} = require('node:crypto');
const { privateKey, publicKey } = generateKeyPairSync('rsa', {
modulusLength: 2048,
});
const sign = createSign('SHA256');
sign.update('some data to sign');
sign.end();
const signature = sign.sign(privateKey);
const verify = createVerify('SHA256');
verify.update('some data to sign');
verify.end();
console.log(verify.verify(publicKey, signature));
// Prints: true
sign.sign(privateKey[, outputEncoding])#
privateKey<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>outputEncoding<string> 返回值的編碼。- 返回:<Buffer> | <string>
計算透過 sign.update() 或 sign.write() 傳入的所有資料的簽名。
如果 privateKey 不是一個 KeyObject,此函式的行為就好像 privateKey 已被傳遞給 crypto.createPrivateKey()。如果它是一個物件,可以傳遞以下附加屬性:
-
dsaEncoding<string> 對於 DSA 和 ECDSA,此選項指定生成簽名的格式。它可以是以下之一:'der'(預設): DER 編碼的 ASN.1 簽名結構,編碼為(r, s)。'ieee-p1363':IEEE-P1363 中提議的簽名格式r || s。
-
padding<integer> RSA 的可選填充值,為以下之一:crypto.constants.RSA_PKCS1_PADDING(預設)crypto.constants.RSA_PKCS1_PSS_PADDING
RSA_PKCS1_PSS_PADDING將使用 MGF1,其雜湊函式與用於簽署訊息的雜湊函式相同,如 RFC 4055 第 3.1 節所述,除非已根據 RFC 4055 第 3.3 節的規定,在金鑰中指定了 MGF1 雜湊函式。 -
saltLength<integer> 當填充為RSA_PKCS1_PSS_PADDING時的鹽長度。特殊值crypto.constants.RSA_PSS_SALTLEN_DIGEST將鹽長度設定為摘要大小,crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN(預設) 將其設定為最大允許值。
如果提供了 outputEncoding,則返回一個字串;否則返回一個 Buffer。
在 sign.sign() 方法被呼叫後,Sign 物件不能再次使用。多次呼叫 sign.sign() 將導致丟擲錯誤。
sign.update(data[, inputEncoding])#
data<string> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string>data字串的編碼。
用給定的 data 更新 Sign 內容,其編碼在 inputEncoding 中給出。如果未提供 encoding,且 data 是一個字串,則強制使用 'utf8' 編碼。如果 data 是一個 Buffer、TypedArray 或 DataView,則忽略 inputEncoding。
當新資料以流式傳輸時,可以多次呼叫此方法。
類:Verify#
Verify 類是用於驗證簽名的實用工具。它可以透過以下兩種方式之一使用:
- 作為一個可寫的 流,其中寫入的資料用於與提供的簽名進行驗證,或者
- 使用
verify.update()和verify.verify()方法來驗證簽名。
crypto.createVerify() 方法用於建立 Verify 例項。不應直接使用 new 關鍵字建立 Verify 物件。
有關示例,請參見 Sign。
verify.update(data[, inputEncoding])#
data<string> | <Buffer> | <TypedArray> | <DataView>inputEncoding<string>data字串的編碼。
用給定的 data 更新 Verify 內容,其編碼在 inputEncoding 中給出。如果未提供 inputEncoding,且 data 是一個字串,則強制使用 'utf8' 編碼。如果 data 是一個 Buffer、TypedArray 或 DataView,則忽略 inputEncoding。
當新資料以流式傳輸時,可以多次呼叫此方法。
verify.verify(object, signature[, signatureEncoding])#
object<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>signature<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>signatureEncoding<string>signature字串的編碼。- 返回:<boolean> 根據資料和公鑰的簽名有效性返回
true或false。
使用給定的 object 和 signature 驗證所提供的資料。
如果 object 不是一個 KeyObject,此函式的行為就好像 object 已被傳遞給 crypto.createPublicKey()。如果它是一個物件,可以傳遞以下附加屬性:
-
dsaEncoding<string> 對於 DSA 和 ECDSA,此選項指定簽名的格式。它可以是以下之一:'der'(預設): DER 編碼的 ASN.1 簽名結構,編碼為(r, s)。'ieee-p1363':IEEE-P1363 中提議的簽名格式r || s。
-
padding<integer> RSA 的可選填充值,為以下之一:crypto.constants.RSA_PKCS1_PADDING(預設)crypto.constants.RSA_PKCS1_PSS_PADDING
RSA_PKCS1_PSS_PADDING將使用 MGF1,其雜湊函式與用於驗證訊息的雜湊函式相同,如 RFC 4055 第 3.1 節所述,除非已根據 RFC 4055 第 3.3 節的規定,在金鑰中指定了 MGF1 雜湊函式。 -
saltLength<integer> 當填充為RSA_PKCS1_PSS_PADDING時的鹽長度。特殊值crypto.constants.RSA_PSS_SALTLEN_DIGEST將鹽長度設定為摘要大小,crypto.constants.RSA_PSS_SALTLEN_AUTO(預設) 使其自動確定。
signature 引數是先前為資料計算的簽名,其編碼為 signatureEncoding。如果指定了 signatureEncoding,則 signature 應為一個字串;否則 signature 應為一個 Buffer、TypedArray 或 DataView。
在 verify.verify() 被呼叫後,verify 物件不能再次使用。多次呼叫 verify.verify() 將導致丟擲錯誤。
因為公鑰可以從私鑰派生,所以可以傳遞私鑰來代替公鑰。
類:X509Certificate#
封裝 X509 證書並提供對其資訊的只讀訪問。
const { X509Certificate } = await import('node:crypto');
const x509 = new X509Certificate('{... pem encoded cert ...}');
console.log(x509.subject);const { X509Certificate } = require('node:crypto');
const x509 = new X509Certificate('{... pem encoded cert ...}');
console.log(x509.subject);
new X509Certificate(buffer)#
buffer<string> | <TypedArray> | <Buffer> | <DataView> PEM 或 DER 編碼的 X509 證書。
x509.checkEmail(email[, options])#
email<string>options<Object>subject<string>'default'、'always'或'never'。預設值:'default'。
- 返回:<string> | <undefined> 如果證書匹配,則返回
email,否則返回undefined。
檢查證書是否與給定的電子郵件地址匹配。
如果 'subject' 選項未定義或設定為 'default',則僅當主題備用名稱擴充套件不存在或不包含任何電子郵件地址時,才會考慮證書主題。
如果 'subject' 選項設定為 'always',並且主題備用名稱擴充套件不存在或不包含匹配的電子郵件地址,則會考慮證書主題。
如果 'subject' 選項設定為 'never',則永遠不會考慮證書主題,即使證書不包含主題備用名稱。
x509.checkHost(name[, options])#
name<string>options<Object>- 返回:<string> | <undefined> 返回與
name匹配的主題名稱,如果沒有主題名稱匹配name,則返回undefined。
檢查證書是否與給定的主機名匹配。
如果證書與給定的主機名匹配,則返回匹配的主題名稱。返回的名稱可能是精確匹配(例如 foo.example.com),也可能包含萬用字元(例如 *.example.com)。因為主機名比較不區分大小寫,所以返回的主題名稱的大小寫也可能與給定的 name 不同。
如果 'subject' 選項未定義或設定為 'default',則僅當主題備用名稱擴充套件不存在或不包含任何 DNS 名稱時,才會考慮證書主題。此行為與 RFC 2818(“HTTP Over TLS”)一致。
如果 'subject' 選項設定為 'always',並且主題備用名稱擴充套件不存在或不包含匹配的 DNS 名稱,則會考慮證書主題。
如果 'subject' 選項設定為 'never',則永遠不會考慮證書主題,即使證書不包含主題備用名稱。
x509.checkIP(ip)#
ip<string>- 返回:<string> | <undefined> 如果證書匹配,則返回
ip,否則返回undefined。
檢查證書是否與給定的 IP 地址(IPv4 或 IPv6)匹配。
僅考慮 RFC 5280 iPAddress 主題備用名稱,並且它們必須與給定的 ip 地址完全匹配。證書的其他主題備用名稱以及主題欄位將被忽略。
x509.checkIssued(otherCert)#
otherCert<X509Certificate>- 返回:<boolean>
透過比較證書元資料,檢查此證書是否可能由給定的 otherCert 頒發。
這對於修剪可能的頒發者證書列表非常有用,這些證書是使用更基本的過濾例程(即僅基於主題和頒發者名稱)選擇的。
最後,要驗證此證書的簽名是由與 otherCert 的公鑰對應的私鑰生成的,請使用 x509.verify(publicKey),其中 otherCert 的公鑰表示為一個 KeyObject,如下所示
if (!x509.verify(otherCert.publicKey)) {
throw new Error('otherCert did not issue x509');
}
x509.fingerprint#
- 型別:<string>
此證書的 SHA-1 指紋。
由於 SHA-1 在密碼學上已被破解,並且 SHA-1 的安全性明顯低於通常用於簽署證書的演算法,因此請考慮改用 x509.fingerprint256。
x509.fingerprint512#
- 型別:<string>
此證書的 SHA-512 指紋。
由於計算 SHA-256 指紋通常更快,並且其大小僅為 SHA-512 指紋的一半,因此 x509.fingerprint256 可能是更好的選擇。雖然 SHA-512 通常被認為提供了更高的安全級別,但 SHA-256 的安全性與大多數常用於簽署證書的演算法相匹配。
x509.infoAccess#
- 型別:<string>
證書的頒發機構資訊訪問擴充套件的文字表示。
這是一個以換行符分隔的訪問描述列表。每行以訪問方法和訪問位置的型別開頭,後跟一個冒號和與訪問位置關聯的值。
在表示訪問方法和訪問位置型別的字首之後,每行剩餘的部分可能會用引號括起來,以表明該值是一個 JSON 字串字面量。為了向後相容,Node.js 僅在為避免歧義而必要時才在此屬性內使用 JSON 字串字面量。第三方程式碼應準備好處理這兩種可能的條目格式。
x509.subjectAltName#
- 型別:<string>
為此證書指定的主題備用名稱。
這是一個以逗號分隔的主題備用名稱列表。每個條目以一個標識主題備用名稱型別的字串開頭,後跟一個冒號和與該條目關聯的值。
早期版本的 Node.js 錯誤地假設在此屬性上按雙字元序列 ', ' 進行分割是安全的(參見 CVE-2021-44532)。然而,無論是惡意證書還是合法證書,在表示為字串時,其主題備用名稱都可能包含此序列。
在表示條目型別的字首之後,每個條目的剩餘部分可能會用引號括起來,以表明該值是一個 JSON 字串字面量。為了向後相容,Node.js 僅在為避免歧義而必要時才在此屬性內使用 JSON 字串字面量。第三方程式碼應準備好處理這兩種可能的條目格式。
node:crypto 模組方法和屬性#
crypto.argon2(algorithm, parameters, callback)#
algorithm<string> Argon2 的變體,為"argon2d"、"argon2i"或"argon2id"之一。parameters<Object>message<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 必需,這是 Argon2 密碼雜湊應用的密碼。nonce<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 必需,必須至少為 8 位元組長。這是 Argon2 密碼雜湊應用的鹽。parallelism<number> 必需,並行度決定了可以執行多少個計算鏈(通道)。必須大於 1 且小於2**24-1。tagLength<number> 必需,要生成的金鑰長度。必須大於 4 且小於2**32-1。memory<number> 必需,以 1KiB 塊為單位的記憶體成本。必須大於8 * parallelism且小於2**32-1。實際塊數會向下取整到最接近4 * parallelism的倍數。passes<number> 必需,傳遞次數(迭代次數)。必須大於 1 且小於2**32-1。secret<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <undefined> 可選,隨機的附加輸入,類似於鹽,不應與派生金鑰一起儲存。這在密碼雜湊應用中被稱為“胡椒”(pepper)。如果使用,長度不得超過2**32-1位元組。associatedData<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <undefined> 可選,要新增到雜湊中的附加資料,功能上等同於鹽或秘密,但用於非隨機資料。如果使用,長度不得超過2**32-1位元組。
callback<Function>
提供一個非同步的 Argon2 實現。Argon2 是一種基於密碼的金鑰派生函式,旨在使計算和記憶體成本高昂,從而使暴力攻擊變得不划算。
nonce 應該儘可能唯一。建議 nonce 是隨機的且至少 16 位元組長。詳情請參閱 NIST SP 800-132。
當為 message、nonce、secret 或 associatedData 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
callback 函式被呼叫時帶有兩個引數:err 和 derivedKey。當金鑰派生失敗時,err 是一個異常物件,否則 err 為 null。derivedKey 作為 Buffer 傳遞給回撥函式。
當任何輸入引數指定了無效的值或型別時,會丟擲異常。
const { argon2, randomBytes } = await import('node:crypto');
const parameters = {
message: 'password',
nonce: randomBytes(16),
parallelism: 4,
tagLength: 64,
memory: 65536,
passes: 3,
};
argon2('argon2id', parameters, (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // 'af91dad...9520f15'
});const { argon2, randomBytes } = require('node:crypto');
const parameters = {
message: 'password',
nonce: randomBytes(16),
parallelism: 4,
tagLength: 64,
memory: 65536,
passes: 3,
};
argon2('argon2id', parameters, (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // 'af91dad...9520f15'
});
crypto.argon2Sync(algorithm, parameters)#
algorithm<string> Argon2 的變體,為"argon2d"、"argon2i"或"argon2id"之一。parameters<Object>message<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 必需,這是 Argon2 密碼雜湊應用的密碼。nonce<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 必需,必須至少為 8 位元組長。這是 Argon2 密碼雜湊應用的鹽。parallelism<number> 必需,並行度決定了可以執行多少個計算鏈(通道)。必須大於 1 且小於2**24-1。tagLength<number> 必需,要生成的金鑰長度。必須大於 4 且小於2**32-1。memory<number> 必需,以 1KiB 塊為單位的記憶體成本。必須大於8 * parallelism且小於2**32-1。實際塊數會向下取整到最接近4 * parallelism的倍數。passes<number> 必需,傳遞次數(迭代次數)。必須大於 1 且小於2**32-1。secret<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <undefined> 可選,隨機的附加輸入,類似於鹽,不應與派生金鑰一起儲存。這在密碼雜湊應用中被稱為“胡椒”(pepper)。如果使用,長度不得超過2**32-1位元組。associatedData<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <undefined> 可選,要新增到雜湊中的附加資料,功能上等同於鹽或秘密,但用於非隨機資料。如果使用,長度不得超過2**32-1位元組。
- 返回:<Buffer>
提供一個同步的 Argon2 實現。Argon2 是一種基於密碼的金鑰派生函式,旨在使計算和記憶體成本高昂,從而使暴力攻擊變得不划算。
nonce 應該儘可能唯一。建議 nonce 是隨機的且至少 16 位元組長。詳情請參閱 NIST SP 800-132。
當為 message、nonce、secret 或 associatedData 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
當金鑰派生失敗時,會丟擲異常,否則派生的金鑰將作為 Buffer 返回。
當任何輸入引數指定了無效的值或型別時,會丟擲異常。
const { argon2Sync, randomBytes } = await import('node:crypto');
const parameters = {
message: 'password',
nonce: randomBytes(16),
parallelism: 4,
tagLength: 64,
memory: 65536,
passes: 3,
};
const derivedKey = argon2Sync('argon2id', parameters);
console.log(derivedKey.toString('hex')); // 'af91dad...9520f15'const { argon2Sync, randomBytes } = require('node:crypto');
const parameters = {
message: 'password',
nonce: randomBytes(16),
parallelism: 4,
tagLength: 64,
memory: 65536,
passes: 3,
};
const derivedKey = argon2Sync('argon2id', parameters);
console.log(derivedKey.toString('hex')); // 'af91dad...9520f15'
crypto.checkPrime(candidate[, options], callback)#
candidate<ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint> 一個可能的素數,編碼為任意長度的大端位元組序列。options<Object>checks<number> 要執行的 Miller-Rabin 機率性素性測試的迭代次數。當值為0(零)時,將使用一定數量的檢查,使得對於隨機輸入,假陽性率最多為 2-64。選擇檢查次數時必須謹慎。有關更多詳細資訊,請參閱 OpenSSL 文件中關於BN_is_prime_ex函式的nchecks選項。預設值:0
callback<Function>
檢查 candidate 的素性。
crypto.checkPrimeSync(candidate[, options])#
candidate<ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint> 一個可能的素數,編碼為任意長度的大端位元組序列。options<Object>checks<number> 要執行的 Miller-Rabin 機率性素性測試的迭代次數。當值為0(零)時,將使用一定數量的檢查,使得對於隨機輸入,假陽性率最多為 2-64。選擇檢查次數時必須謹慎。有關更多詳細資訊,請參閱 OpenSSL 文件中關於BN_is_prime_ex函式的nchecks選項。預設值:0
- 返回:<boolean> 如果候選數是素數且錯誤機率小於
0.25 ** options.checks,則為true。
檢查 candidate 的素性。
crypto.createCipheriv(algorithm, key, iv[, options])#
algorithm<string>key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>iv<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <null>options<Object>stream.transform選項- 返回:<Cipheriv>
建立並返回一個 Cipheriv 物件,使用給定的 algorithm、key 和初始化向量 (iv)。
options 引數控制流行為,並且是可選的,除非使用 CCM 或 OCB 模式的密碼(例如 'aes-128-ccm')。在這種情況下,authTagLength 選項是必需的,並指定身份驗證標籤的長度(以位元組為單位),請參閱 CCM 模式。在 GCM 模式下,authTagLength 選項不是必需的,但可用於設定將由 getAuthTag() 返回的身份驗證標籤的長度,預設為 16 位元組。對於 chacha20-poly1305,authTagLength 選項預設為 16 位元組。
algorithm 取決於 OpenSSL,例如 'aes192' 等。在最新的 OpenSSL 版本中,openssl list -cipher-algorithms 將顯示可用的密碼演算法。
key 是 algorithm 使用的原始金鑰,iv 是初始化向量。兩個引數都必須是 'utf8' 編碼的字串、Buffers、TypedArray 或 DataView。key 也可以是型別為 secret 的 KeyObject。如果密碼不需要初始化向量,iv 可以是 null。
當為 key 或 iv 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
初始化向量應該是不可預測且唯一的;理想情況下,它們應該是加密安全的隨機數。它們不必是機密的:IV 通常只是以未加密的形式新增到密文訊息中。某些事物必須是不可預測且唯一的,但又不必是機密的,這聽起來可能有些矛盾;請記住,攻擊者必須不能提前預測出給定的 IV 將是什麼。
crypto.createDecipheriv(algorithm, key, iv[, options])#
algorithm<string>key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>iv<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <null>options<Object>stream.transform選項- 返回:<Decipheriv>
建立並返回一個使用給定 algorithm、key 和初始化向量 (iv) 的 Decipheriv 物件。
options 引數控制流行為,並且是可選的,除非使用 CCM 或 OCB 模式的密碼(例如 'aes-128-ccm')。在這種情況下,authTagLength 選項是必需的,並指定身份驗證標籤的長度(以位元組為單位),請參閱 CCM 模式。對於 AES-GCM 和 chacha20-poly1305,authTagLength 選項預設為 16 位元組,如果使用不同長度,則必須設定為不同的值。
algorithm 取決於 OpenSSL,例如 'aes192' 等。在最新的 OpenSSL 版本中,openssl list -cipher-algorithms 將顯示可用的密碼演算法。
key 是 algorithm 使用的原始金鑰,iv 是初始化向量。兩個引數都必須是 'utf8' 編碼的字串、Buffers、TypedArray 或 DataView。key 也可以是型別為 secret 的 KeyObject。如果密碼不需要初始化向量,iv 可以是 null。
當為 key 或 iv 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
初始化向量應該是不可預測且唯一的;理想情況下,它們應該是加密安全的隨機數。它們不必是機密的:IV 通常只是以未加密的形式新增到密文訊息中。某些事物必須是不可預測且唯一的,但又不必是機密的,這聽起來可能有些矛盾;請記住,攻擊者必須不能提前預測出給定的 IV 將是什麼。
crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding])#
prime<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>primeEncoding<string>prime字串的編碼。generator<number> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 預設值:2generatorEncoding<string>generator字串的編碼。- 返回:<DiffieHellman>
使用提供的 prime 和一個可選的特定 generator 建立一個 DiffieHellman 金鑰交換物件。
generator 引數可以是一個數字、字串或 Buffer。如果未指定 generator,則使用值 2。
如果指定了 primeEncoding,則 prime 應為字串;否則應為 Buffer、TypedArray 或 DataView。
如果指定了 generatorEncoding,則 generator 應為字串;否則應為數字、Buffer、TypedArray 或 DataView。
crypto.createDiffieHellman(primeLength[, generator])#
primeLength<number>generator<number> 預設值:2- 返回:<DiffieHellman>
建立一個 DiffieHellman 金鑰交換物件,並使用可選的特定數值 generator 生成一個 primeLength 位的素數。如果未指定 generator,則使用值 2。
crypto.createDiffieHellmanGroup(name)#
name<string>- 返回:<DiffieHellmanGroup>
crypto.createECDH(curveName)#
使用由 curveName 字串指定的預定義曲線建立一個橢圓曲線迪菲-赫爾曼 (ECDH) 金鑰交換物件。使用 crypto.getCurves() 獲取可用曲線名稱的列表。在最新的 OpenSSL 版本中,openssl ecparam -list_curves 也會顯示每個可用橢圓曲線的名稱和描述。
crypto.createHash(algorithm[, options])#
algorithm<string>options<Object>stream.transform選項- 返回:<Hash>
建立並返回一個 Hash 物件,該物件可用於使用給定的 algorithm 生成雜湊摘要。可選的 options 引數控制流行為。對於 XOF 雜湊函式(如 'shake256'),可以使用 outputLength 選項來指定所需的輸出長度(以位元組為單位)。
algorithm 取決於平臺上 OpenSSL 版本支援的可用演算法。例如 'sha256'、'sha512' 等。在最新的 OpenSSL 版本中,openssl list -digest-algorithms 將顯示可用的摘要演算法。
示例:生成檔案的 sha256 校驗和
import {
createReadStream,
} from 'node:fs';
import { argv } from 'node:process';
const {
createHash,
} = await import('node:crypto');
const filename = argv[2];
const hash = createHash('sha256');
const input = createReadStream(filename);
input.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = input.read();
if (data)
hash.update(data);
else {
console.log(`${hash.digest('hex')} ${filename}`);
}
});const {
createReadStream,
} = require('node:fs');
const {
createHash,
} = require('node:crypto');
const { argv } = require('node:process');
const filename = argv[2];
const hash = createHash('sha256');
const input = createReadStream(filename);
input.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = input.read();
if (data)
hash.update(data);
else {
console.log(`${hash.digest('hex')} ${filename}`);
}
});
crypto.createHmac(algorithm, key[, options])#
algorithm<string>key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>options<Object>stream.transform選項encoding<string> 當key是字串時使用的字串編碼。
- 返回:<Hmac>
建立並返回一個使用給定 algorithm 和 key 的 Hmac 物件。可選的 options 引數控制流行為。
algorithm 取決於平臺上 OpenSSL 版本支援的可用演算法。例如 'sha256'、'sha512' 等。在最新的 OpenSSL 版本中,openssl list -digest-algorithms 將顯示可用的摘要演算法。
key 是用於生成加密 HMAC 雜湊的 HMAC 金鑰。如果它是一個 KeyObject,其型別必須是 secret。如果它是一個字串,請考慮將字串用作加密 API 輸入時的注意事項。如果它是從加密安全的熵源(如 crypto.randomBytes() 或 crypto.generateKey())獲得的,其長度不應超過 algorithm 的塊大小(例如,對於 SHA-256 為 512 位)。
示例:生成檔案的 sha256 HMAC
import {
createReadStream,
} from 'node:fs';
import { argv } from 'node:process';
const {
createHmac,
} = await import('node:crypto');
const filename = argv[2];
const hmac = createHmac('sha256', 'a secret');
const input = createReadStream(filename);
input.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = input.read();
if (data)
hmac.update(data);
else {
console.log(`${hmac.digest('hex')} ${filename}`);
}
});const {
createReadStream,
} = require('node:fs');
const {
createHmac,
} = require('node:crypto');
const { argv } = require('node:process');
const filename = argv[2];
const hmac = createHmac('sha256', 'a secret');
const input = createReadStream(filename);
input.on('readable', () => {
// Only one element is going to be produced by the
// hash stream.
const data = input.read();
if (data)
hmac.update(data);
else {
console.log(`${hmac.digest('hex')} ${filename}`);
}
});
crypto.createPrivateKey(key)#
key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <Object> 金鑰材料,格式為 PEM、DER 或 JWK。format<string> 必須是'pem'、'der'或 ''jwk'。預設值:'pem'。type<string> 必須是'pkcs1'、'pkcs8'或'sec1'。此選項僅在format為'der'時是必需的,否則將被忽略。passphrase<string> | <Buffer> 用於解密的密碼短語。encoding<string> 當key是字串時使用的字串編碼。
- 返回:<KeyObject>
建立並返回一個包含私鑰的新金鑰物件。如果 key 是字串或 Buffer,則假定 format 為 'pem';否則,key 必須是具有上述屬性的物件。
如果私鑰已加密,則必須指定 passphrase。密碼短語的長度限制為 1024 位元組。
crypto.createPublicKey(key)#
key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <Object> 金鑰材料,格式為 PEM、DER 或 JWK。format<string> 必須是'pem'、'der'或'jwk'。預設值:'pem'。type<string> 必須是'pkcs1'或'spki'。此選項僅在format為'der'時是必需的,否則將被忽略。encoding<string> 當key是字串時使用的字串編碼。
- 返回:<KeyObject>
建立並返回一個包含公鑰的新金鑰物件。如果 key 是字串或 Buffer,則假定 format 為 'pem';如果 key 是一個型別為 'private' 的 KeyObject,則公鑰從給定的私鑰派生;否則,key 必須是具有上述屬性的物件。
如果格式是 'pem','key' 也可以是 X.509 證書。
因為公鑰可以從私鑰派生,所以可以傳遞私鑰來代替公鑰。在這種情況下,此函式的行為就好像呼叫了 crypto.createPrivateKey() 一樣,只是返回的 KeyObject 的型別將是 'public',並且無法從返回的 KeyObject 中提取私鑰。類似地,如果給定一個型別為 'private' 的 KeyObject,將返回一個型別為 'public' 的新 KeyObject,並且無法從返回的物件中提取私鑰。
crypto.createSecretKey(key[, encoding])#
key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>encoding<string> 當key是字串時的字串編碼。- 返回:<KeyObject>
建立並返回一個包含用於對稱加密或 Hmac 的金鑰的新金鑰物件。
crypto.createSign(algorithm[, options])#
algorithm<string>options<Object>stream.Writable選項- 返回:<Sign>
建立並返回一個使用給定 algorithm 的 Sign 物件。使用 crypto.getHashes() 獲取可用摘要演算法的名稱。可選的 options 引數控制 stream.Writable 行為。
在某些情況下,可以使用簽名演算法的名稱(如 'RSA-SHA256')來建立 Sign 例項,而不是摘要演算法的名稱。這將使用相應的摘要演算法。但這不適用於所有簽名演算法,例如 'ecdsa-with-SHA256',所以最好總是使用摘要演算法的名稱。
crypto.createVerify(algorithm[, options])#
algorithm<string>options<Object>stream.Writable選項- 返回:<Verify>
建立並返回一個使用給定演算法的 Verify 物件。使用 crypto.getHashes() 獲取可用簽名演算法名稱的陣列。可選的 options 引數控制 stream.Writable 行為。
在某些情況下,可以使用簽名演算法的名稱(如 'RSA-SHA256')來建立 Verify 例項,而不是摘要演算法的名稱。這將使用相應的摘要演算法。但這不適用於所有簽名演算法,例如 'ecdsa-with-SHA256',所以最好總是使用摘要演算法的名稱。
crypto.decapsulate(key, ciphertext[, callback])#
key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> 私鑰ciphertext<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>callback<Function>- 返回:如果未提供
callback函式,則返回 <Buffer>。
使用 KEM 演算法和私鑰進行金鑰解封裝。
支援的金鑰型別及其 KEM 演算法如下
'rsa'2 RSA 秘密值封裝'ec'3 DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256)'x25519'3 DHKEM(X25519, HKDF-SHA256)'x448'3 DHKEM(X448, HKDF-SHA512)'ml-kem-512'1 ML-KEM'ml-kem-768'1 ML-KEM'ml-kem-1024'1 ML-KEM
如果 key 不是 KeyObject,此函式的行為就好像將 key 傳遞給了 crypto.createPrivateKey() 一樣。
如果提供了 callback 函式,此函式將使用 libuv 的執行緒池。
crypto.diffieHellman(options[, callback])#
options<Object>privateKey<KeyObject>publicKey<KeyObject>
callback<Function>- 返回:如果未提供
callback函式,則返回 <Buffer>。
根據 privateKey 和 publicKey 計算 Diffie-Hellman 共享金鑰。兩個金鑰必須具有相同的 asymmetricKeyType,並且必須支援 DH 或 ECDH 操作。
如果提供了 callback 函式,此函式將使用 libuv 的執行緒池。
crypto.encapsulate(key[, callback])#
key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> 公鑰callback<Function>- 返回:如果未提供
callback函式,則返回 <Object>。
使用 KEM 演算法和公鑰進行金鑰封裝。
支援的金鑰型別及其 KEM 演算法如下
'rsa'2 RSA 秘密值封裝'ec'3 DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256)'x25519'3 DHKEM(X25519, HKDF-SHA256)'x448'3 DHKEM(X448, HKDF-SHA512)'ml-kem-512'1 ML-KEM'ml-kem-768'1 ML-KEM'ml-kem-1024'1 ML-KEM
如果 key 不是 KeyObject,此函式的行為就好像將 key 傳遞給了 crypto.createPublicKey() 一樣。
如果提供了 callback 函式,此函式將使用 libuv 的執行緒池。
crypto.fips#
用於檢查和控制當前是否正在使用符合 FIPS 的加密提供程式的屬性。設定為 true 需要 Node.js 的 FIPS 構建版本。
此屬性已棄用。請改用 crypto.setFips() 和 crypto.getFips()。
crypto.generateKey(type, options, callback)#
type<string> 生成的金鑰的預期用途。當前接受的值是'hmac'和'aes'。options<Object>length<number> 要生成的金鑰的位長度。此值必須大於 0。- 如果
type是'hmac',最小值為 8,最大長度為 231-1。如果該值不是 8 的倍數,生成的金鑰將被截斷為Math.floor(length / 8)。 - 如果
type是'aes',長度必須是128、192或256之一。
- 如果
callback<Function>err<Error>key<KeyObject>
非同步生成一個給定 length 的新隨機金鑰。type 將決定對 length 執行哪些驗證。
const {
generateKey,
} = await import('node:crypto');
generateKey('hmac', { length: 512 }, (err, key) => {
if (err) throw err;
console.log(key.export().toString('hex')); // 46e..........620
});const {
generateKey,
} = require('node:crypto');
generateKey('hmac', { length: 512 }, (err, key) => {
if (err) throw err;
console.log(key.export().toString('hex')); // 46e..........620
});
生成的 HMAC 金鑰的大小不應超過底層雜湊函式的塊大小。有關更多資訊,請參閱 crypto.createHmac()。
crypto.generateKeyPair(type, options, callback)#
type<string> 要生成的非對稱金鑰型別。請參閱支援的非對稱金鑰型別。options<Object>modulusLength<number> 金鑰大小(以位為單位)(RSA, DSA)。publicExponent<number> 公共指數 (RSA)。預設值:0x10001。hashAlgorithm<string> 訊息摘要的名稱(RSA-PSS)。mgf1HashAlgorithm<string> MGF1 使用的訊息摘要的名稱(RSA-PSS)。saltLength<number> 最小鹽長度(以位元組為單位)(RSA-PSS)。divisorLength<number>q的大小(以位為單位)(DSA)。namedCurve<string> 要使用的曲線名稱 (EC)。prime<Buffer> 素數引數 (DH)。primeLength<number> 素數長度(以位為單位)(DH)。generator<number> 自定義生成元 (DH)。預設值:2。groupName<string> Diffie-Hellman 組名 (DH)。請參閱crypto.getDiffieHellman()。paramEncoding<string> 必須是'named'或'explicit'(EC)。預設值:'named'。publicKeyEncoding<Object> 請參閱keyObject.export()。privateKeyEncoding<Object> 請參閱keyObject.export()。
callback<Function>err<Error>publicKey<string> | <Buffer> | <KeyObject>privateKey<string> | <Buffer> | <KeyObject>
生成給定 type 的新非對稱金鑰對。目前支援 RSA、RSA-PSS、DSA、EC、Ed25519、Ed448、X25519、X448 和 DH。
如果指定了 publicKeyEncoding 或 privateKeyEncoding,此函式的行為就好像在其結果上呼叫了 keyObject.export()。否則,金鑰的相應部分將作為 KeyObject 返回。
建議將公鑰編碼為 'spki',將私鑰編碼為 'pkcs8' 並進行加密以供長期儲存。
const {
generateKeyPair,
} = await import('node:crypto');
generateKeyPair('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret',
},
}, (err, publicKey, privateKey) => {
// Handle errors and use the generated key pair.
});const {
generateKeyPair,
} = require('node:crypto');
generateKeyPair('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret',
},
}, (err, publicKey, privateKey) => {
// Handle errors and use the generated key pair.
});
完成後,將呼叫 callback,其中 err 設定為 undefined,publicKey / privateKey 表示生成的金鑰對。
如果此方法作為其 util.promisify() 版本被呼叫,它將返回一個 Promise,該 Promise 解析為一個具有 publicKey 和 privateKey 屬性的物件。
crypto.generateKeyPairSync(type, options)#
type<string> 要生成的非對稱金鑰型別。請參閱支援的非對稱金鑰型別。options<Object>modulusLength<number> 金鑰大小(以位為單位)(RSA, DSA)。publicExponent<number> 公共指數 (RSA)。預設值:0x10001。hashAlgorithm<string> 訊息摘要的名稱(RSA-PSS)。mgf1HashAlgorithm<string> MGF1 使用的訊息摘要的名稱(RSA-PSS)。saltLength<number> 最小鹽長度(以位元組為單位)(RSA-PSS)。divisorLength<number>q的大小(以位為單位)(DSA)。namedCurve<string> 要使用的曲線名稱 (EC)。prime<Buffer> 素數引數 (DH)。primeLength<number> 素數長度(以位為單位)(DH)。generator<number> 自定義生成元 (DH)。預設值:2。groupName<string> Diffie-Hellman 組名 (DH)。請參閱crypto.getDiffieHellman()。paramEncoding<string> 必須是'named'或'explicit'(EC)。預設值:'named'。publicKeyEncoding<Object> 請參閱keyObject.export()。privateKeyEncoding<Object> 請參閱keyObject.export()。
- 返回:<Object>
publicKey<string> | <Buffer> | <KeyObject>privateKey<string> | <Buffer> | <KeyObject>
生成給定 type 的新非對稱金鑰對。目前支援 RSA、RSA-PSS、DSA、EC、Ed25519、Ed448、X25519、X448、DH 和 ML-DSA1。
如果指定了 publicKeyEncoding 或 privateKeyEncoding,此函式的行為就好像在其結果上呼叫了 keyObject.export()。否則,金鑰的相應部分將作為 KeyObject 返回。
編碼公鑰時,建議使用 'spki'。編碼私鑰時,建議使用 'pkcs8' 和強密碼,並對密碼保密。
const {
generateKeyPairSync,
} = await import('node:crypto');
const {
publicKey,
privateKey,
} = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret',
},
});const {
generateKeyPairSync,
} = require('node:crypto');
const {
publicKey,
privateKey,
} = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'top secret',
},
});
返回值 { publicKey, privateKey } 表示生成的金鑰對。當選擇 PEM 編碼時,相應的金鑰將是一個字串,否則它將是一個包含 DER 編碼資料的緩衝區。
crypto.generateKeySync(type, options)#
type<string> 生成的金鑰的預期用途。當前接受的值是'hmac'和'aes'。options<Object>length<number> 要生成的金鑰的位長度。- 如果
type是'hmac',最小值為 8,最大長度為 231-1。如果該值不是 8 的倍數,生成的金鑰將被截斷為Math.floor(length / 8)。 - 如果
type是'aes',長度必須是128、192或256之一。
- 如果
- 返回:<KeyObject>
同步生成一個給定 length 的新隨機金鑰。type 將決定對 length 執行哪些驗證。
const {
generateKeySync,
} = await import('node:crypto');
const key = generateKeySync('hmac', { length: 512 });
console.log(key.export().toString('hex')); // e89..........41econst {
generateKeySync,
} = require('node:crypto');
const key = generateKeySync('hmac', { length: 512 });
console.log(key.export().toString('hex')); // e89..........41e
生成的 HMAC 金鑰的大小不應超過底層雜湊函式的塊大小。有關更多資訊,請參閱 crypto.createHmac()。
crypto.generatePrime(size[, options], callback)#
size<number> 要生成的素數的大小(以位為單位)。options<Object>add<ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint>rem<ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint>safe<boolean> 預設值:false。bigint<boolean> 當為true時,生成的素數將作為bigint返回。
callback<Function>err<Error>prime<ArrayBuffer> | <bigint>
生成一個 size 位的偽隨機素數。
如果 options.safe 為 true,則該素數將是一個安全素數——也就是說,(prime - 1) / 2 也將是一個素數。
options.add 和 options.rem 引數可用於強制執行附加要求,例如用於 Diffie-Hellman
- 如果
options.add和options.rem都被設定,素數將滿足條件prime % add = rem。 - 如果僅設定了
options.add且options.safe不為true,則素數將滿足條件prime % add = 1。 - 如果僅設定了
options.add且options.safe設定為true,則素數將改為滿足條件prime % add = 3。這是必要的,因為對於options.add > 2,prime % add = 1會與options.safe強制執行的條件相矛盾。 - 如果未給出
options.add,則忽略options.rem。
如果 options.add 和 options.rem 以 ArrayBuffer、SharedArrayBuffer、TypedArray、Buffer 或 DataView 的形式給出,則它們必須編碼為大端序列。
預設情況下,素數被編碼為 <ArrayBuffer> 中的大端八位位元組序列。如果 bigint 選項為 true,則提供一個 <bigint>。
素數的 size 會直接影響生成素數所需的時間。size 越大,所需時間越長。因為我們使用 OpenSSL 的 BN_generate_prime_ex 函式,該函式對我們中斷生成過程的能力控制很小,所以不建議生成過大的素數,因為這樣做可能會使程序無響應。
crypto.generatePrimeSync(size[, options])#
size<number> 要生成的素數的大小(以位為單位)。options<Object>add<ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint>rem<ArrayBuffer> | <SharedArrayBuffer> | <TypedArray> | <Buffer> | <DataView> | <bigint>safe<boolean> 預設值:false。bigint<boolean> 當為true時,生成的素數將作為bigint返回。
- 返回:<ArrayBuffer> | <bigint>
生成一個 size 位的偽隨機素數。
如果 options.safe 為 true,則該素數將是一個安全素數——也就是說,(prime - 1) / 2 也將是一個素數。
options.add 和 options.rem 引數可用於強制執行附加要求,例如用於 Diffie-Hellman
- 如果
options.add和options.rem都被設定,素數將滿足條件prime % add = rem。 - 如果僅設定了
options.add且options.safe不為true,則素數將滿足條件prime % add = 1。 - 如果僅設定了
options.add且options.safe設定為true,則素數將改為滿足條件prime % add = 3。這是必要的,因為對於options.add > 2,prime % add = 1會與options.safe強制執行的條件相矛盾。 - 如果未給出
options.add,則忽略options.rem。
如果 options.add 和 options.rem 以 ArrayBuffer、SharedArrayBuffer、TypedArray、Buffer 或 DataView 的形式給出,則它們必須編碼為大端序列。
預設情況下,素數被編碼為 <ArrayBuffer> 中的大端八位位元組序列。如果 bigint 選項為 true,則提供一個 <bigint>。
素數的 size 會直接影響生成素數所需的時間。size 越大,所需時間越長。因為我們使用 OpenSSL 的 BN_generate_prime_ex 函式,該函式對我們中斷生成過程的能力控制很小,所以不建議生成過大的素數,因為這樣做可能會使程序無響應。
crypto.getCipherInfo(nameOrNid[, options])#
nameOrNid<string> | <number> 要查詢的密碼的名稱或 nid。options<Object>- 返回:<Object>
name<string> 密碼的名稱nid<number> 密碼的 nidblockSize<number> 密碼的塊大小(以位元組為單位)。當mode為'stream'時,此屬性被省略。ivLength<number> 預期的或預設的初始化向量長度(以位元組為單位)。如果密碼不使用初始化向量,則省略此屬性。keyLength<number> 預期的或預設的金鑰長度(以位元組為單位)。mode<string> 密碼模式。為'cbc'、'ccm'、'cfb'、'ctr'、'ecb'、'gcm'、'ocb'、'ofb'、'stream'、'wrap'、'xts'之一。
返回有關給定密碼的資訊。
一些密碼接受可變長度的金鑰和初始化向量。預設情況下,crypto.getCipherInfo() 方法將返回這些密碼的預設值。要測試給定的金鑰長度或 IV 長度是否適用於給定的密碼,請使用 keyLength 和 ivLength 選項。如果給定的值不可接受,將返回 undefined。
crypto.getCiphers()#
- 返回:<string[]> 一個包含支援的密碼演算法名稱的陣列。
const {
getCiphers,
} = await import('node:crypto');
console.log(getCiphers()); // ['aes-128-cbc', 'aes-128-ccm', ...]const {
getCiphers,
} = require('node:crypto');
console.log(getCiphers()); // ['aes-128-cbc', 'aes-128-ccm', ...]
crypto.getCurves()#
- 返回:<string[]> 一個包含支援的橢圓曲線名稱的陣列。
const {
getCurves,
} = await import('node:crypto');
console.log(getCurves()); // ['Oakley-EC2N-3', 'Oakley-EC2N-4', ...]const {
getCurves,
} = require('node:crypto');
console.log(getCurves()); // ['Oakley-EC2N-3', 'Oakley-EC2N-4', ...]
crypto.getDiffieHellman(groupName)#
groupName<string>- 返回:<DiffieHellmanGroup>
建立一個預定義的 DiffieHellmanGroup 金鑰交換物件。支援的組在 DiffieHellmanGroup 的文件中列出。
返回的物件模仿由 crypto.createDiffieHellman() 建立的物件的介面,但不允許更改金鑰(例如,使用 diffieHellman.setPublicKey())。使用此方法的優點是各方不必事先生成或交換組模數,從而節省了處理器和通訊時間。
示例(獲取共享金鑰)
const {
getDiffieHellman,
} = await import('node:crypto');
const alice = getDiffieHellman('modp14');
const bob = getDiffieHellman('modp14');
alice.generateKeys();
bob.generateKeys();
const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');
/* aliceSecret and bobSecret should be the same */
console.log(aliceSecret === bobSecret);const {
getDiffieHellman,
} = require('node:crypto');
const alice = getDiffieHellman('modp14');
const bob = getDiffieHellman('modp14');
alice.generateKeys();
bob.generateKeys();
const aliceSecret = alice.computeSecret(bob.getPublicKey(), null, 'hex');
const bobSecret = bob.computeSecret(alice.getPublicKey(), null, 'hex');
/* aliceSecret and bobSecret should be the same */
console.log(aliceSecret === bobSecret);
crypto.getFips()#
crypto.getHashes()#
- 返回:<string[]> 一個包含支援的雜湊演算法名稱的陣列,例如
'RSA-SHA256'。雜湊演算法也稱為“摘要”演算法。
const {
getHashes,
} = await import('node:crypto');
console.log(getHashes()); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...]const {
getHashes,
} = require('node:crypto');
console.log(getHashes()); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...]
crypto.getRandomValues(typedArray)#
typedArray<Buffer> | <TypedArray> | <DataView> | <ArrayBuffer>- 返回:<Buffer> | <TypedArray> | <DataView> | <ArrayBuffer> 返回
typedArray。
crypto.webcrypto.getRandomValues() 的一個方便別名。此實現不符合 Web Crypto 規範,要編寫與 Web 相容的程式碼,請改用 crypto.webcrypto.getRandomValues()。
crypto.hash(algorithm, data[, options])#
algorithm<string> | <undefined>data<string> | <Buffer> | <TypedArray> | <DataView> 當data是字串時,它將在雜湊前被編碼為 UTF-8。如果希望對字串輸入使用不同的輸入編碼,使用者可以使用TextEncoder或Buffer.from()將字串編碼為TypedArray,然後將編碼後的TypedArray傳遞給此 API。options<Object> | <string>- 返回:<string> | <Buffer>
一個用於建立資料的一次性雜湊摘要的實用工具。在對較小量(<= 5MB)且已準備好的資料進行雜湊時,它可能比基於物件的 crypto.createHash() 更快。如果資料可能很大或是流式資料,仍建議使用 crypto.createHash()。
algorithm 取決於平臺上 OpenSSL 版本支援的可用演算法。例如 'sha256'、'sha512' 等。在最新的 OpenSSL 版本中,openssl list -digest-algorithms 將顯示可用的摘要演算法。
如果 options 是一個字串,則它指定了 outputEncoding。
示例
const crypto = require('node:crypto');
const { Buffer } = require('node:buffer');
// Hashing a string and return the result as a hex-encoded string.
const string = 'Node.js';
// 10b3493287f831e81a438811a1ffba01f8cec4b7
console.log(crypto.hash('sha1', string));
// Encode a base64-encoded string into a Buffer, hash it and return
// the result as a buffer.
const base64 = 'Tm9kZS5qcw==';
// <Buffer 10 b3 49 32 87 f8 31 e8 1a 43 88 11 a1 ff ba 01 f8 ce c4 b7>
console.log(crypto.hash('sha1', Buffer.from(base64, 'base64'), 'buffer'));import crypto from 'node:crypto';
import { Buffer } from 'node:buffer';
// Hashing a string and return the result as a hex-encoded string.
const string = 'Node.js';
// 10b3493287f831e81a438811a1ffba01f8cec4b7
console.log(crypto.hash('sha1', string));
// Encode a base64-encoded string into a Buffer, hash it and return
// the result as a buffer.
const base64 = 'Tm9kZS5qcw==';
// <Buffer 10 b3 49 32 87 f8 31 e8 1a 43 88 11 a1 ff ba 01 f8 ce c4 b7>
console.log(crypto.hash('sha1', Buffer.from(base64, 'base64'), 'buffer'));
crypto.hkdf(digest, ikm, salt, info, keylen, callback)#
digest<string> 要使用的摘要演算法。ikm<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> 輸入金鑰材料。必須提供,但可以為零長度。salt<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 鹽值。必須提供,但可以為零長度。info<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 附加資訊值。必須提供,但可以為零長度,並且不能超過 1024 位元組。keylen<number> 要生成的金鑰的長度。必須大於 0。允許的最大值是所選摘要函式產生的位元組數的255倍(例如,sha512生成 64 位元組的雜湊,使得最大 HKDF 輸出為 16320 位元組)。callback<Function>err<Error>derivedKey<ArrayBuffer>
HKDF 是 RFC 5869 中定義的一個簡單的金鑰派生函式。給定的 ikm、salt 和 info 與 digest 一起用於派生一個長度為 keylen 位元組的金鑰。
提供的 callback 函式被呼叫時帶有兩個引數:err 和 derivedKey。如果在派生金鑰時發生錯誤,err 將被設定;否則 err 將為 null。成功生成的 derivedKey 將作為 <ArrayBuffer> 傳遞給回撥函式。如果任何輸入引數指定了無效的值或型別,將丟擲錯誤。
import { Buffer } from 'node:buffer';
const {
hkdf,
} = await import('node:crypto');
hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => {
if (err) throw err;
console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653'
});const {
hkdf,
} = require('node:crypto');
const { Buffer } = require('node:buffer');
hkdf('sha512', 'key', 'salt', 'info', 64, (err, derivedKey) => {
if (err) throw err;
console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653'
});
crypto.hkdfSync(digest, ikm, salt, info, keylen)#
digest<string> 要使用的摘要演算法。ikm<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> 輸入金鑰材料。必須提供,但可以為零長度。salt<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 鹽值。必須提供,但可以為零長度。info<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 附加資訊值。必須提供,但可以為零長度,並且不能超過 1024 位元組。keylen<number> 要生成的金鑰的長度。必須大於 0。允許的最大值是所選摘要函式產生的位元組數的255倍(例如,sha512生成 64 位元組的雜湊,使得最大 HKDF 輸出為 16320 位元組)。- 返回:<ArrayBuffer>
提供一個同步的 HKDF 金鑰派生函式,如 RFC 5869 中定義。給定的 ikm、salt 和 info 與 digest 一起用於派生一個長度為 keylen 位元組的金鑰。
成功生成的 derivedKey 將作為 <ArrayBuffer> 返回。
如果任何輸入引數指定了無效的值或型別,或者無法生成派生金鑰,則將丟擲錯誤。
import { Buffer } from 'node:buffer';
const {
hkdfSync,
} = await import('node:crypto');
const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64);
console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653'const {
hkdfSync,
} = require('node:crypto');
const { Buffer } = require('node:buffer');
const derivedKey = hkdfSync('sha512', 'key', 'salt', 'info', 64);
console.log(Buffer.from(derivedKey).toString('hex')); // '24156e2...5391653'
crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)#
password<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>salt<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>iterations<number>keylen<number>digest<string>callback<Function>
提供一個非同步的基於密碼的金鑰派生函式 2 (PBKDF2) 的實現。它應用由 digest 指定的 HMAC 摘要演算法,從 password、salt 和 iterations 中派生出所需位元組長度 (keylen) 的金鑰。
提供的 callback 函式被呼叫時會帶有兩個引數:err 和 derivedKey。如果在派生金鑰時發生錯誤,err 將被設定;否則 err 將為 null。預設情況下,成功生成的 derivedKey 將作為 Buffer 傳遞給回撥函式。如果任何輸入引數指定了無效的值或型別,則會丟擲錯誤。
iterations 引數必須是一個數字,並且設定得越高越好。迭代次數越多,派生出的金鑰就越安全,但完成所需的時間也越長。
salt 應儘可能唯一。建議 salt 是隨機的,並且長度至少為 16 位元組。詳情請參閱 NIST SP 800-132。
當為 password 或 salt 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
const {
pbkdf2,
} = await import('node:crypto');
pbkdf2('secret', 'salt', 100000, 64, 'sha512', (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // '3745e48...08d59ae'
});const {
pbkdf2,
} = require('node:crypto');
pbkdf2('secret', 'salt', 100000, 64, 'sha512', (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // '3745e48...08d59ae'
});
可以使用 crypto.getHashes() 獲取支援的摘要函式陣列。
此 API 使用 libuv 的執行緒池,這可能對某些應用程式產生意想不到的負面性能影響;更多資訊請參閱 UV_THREADPOOL_SIZE 文件。
crypto.pbkdf2Sync(password, salt, iterations, keylen, digest)#
password<string> | <Buffer> | <TypedArray> | <DataView>salt<string> | <Buffer> | <TypedArray> | <DataView>iterations<number>keylen<number>digest<string>- 返回:<Buffer>
提供一個同步的基於密碼的金鑰派生函式 2 (PBKDF2) 的實現。它應用由 digest 指定的 HMAC 摘要演算法,從 password、salt 和 iterations 中派生出所需位元組長度 (keylen) 的金鑰。
如果發生錯誤,將丟擲 Error,否則派生的金鑰將作為 Buffer 返回。
iterations 引數必須是一個數字,並且設定得越高越好。迭代次數越多,派生出的金鑰就越安全,但完成所需的時間也越長。
salt 應儘可能唯一。建議 salt 是隨機的,並且長度至少為 16 位元組。詳情請參閱 NIST SP 800-132。
當為 password 或 salt 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
const {
pbkdf2Sync,
} = await import('node:crypto');
const key = pbkdf2Sync('secret', 'salt', 100000, 64, 'sha512');
console.log(key.toString('hex')); // '3745e48...08d59ae'const {
pbkdf2Sync,
} = require('node:crypto');
const key = pbkdf2Sync('secret', 'salt', 100000, 64, 'sha512');
console.log(key.toString('hex')); // '3745e48...08d59ae'
可以使用 crypto.getHashes() 獲取支援的摘要函式陣列。
crypto.privateDecrypt(privateKey, buffer)#
privateKey<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>oaepHash<string> 用於 OAEP 填充和 MGF1 的雜湊函式。預設值:'sha1'oaepLabel<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 用於 OAEP 填充的標籤。如果未指定,則不使用標籤。padding<crypto.constants> 一個在crypto.constants中定義的可選填充值,可以是:crypto.constants.RSA_NO_PADDING、crypto.constants.RSA_PKCS1_PADDING或crypto.constants.RSA_PKCS1_OAEP_PADDING。
buffer<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>- 返回: <Buffer> 一個包含解密內容的新
Buffer。
使用 privateKey 解密 buffer。buffer 之前是使用相應的公鑰加密的,例如使用 crypto.publicEncrypt()。
如果 privateKey 不是 KeyObject,此函式的行為就如同將 privateKey 傳遞給了 crypto.createPrivateKey()。如果它是一個物件,則可以傳遞 padding 屬性。否則,此函式使用 RSA_PKCS1_OAEP_PADDING。
在 crypto.privateDecrypt() 中使用 crypto.constants.RSA_PKCS1_PADDING 要求 OpenSSL 支援隱式拒絕(rsa_pkcs1_implicit_rejection)。如果 Node.js 使用的 OpenSSL 版本不支援此功能,嘗試使用 RSA_PKCS1_PADDING 將會失敗。
crypto.privateEncrypt(privateKey, buffer)#
privateKey<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey> 一個 PEM 編碼的私鑰。passphrase<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 私鑰的可選密碼短語。padding<crypto.constants> 一個在crypto.constants中定義的可選填充值,可以是:crypto.constants.RSA_NO_PADDING或crypto.constants.RSA_PKCS1_PADDING。encoding<string> 當buffer、key或passphrase是字串時使用的字串編碼。
buffer<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>- 返回: <Buffer> 一個包含加密內容的新
Buffer。
使用 privateKey 加密 buffer。返回的資料可以使用相應的公鑰解密,例如使用 crypto.publicDecrypt()。
如果 privateKey 不是 KeyObject,此函式的行為就如同將 privateKey 傳遞給了 crypto.createPrivateKey()。如果它是一個物件,則可以傳遞 padding 屬性。否則,此函式使用 RSA_PKCS1_PADDING。
crypto.publicDecrypt(key, buffer)#
key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>passphrase<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 私鑰的可選密碼短語。padding<crypto.constants> 一個在crypto.constants中定義的可選填充值,可以是:crypto.constants.RSA_NO_PADDING或crypto.constants.RSA_PKCS1_PADDING。encoding<string> 當buffer、key或passphrase是字串時使用的字串編碼。
buffer<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>- 返回: <Buffer> 一個包含解密內容的新
Buffer。
使用 key 解密 buffer。buffer 之前是使用相應的私鑰加密的,例如使用 crypto.privateEncrypt()。
如果 key 不是 KeyObject,此函式的行為就如同將 key 傳遞給了 crypto.createPublicKey()。如果它是一個物件,則可以傳遞 padding 屬性。否則,此函式使用 RSA_PKCS1_PADDING。
因為 RSA 公鑰可以從私鑰派生,所以可以傳遞私鑰而不是公鑰。
crypto.publicEncrypt(key, buffer)#
key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>key<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey> 一個 PEM 編碼的公鑰或私鑰、<KeyObject> 或 <CryptoKey>。oaepHash<string> 用於 OAEP 填充和 MGF1 的雜湊函式。預設值:'sha1'oaepLabel<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 用於 OAEP 填充的標籤。如果未指定,則不使用標籤。passphrase<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 私鑰的可選密碼短語。padding<crypto.constants> 一個在crypto.constants中定義的可選填充值,可以是:crypto.constants.RSA_NO_PADDING、crypto.constants.RSA_PKCS1_PADDING或crypto.constants.RSA_PKCS1_OAEP_PADDING。encoding<string> 當buffer、key、oaepLabel或passphrase是字串時使用的字串編碼。
buffer<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>- 返回: <Buffer> 一個包含加密內容的新
Buffer。
使用 key 加密 buffer 的內容,並返回一個包含加密內容的新 Buffer。返回的資料可以使用相應的私鑰解密,例如使用 crypto.privateDecrypt()。
如果 key 不是 KeyObject,此函式的行為就如同將 key 傳遞給了 crypto.createPublicKey()。如果它是一個物件,則可以傳遞 padding 屬性。否則,此函式使用 RSA_PKCS1_OAEP_PADDING。
因為 RSA 公鑰可以從私鑰派生,所以可以傳遞私鑰而不是公鑰。
crypto.randomBytes(size[, callback])#
size<number> 要生成的位元組數。size不得大於2**31 - 1。callback<Function>- 返回:如果未提供
callback函式,則返回 <Buffer>。
生成密碼學上強偽隨機資料。size 引數是一個數字,指示要生成的位元組數。
如果提供了 callback 函式,則位元組會非同步生成,並且 callback 函式會被呼叫並帶有兩個引數:err 和 buf。如果發生錯誤,err 將是一個 Error 物件;否則為 null。buf 引數是一個包含所生成位元組的 Buffer。
// Asynchronous
const {
randomBytes,
} = await import('node:crypto');
randomBytes(256, (err, buf) => {
if (err) throw err;
console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`);
});// Asynchronous
const {
randomBytes,
} = require('node:crypto');
randomBytes(256, (err, buf) => {
if (err) throw err;
console.log(`${buf.length} bytes of random data: ${buf.toString('hex')}`);
});
如果沒有提供 callback 函式,則隨機位元組會同步生成並作為 Buffer 返回。如果在生成位元組時出現問題,將丟擲錯誤。
// Synchronous
const {
randomBytes,
} = await import('node:crypto');
const buf = randomBytes(256);
console.log(
`${buf.length} bytes of random data: ${buf.toString('hex')}`);// Synchronous
const {
randomBytes,
} = require('node:crypto');
const buf = randomBytes(256);
console.log(
`${buf.length} bytes of random data: ${buf.toString('hex')}`);
crypto.randomBytes() 方法直到有足夠的可用熵時才會完成。這通常不應超過幾毫秒。唯一可能導致生成隨機位元組阻塞較長時間的情況是在系統啟動後不久,此時整個系統熵較低。
此 API 使用 libuv 的執行緒池,這可能對某些應用程式產生意想不到的負面性能影響;更多資訊請參閱 UV_THREADPOOL_SIZE 文件。
crypto.randomBytes() 的非同步版本在一個執行緒池請求中執行。為了最小化執行緒池任務長度的變化,在作為滿足客戶端請求的一部分執行此操作時,請將大的 randomBytes 請求進行分割槽。
crypto.randomFill(buffer[, offset][, size], callback)#
buffer<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 必須提供。所提供buffer的大小不得大於2**31 - 1。offset<number> 預設值:0size<number> 預設值:buffer.length - offset。size不得大於2**31 - 1。callback<Function>function(err, buf) {}。
此函式類似於 crypto.randomBytes(),但要求第一個引數是一個將被填充的 Buffer。它還要求傳入一個回撥函式。
如果沒有提供 callback 函式,將丟擲錯誤。
import { Buffer } from 'node:buffer';
const { randomFill } = await import('node:crypto');
const buf = Buffer.alloc(10);
randomFill(buf, (err, buf) => {
if (err) throw err;
console.log(buf.toString('hex'));
});
randomFill(buf, 5, (err, buf) => {
if (err) throw err;
console.log(buf.toString('hex'));
});
// The above is equivalent to the following:
randomFill(buf, 5, 5, (err, buf) => {
if (err) throw err;
console.log(buf.toString('hex'));
});const { randomFill } = require('node:crypto');
const { Buffer } = require('node:buffer');
const buf = Buffer.alloc(10);
randomFill(buf, (err, buf) => {
if (err) throw err;
console.log(buf.toString('hex'));
});
randomFill(buf, 5, (err, buf) => {
if (err) throw err;
console.log(buf.toString('hex'));
});
// The above is equivalent to the following:
randomFill(buf, 5, 5, (err, buf) => {
if (err) throw err;
console.log(buf.toString('hex'));
});
任何 ArrayBuffer、TypedArray 或 DataView 例項都可以作為 buffer 傳遞。
雖然這包括 Float32Array 和 Float64Array 的例項,但不應使用此函式生成隨機浮點數。結果可能包含 +Infinity、-Infinity 和 NaN,即使陣列僅包含有限的數字,它們也不是從均勻隨機分佈中抽取的,並且沒有有意義的下限或上限。
import { Buffer } from 'node:buffer';
const { randomFill } = await import('node:crypto');
const a = new Uint32Array(10);
randomFill(a, (err, buf) => {
if (err) throw err;
console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
.toString('hex'));
});
const b = new DataView(new ArrayBuffer(10));
randomFill(b, (err, buf) => {
if (err) throw err;
console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
.toString('hex'));
});
const c = new ArrayBuffer(10);
randomFill(c, (err, buf) => {
if (err) throw err;
console.log(Buffer.from(buf).toString('hex'));
});const { randomFill } = require('node:crypto');
const { Buffer } = require('node:buffer');
const a = new Uint32Array(10);
randomFill(a, (err, buf) => {
if (err) throw err;
console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
.toString('hex'));
});
const b = new DataView(new ArrayBuffer(10));
randomFill(b, (err, buf) => {
if (err) throw err;
console.log(Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength)
.toString('hex'));
});
const c = new ArrayBuffer(10);
randomFill(c, (err, buf) => {
if (err) throw err;
console.log(Buffer.from(buf).toString('hex'));
});
此 API 使用 libuv 的執行緒池,這可能對某些應用程式產生意想不到的負面性能影響;更多資訊請參閱 UV_THREADPOOL_SIZE 文件。
crypto.randomFill() 的非同步版本在一個執行緒池請求中執行。為了最小化執行緒池任務長度的變化,在作為滿足客戶端請求的一部分執行此操作時,請將大的 randomFill 請求進行分割槽。
crypto.randomFillSync(buffer[, offset][, size])#
buffer<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 必須提供。所提供buffer的大小不得大於2**31 - 1。offset<number> 預設值:0size<number> 預設值:buffer.length - offset。size不得大於2**31 - 1。- 返回: <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 作為
buffer引數傳遞的物件。
crypto.randomFill() 的同步版本。
import { Buffer } from 'node:buffer';
const { randomFillSync } = await import('node:crypto');
const buf = Buffer.alloc(10);
console.log(randomFillSync(buf).toString('hex'));
randomFillSync(buf, 5);
console.log(buf.toString('hex'));
// The above is equivalent to the following:
randomFillSync(buf, 5, 5);
console.log(buf.toString('hex'));const { randomFillSync } = require('node:crypto');
const { Buffer } = require('node:buffer');
const buf = Buffer.alloc(10);
console.log(randomFillSync(buf).toString('hex'));
randomFillSync(buf, 5);
console.log(buf.toString('hex'));
// The above is equivalent to the following:
randomFillSync(buf, 5, 5);
console.log(buf.toString('hex'));
任何 ArrayBuffer、TypedArray 或 DataView 例項都可以作為 buffer 傳遞。
import { Buffer } from 'node:buffer';
const { randomFillSync } = await import('node:crypto');
const a = new Uint32Array(10);
console.log(Buffer.from(randomFillSync(a).buffer,
a.byteOffset, a.byteLength).toString('hex'));
const b = new DataView(new ArrayBuffer(10));
console.log(Buffer.from(randomFillSync(b).buffer,
b.byteOffset, b.byteLength).toString('hex'));
const c = new ArrayBuffer(10);
console.log(Buffer.from(randomFillSync(c)).toString('hex'));const { randomFillSync } = require('node:crypto');
const { Buffer } = require('node:buffer');
const a = new Uint32Array(10);
console.log(Buffer.from(randomFillSync(a).buffer,
a.byteOffset, a.byteLength).toString('hex'));
const b = new DataView(new ArrayBuffer(10));
console.log(Buffer.from(randomFillSync(b).buffer,
b.byteOffset, b.byteLength).toString('hex'));
const c = new ArrayBuffer(10);
console.log(Buffer.from(randomFillSync(c)).toString('hex'));
crypto.randomInt([min, ]max[, callback])#
min<integer> 隨機範圍的起始值(包含)。預設值:0。max<integer> 隨機範圍的結束值(不包含)。callback<Function>function(err, n) {}。
返回一個隨機整數 n,使得 min <= n < max。此實現避免了模偏差。
範圍 (max - min) 必須小於 248。min 和 max 必須是安全整數。
如果沒有提供 callback 函式,則隨機整數會同步生成。
// Asynchronous
const {
randomInt,
} = await import('node:crypto');
randomInt(3, (err, n) => {
if (err) throw err;
console.log(`Random number chosen from (0, 1, 2): ${n}`);
});// Asynchronous
const {
randomInt,
} = require('node:crypto');
randomInt(3, (err, n) => {
if (err) throw err;
console.log(`Random number chosen from (0, 1, 2): ${n}`);
});
// Synchronous
const {
randomInt,
} = await import('node:crypto');
const n = randomInt(3);
console.log(`Random number chosen from (0, 1, 2): ${n}`);// Synchronous
const {
randomInt,
} = require('node:crypto');
const n = randomInt(3);
console.log(`Random number chosen from (0, 1, 2): ${n}`);
// With `min` argument
const {
randomInt,
} = await import('node:crypto');
const n = randomInt(1, 7);
console.log(`The dice rolled: ${n}`);// With `min` argument
const {
randomInt,
} = require('node:crypto');
const n = randomInt(1, 7);
console.log(`The dice rolled: ${n}`);
crypto.randomUUID([options])#
options<Object>disableEntropyCache<boolean> 預設情況下,為提高效能,Node.js 會生成並快取足夠的隨機資料,以生成多達 128 個隨機 UUID。要生成一個不使用快取的 UUID,請將disableEntropyCache設定為true。預設值:false。
- 返回: <string>
生成一個隨機的 RFC 4122 版本 4 UUID。該 UUID 使用密碼學偽隨機數生成器生成。
crypto.scrypt(password, salt, keylen[, options], callback)#
password<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>salt<string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>keylen<number>options<Object>cost<number> CPU/記憶體成本引數。必須是大於 1 的 2 的冪。預設值:16384。blockSize<number> 塊大小引數。預設值:8。parallelization<number> 並行化引數。預設值:1。N<number>cost的別名。兩者中只能指定一個。r<number>blockSize的別名。兩者中只能指定一個。p<number>parallelization的別名。兩者中只能指定一個。maxmem<number> 記憶體上限。當(大約)128 * N * r > maxmem時會報錯。預設值:32 * 1024 * 1024。
callback<Function>
提供一個非同步的 scrypt 實現。Scrypt 是一種基於密碼的金鑰派生函式,其設計旨在計算和記憶體上都非常昂貴,以使暴力攻擊得不償失。
salt 應儘可能唯一。建議 salt 是隨機的,並且長度至少為 16 位元組。詳情請參閱 NIST SP 800-132。
當為 password 或 salt 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
callback 函式被呼叫時帶有兩個引數:err 和 derivedKey。當金鑰派生失敗時,err 是一個異常物件,否則 err 為 null。derivedKey 作為 Buffer 傳遞給回撥函式。
當任何輸入引數指定了無效的值或型別時,會丟擲異常。
const {
scrypt,
} = await import('node:crypto');
// Using the factory defaults.
scrypt('password', 'salt', 64, (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // '3745e48...08d59ae'
});
// Using a custom N parameter. Must be a power of two.
scrypt('password', 'salt', 64, { N: 1024 }, (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // '3745e48...aa39b34'
});const {
scrypt,
} = require('node:crypto');
// Using the factory defaults.
scrypt('password', 'salt', 64, (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // '3745e48...08d59ae'
});
// Using a custom N parameter. Must be a power of two.
scrypt('password', 'salt', 64, { N: 1024 }, (err, derivedKey) => {
if (err) throw err;
console.log(derivedKey.toString('hex')); // '3745e48...aa39b34'
});
crypto.scryptSync(password, salt, keylen[, options])#
password<string> | <Buffer> | <TypedArray> | <DataView>salt<string> | <Buffer> | <TypedArray> | <DataView>keylen<number>options<Object>cost<number> CPU/記憶體成本引數。必須是大於 1 的 2 的冪。預設值:16384。blockSize<number> 塊大小引數。預設值:8。parallelization<number> 並行化引數。預設值:1。N<number>cost的別名。兩者中只能指定一個。r<number>blockSize的別名。兩者中只能指定一個。p<number>parallelization的別名。兩者中只能指定一個。maxmem<number> 記憶體上限。當(大約)128 * N * r > maxmem時會報錯。預設值:32 * 1024 * 1024。
- 返回:<Buffer>
提供一個同步的 scrypt 實現。Scrypt 是一種基於密碼的金鑰派生函式,其設計旨在計算和記憶體上都非常昂貴,以使暴力攻擊得不償失。
salt 應儘可能唯一。建議 salt 是隨機的,並且長度至少為 16 位元組。詳情請參閱 NIST SP 800-132。
當為 password 或 salt 傳遞字串時,請考慮將字串用作加密 API 輸入時的注意事項。
當金鑰派生失敗時,會丟擲異常,否則派生的金鑰將作為 Buffer 返回。
當任何輸入引數指定了無效的值或型別時,會丟擲異常。
const {
scryptSync,
} = await import('node:crypto');
// Using the factory defaults.
const key1 = scryptSync('password', 'salt', 64);
console.log(key1.toString('hex')); // '3745e48...08d59ae'
// Using a custom N parameter. Must be a power of two.
const key2 = scryptSync('password', 'salt', 64, { N: 1024 });
console.log(key2.toString('hex')); // '3745e48...aa39b34'const {
scryptSync,
} = require('node:crypto');
// Using the factory defaults.
const key1 = scryptSync('password', 'salt', 64);
console.log(key1.toString('hex')); // '3745e48...08d59ae'
// Using a custom N parameter. Must be a power of two.
const key2 = scryptSync('password', 'salt', 64, { N: 1024 });
console.log(key2.toString('hex')); // '3745e48...aa39b34'
crypto.secureHeapUsed()#
crypto.setEngine(engine[, flags])#
engine<string>flags<crypto.constants> 預設值:crypto.constants.ENGINE_METHOD_ALL
為部分或全部 OpenSSL 函式(由標誌選擇)載入並設定 engine。OpenSSL 3 起已棄用對自定義引擎的支援。
engine 可以是引擎的 id 或其共享庫的路徑。
可選的 flags 引數預設使用 ENGINE_METHOD_ALL。flags 是一個位欄位,可以接受以下一個或多個標誌的組合(定義在 crypto.constants 中):
crypto.constants.ENGINE_METHOD_RSAcrypto.constants.ENGINE_METHOD_DSAcrypto.constants.ENGINE_METHOD_DHcrypto.constants.ENGINE_METHOD_RANDcrypto.constants.ENGINE_METHOD_ECcrypto.constants.ENGINE_METHOD_CIPHERScrypto.constants.ENGINE_METHOD_DIGESTScrypto.constants.ENGINE_METHOD_PKEY_METHScrypto.constants.ENGINE_METHOD_PKEY_ASN1_METHScrypto.constants.ENGINE_METHOD_ALLcrypto.constants.ENGINE_METHOD_NONE
crypto.setFips(bool)#
bool<boolean>true表示啟用 FIPS 模式。
在一個啟用了 FIPS 的 Node.js 構建中,啟用符合 FIPS 的加密提供程式。如果 FIPS 模式不可用,則丟擲錯誤。
crypto.sign(algorithm, data, key[, callback])#
algorithm<string> | <null> | <undefined>data<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>callback<Function>- 返回:如果未提供
callback函式,則返回 <Buffer>。
使用給定的私鑰和演算法計算並返回 data 的簽名。如果 algorithm 為 null 或 undefined,則演算法依賴於金鑰型別。
對於 Ed25519、Ed448 和 ML-DSA,algorithm 必須為 null 或 undefined。
如果 key 不是 KeyObject,此函式的行為就如同將 key 傳遞給了 crypto.createPrivateKey()。如果它是一個物件,可以傳遞以下附加屬性:
-
dsaEncoding<string> 對於 DSA 和 ECDSA,此選項指定生成簽名的格式。它可以是以下之一:'der'(預設): DER 編碼的 ASN.1 簽名結構,編碼為(r, s)。'ieee-p1363':IEEE-P1363 中提議的簽名格式r || s。
-
padding<integer> RSA 的可選填充值,為以下之一:crypto.constants.RSA_PKCS1_PADDING(預設)crypto.constants.RSA_PKCS1_PSS_PADDING
RSA_PKCS1_PSS_PADDING將使用 MGF1,其雜湊函式與 RFC 4055 第 3.1 節中指定的用於簽署訊息的雜湊函式相同。 -
saltLength<integer> 當填充為RSA_PKCS1_PSS_PADDING時的鹽長度。特殊值crypto.constants.RSA_PSS_SALTLEN_DIGEST將鹽長度設定為摘要大小,crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN(預設) 將其設定為最大允許值。 -
context<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 對於 Ed448、ML-DSA 和 SLH-DSA,此選項指定可選的上下文,以區分使用相同金鑰為不同目的生成的簽名。
如果提供了 callback 函式,此函式將使用 libuv 的執行緒池。
crypto.timingSafeEqual(a, b)#
a<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>b<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>- 返回:<boolean>
此函式使用恆定時間演算法比較表示給定 ArrayBuffer、TypedArray 或 DataView 例項的底層位元組。
此函式不會洩露計時資訊,從而避免攻擊者猜測其中一個值。這適用於比較 HMAC 摘要或機密值,如身份驗證 Cookie 或能力 URL。
a 和 b 必須都是 Buffer、TypedArray 或 DataView,並且它們必須具有相同的位元組長度。如果 a 和 b 的位元組長度不同,則會丟擲錯誤。
如果 a 和 b 中至少有一個是每個條目超過一個位元組的 TypedArray(例如 Uint16Array),則結果將使用平臺位元組序進行計算。
當兩個輸入都是 Float32Array 或 Float64Array 時,由於 IEEE 754 浮點數編碼,此函式可能會返回意外結果。特別是,x === y 和 Object.is(x, y) 都不意味著兩個浮點數 x 和 y 的位元組表示是相等的。
使用 crypto.timingSafeEqual 並不能保證*周邊*程式碼是時間安全的。應注意確保周邊程式碼不會引入時間漏洞。
crypto.verify(algorithm, data, key, signature[, callback])#
algorithm<string> | <null> | <undefined>data<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>key<Object> | <string> | <ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> | <KeyObject> | <CryptoKey>signature<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView>callback<Function>- 返回: <boolean> 如果未提供
callback函式,則根據資料和公鑰的簽名有效性返回true或false。
使用給定的金鑰和演算法驗證 data 的簽名。如果 algorithm 為 null 或 undefined,則演算法依賴於金鑰型別。
對於 Ed25519、Ed448 和 ML-DSA,algorithm 必須為 null 或 undefined。
如果 key 不是 KeyObject,此函式的行為就如同將 key 傳遞給了 crypto.createPublicKey()。如果它是一個物件,可以傳遞以下附加屬性:
-
dsaEncoding<string> 對於 DSA 和 ECDSA,此選項指定簽名的格式。它可以是以下之一:'der'(預設): DER 編碼的 ASN.1 簽名結構,編碼為(r, s)。'ieee-p1363':IEEE-P1363 中提議的簽名格式r || s。
-
padding<integer> RSA 的可選填充值,為以下之一:crypto.constants.RSA_PKCS1_PADDING(預設)crypto.constants.RSA_PKCS1_PSS_PADDING
RSA_PKCS1_PSS_PADDING將使用 MGF1,其雜湊函式與 RFC 4055 第 3.1 節中指定的用於簽署訊息的雜湊函式相同。 -
saltLength<integer> 當填充為RSA_PKCS1_PSS_PADDING時的鹽長度。特殊值crypto.constants.RSA_PSS_SALTLEN_DIGEST將鹽長度設定為摘要大小,crypto.constants.RSA_PSS_SALTLEN_MAX_SIGN(預設) 將其設定為最大允許值。 -
context<ArrayBuffer> | <Buffer> | <TypedArray> | <DataView> 對於 Ed448、ML-DSA 和 SLH-DSA,此選項指定可選的上下文,以區分使用相同金鑰為不同目的生成的簽名。
signature 引數是先前為 data 計算的簽名。
由於公鑰可以從私鑰派生,因此可以為 key 傳遞私鑰或公鑰。
如果提供了 callback 函式,此函式將使用 libuv 的執行緒池。
注意事項#
將字串用作加密 API 的輸入#
由於歷史原因,Node.js 提供的許多加密 API 接受字串作為輸入,而底層加密演算法處理的是位元組序列。這些情況包括明文、密文、對稱金鑰、初始化向量、密碼短語、鹽值、認證標籤和附加認證資料。
將字串傳遞給加密 API 時,請考慮以下因素。
-
並非所有位元組序列都是有效的 UTF-8 字串。因此,當從字串派生出長度為
n的位元組序列時,其熵通常低於隨機或偽隨機n位元組序列的熵。例如,沒有 UTF-8 字串會產生位元組序列c0 af。金鑰幾乎都應該是隨機或偽隨機的位元組序列。 -
同樣,當將隨機或偽隨機位元組序列轉換為 UTF-8 字串時,不代表有效碼點的子序列可能會被 Unicode 替換字元 (
U+FFFD) 替換。因此,生成的 Unicode 字串的位元組表示可能不等於建立該字串的位元組序列。const original = [0xc0, 0xaf]; const bytesAsString = Buffer.from(original).toString('utf8'); const stringAsBytes = Buffer.from(bytesAsString, 'utf8'); console.log(stringAsBytes); // Prints '<Buffer ef bf bd ef bf bd>'.密碼、雜湊函式、簽名演算法和金鑰派生函式的輸出是偽隨機位元組序列,不應作為 Unicode 字串使用。
-
當從使用者輸入中獲取字串時,一些 Unicode 字元可以用多種等效方式表示,從而導致不同的位元組序列。例如,當將使用者密碼短語傳遞給金鑰派生函式(如 PBKDF2 或 scrypt)時,金鑰派生函式的結果取決於字串是使用組合字元還是分解字元。Node.js 不會規範化字元表示。開發者應考慮在將使用者輸入傳遞給加密 API 之前使用
String.prototype.normalize()。
舊版流 API(Node.js 0.10 之前)#
Crypto 模組是在統一的 Stream API 概念出現之前以及在用於處理二進位制資料的 Buffer 物件出現之前新增到 Node.js 中的。因此,許多 crypto 類具有通常在其他實現 streams API 的 Node.js 類中找不到的方法(例如 update()、final() 或 digest())。此外,許多方法預設接受並返回 'latin1' 編碼的字串,而不是 Buffer。這個預設值在 Node.js v0.8 之後被更改為預設使用 Buffer 物件。
對弱演算法或已受損演算法的支援#
node:crypto 模組仍然支援一些已經受到威脅且不推薦使用的演算法。該 API 還允許使用金鑰大小過小、安全性不足的密碼和雜湊。
使用者應根據其安全需求,對選擇加密演算法和金鑰大小負全部責任。
根據 NIST SP 800-131A 的建議
- 在需要抗碰撞性的場合(如數字簽名),MD5 和 SHA-1 已不再可接受。
- 建議與 RSA、DSA 和 DH 演算法一起使用的金鑰至少有 2048 位,而 ECDSA 和 ECDH 的曲線至少有 224 位,以便在未來幾年內安全使用。
modp1、modp2和modp5的 DH 組的金鑰大小小於 2048 位,不推薦使用。
有關其他建議和詳細資訊,請參閱參考文獻。
一些已知存在弱點且在實踐中關聯性不大的演算法只能透過舊版提供程式獲得,該提供程式預設不啟用。
CCM 模式#
CCM 是受支援的AEAD 演算法之一。使用此模式的應用程式在使用 cipher API 時必須遵守某些限制:
- 身份驗證標籤的長度必須在建立密碼時透過設定
authTagLength選項來指定,並且必須是 4、6、8、10、12、14 或 16 位元組之一。 - 初始化向量 (nonce)
N的長度必須在 7 到 13 位元組之間 (7 ≤ N ≤ 13)。 - 明文的長度限制為
2 ** (8 * (15 - N))位元組。 - 解密時,必須在呼叫
update()之前透過setAuthTag()設定身份驗證標籤。否則,解密將失敗,並且final()將根據 RFC 3610 第 2.6 節丟擲錯誤。 - 在 CCM 模式下使用流方法(如
write(data)、end(data)或pipe())可能會失敗,因為 CCM 每個例項只能處理一個數據塊。 - 當傳遞附加認證資料 (AAD) 時,實際訊息的位元組長度必須透過
plaintextLength選項傳遞給setAAD()。許多加密庫將身份驗證標籤包含在密文中,這意味著它們生成的密文長度為plaintextLength + authTagLength。Node.js 不包含身份驗證標籤,所以密文長度始終為plaintextLength。如果未使用 AAD,則此項不是必需的。 - 由於 CCM 一次處理整個訊息,
update()必須只調用一次。 - 儘管呼叫
update()足以加密/解密訊息,但應用程式*必須*呼叫final()來計算或驗證身份驗證標籤。
import { Buffer } from 'node:buffer';
const {
createCipheriv,
createDecipheriv,
randomBytes,
} = await import('node:crypto');
const key = 'keykeykeykeykeykeykeykey';
const nonce = randomBytes(12);
const aad = Buffer.from('0123456789', 'hex');
const cipher = createCipheriv('aes-192-ccm', key, nonce, {
authTagLength: 16,
});
const plaintext = 'Hello world';
cipher.setAAD(aad, {
plaintextLength: Buffer.byteLength(plaintext),
});
const ciphertext = cipher.update(plaintext, 'utf8');
cipher.final();
const tag = cipher.getAuthTag();
// Now transmit { ciphertext, nonce, tag }.
const decipher = createDecipheriv('aes-192-ccm', key, nonce, {
authTagLength: 16,
});
decipher.setAuthTag(tag);
decipher.setAAD(aad, {
plaintextLength: ciphertext.length,
});
const receivedPlaintext = decipher.update(ciphertext, null, 'utf8');
try {
decipher.final();
} catch (err) {
throw new Error('Authentication failed!', { cause: err });
}
console.log(receivedPlaintext);const { Buffer } = require('node:buffer');
const {
createCipheriv,
createDecipheriv,
randomBytes,
} = require('node:crypto');
const key = 'keykeykeykeykeykeykeykey';
const nonce = randomBytes(12);
const aad = Buffer.from('0123456789', 'hex');
const cipher = createCipheriv('aes-192-ccm', key, nonce, {
authTagLength: 16,
});
const plaintext = 'Hello world';
cipher.setAAD(aad, {
plaintextLength: Buffer.byteLength(plaintext),
});
const ciphertext = cipher.update(plaintext, 'utf8');
cipher.final();
const tag = cipher.getAuthTag();
// Now transmit { ciphertext, nonce, tag }.
const decipher = createDecipheriv('aes-192-ccm', key, nonce, {
authTagLength: 16,
});
decipher.setAuthTag(tag);
decipher.setAAD(aad, {
plaintextLength: ciphertext.length,
});
const receivedPlaintext = decipher.update(ciphertext, null, 'utf8');
try {
decipher.final();
} catch (err) {
throw new Error('Authentication failed!', { cause: err });
}
console.log(receivedPlaintext);
FIPS 模式#
當使用 OpenSSL 3 時,Node.js 在與適當的 OpenSSL 3 提供程式(例如來自 OpenSSL 3 的 FIPS 提供程式)一起使用時支援 FIPS 140-2,該提供程式可以按照 OpenSSL 的 FIPS README 檔案中的說明進行安裝。
要在 Node.js 中支援 FIPS,您需要:
- 一個正確安裝的 OpenSSL 3 FIPS 提供程式。
- 一個 OpenSSL 3 FIPS 模組配置檔案。
- 一個引用 FIPS 模組配置檔案的 OpenSSL 3 配置檔案。
Node.js 需要使用一個指向 FIPS 提供程式的 OpenSSL 配置檔案進行配置。一個示例配置檔案如下:
nodejs_conf = nodejs_init
.include /<absolute path>/fipsmodule.cnf
[nodejs_init]
providers = provider_sect
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
fips = fips_sect
[default_sect]
activate = 1
其中 fipsmodule.cnf 是從 FIPS 提供程式安裝步驟生成的 FIPS 模組配置檔案:
openssl fipsinstall
將 OPENSSL_CONF 環境變數設定為指向您的配置檔案,並將 OPENSSL_MODULES 設定為 FIPS 提供程式動態庫的位置。例如:
export OPENSSL_CONF=/<path to configuration file>/nodejs.cnf
export OPENSSL_MODULES=/<path to openssl lib>/ossl-modules
然後可以透過以下方式在 Node.js 中啟用 FIPS 模式:
- 使用
--enable-fips或--force-fips命令列標誌啟動 Node.js。 - 以程式設計方式呼叫
crypto.setFips(true)。
或者,可以透過 OpenSSL 配置檔案在 Node.js 中啟用 FIPS 模式。例如:
nodejs_conf = nodejs_init
.include /<absolute path>/fipsmodule.cnf
[nodejs_init]
providers = provider_sect
alg_section = algorithm_sect
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included fipsmodule.cnf.
fips = fips_sect
[default_sect]
activate = 1
[algorithm_sect]
default_properties = fips=yes
加密常量#
由 crypto.constants 匯出的以下常量適用於 node:crypto、node:tls 和 node:https 模組的各種用途,並且通常特定於 OpenSSL。
OpenSSL 選項#
詳情請參閱 SSL OP 標誌列表。
| 常量 | 描述 |
|---|---|
SSL_OP_ALL |
在 OpenSSL 中應用多個錯誤修復。詳情請參閱 https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_options.html。 |
SSL_OP_ALLOW_NO_DHE_KEX |
指示 OpenSSL 允許為 TLS v1.3 使用非 [EC]DHE 的金鑰交換模式。 |
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION |
允許 OpenSSL 與未打補丁的客戶端或伺服器之間進行舊版不安全的重新協商。請參閱 https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_options.html。 |
SSL_OP_CIPHER_SERVER_PREFERENCE |
在選擇密碼時,嘗試使用伺服器的偏好而不是客戶端的。行為取決於協議版本。請參閱 https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set_options.html。 |
SSL_OP_CISCO_ANYCONNECT |
指示 OpenSSL 使用思科版本的 DTLS_BAD_VER 識別符號。 |
SSL_OP_COOKIE_EXCHANGE |
指示 OpenSSL 開啟 cookie 交換。 |
SSL_OP_CRYPTOPRO_TLSEXT_BUG |
指示 OpenSSL 新增來自早期版本 cryptopro 草案的 server-hello 擴充套件。 |
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS |
指示 OpenSSL 停用 OpenSSL 0.9.6d 中新增的 SSL 3.0/TLS 1.0 漏洞修復。 |
SSL_OP_LEGACY_SERVER_CONNECT |
允許初始連線到不支援 RI 的伺服器。 |
SSL_OP_NO_COMPRESSION |
指示 OpenSSL 停用對 SSL/TLS 壓縮的支援。 |
SSL_OP_NO_ENCRYPT_THEN_MAC |
指示 OpenSSL 停用 encrypt-then-MAC。 |
SSL_OP_NO_QUERY_MTU |
|
SSL_OP_NO_RENEGOTIATION |
指示 OpenSSL 停用重新協商。 |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
指示 OpenSSL 在執行重新協商時總是啟動一個新會話。 |
SSL_OP_NO_SSLv2 |
指示 OpenSSL 關閉 SSL v2 |
SSL_OP_NO_SSLv3 |
指示 OpenSSL 關閉 SSL v3 |
SSL_OP_NO_TICKET |
指示 OpenSSL 停用 RFC4507bis 票據的使用。 |
SSL_OP_NO_TLSv1 |
指示 OpenSSL 關閉 TLS v1 |
SSL_OP_NO_TLSv1_1 |
指示 OpenSSL 關閉 TLS v1.1 |
SSL_OP_NO_TLSv1_2 |
指示 OpenSSL 關閉 TLS v1.2 |
SSL_OP_NO_TLSv1_3 |
指示 OpenSSL 關閉 TLS v1.3 |
SSL_OP_PRIORITIZE_CHACHA |
指示 OpenSSL 伺服器在客戶端也這樣做時優先選擇 ChaCha20-Poly1305。如果未啟用 SSL_OP_CIPHER_SERVER_PREFERENCE,此選項無效。 |
SSL_OP_TLS_ROLLBACK_BUG |
指示 OpenSSL 停用版本回滾攻擊檢測。 |
OpenSSL 引擎常量#
| 常量 | 描述 |
|---|---|
ENGINE_METHOD_RSA |
限制引擎使用 RSA |
ENGINE_METHOD_DSA |
限制引擎使用 DSA |
ENGINE_METHOD_DH |
限制引擎使用 DH |
ENGINE_METHOD_RAND |
限制引擎使用 RAND |
ENGINE_METHOD_EC |
限制引擎使用 EC |
ENGINE_METHOD_CIPHERS |
限制引擎使用 CIPHERS |
ENGINE_METHOD_DIGESTS |
限制引擎使用 DIGESTS |
ENGINE_METHOD_PKEY_METHS |
限制引擎使用 PKEY_METHS |
ENGINE_METHOD_PKEY_ASN1_METHS |
限制引擎使用 PKEY_ASN1_METHS |
ENGINE_METHOD_ALL |
|
ENGINE_METHOD_NONE |
其他 OpenSSL 常量#
| 常量 | 描述 |
|---|---|
DH_CHECK_P_NOT_SAFE_PRIME |
|
DH_CHECK_P_NOT_PRIME |
|
DH_UNABLE_TO_CHECK_GENERATOR |
|
DH_NOT_SUITABLE_GENERATOR |
|
RSA_PKCS1_PADDING |
|
RSA_SSLV23_PADDING |
|
RSA_NO_PADDING |
|
RSA_PKCS1_OAEP_PADDING |
|
RSA_X931_PADDING |
|
RSA_PKCS1_PSS_PADDING |
|
RSA_PSS_SALTLEN_DIGEST |
在簽名或驗證時,將 RSA_PKCS1_PSS_PADDING 的鹽長度設定為摘要大小。 |
RSA_PSS_SALTLEN_MAX_SIGN |
在簽署資料時,將 RSA_PKCS1_PSS_PADDING 的鹽長度設定為最大允許值。 |
RSA_PSS_SALTLEN_AUTO |
在驗證簽名時,使 RSA_PKCS1_PSS_PADDING 的鹽長度自動確定。 |
POINT_CONVERSION_COMPRESSED |
|
POINT_CONVERSION_UNCOMPRESSED |
|
POINT_CONVERSION_HYBRID |