• Home
Name Date Size #Lines LOC

..--

README.mdD07-Sep-202414.2 KiB348268

crypto_aes.ccD07-Sep-202418.3 KiB605490

crypto_aes.hD07-Sep-20243 KiB9072

crypto_bio.ccD07-Sep-202411.6 KiB501340

crypto_bio.hD07-Sep-20246.2 KiB193100

crypto_cipher.ccD07-Sep-202436.4 KiB1,111863

crypto_cipher.hD07-Sep-20249.1 KiB292239

crypto_clienthello-inl.hD07-Sep-20242.6 KiB9156

crypto_clienthello.ccD07-Sep-20246.6 KiB239148

crypto_clienthello.hD07-Sep-20244.2 KiB13282

crypto_common.ccD07-Sep-202445.2 KiB1,4051,134

crypto_common.hD07-Sep-20244.4 KiB148106

crypto_context.ccD07-Sep-202444.1 KiB1,3881,076

crypto_context.hD07-Sep-20246.2 KiB161123

crypto_dh.ccD07-Sep-202423 KiB729598

crypto_dh.hD07-Sep-20245 KiB158123

crypto_dsa.ccD07-Sep-20245.2 KiB180139

crypto_dsa.hD07-Sep-20242.2 KiB7861

crypto_ec.ccD07-Sep-202430.9 KiB1,019822

crypto_ec.hD07-Sep-20245.1 KiB171131

crypto_hash.ccD07-Sep-202410.8 KiB365286

crypto_hash.hD07-Sep-20242.5 KiB9269

crypto_hkdf.ccD07-Sep-20245.1 KiB168133

crypto_hkdf.hD07-Sep-20241.6 KiB6449

crypto_hmac.ccD07-Sep-20247.8 KiB283237

crypto_hmac.hD07-Sep-20242.6 KiB9570

crypto_keygen.ccD07-Sep-20243 KiB11388

crypto_keygen.hD07-Sep-20249 KiB299231

crypto_keys.ccD07-Sep-202447.8 KiB1,5171,254

crypto_keys.hD07-Sep-202412.3 KiB420320

crypto_pbkdf2.ccD07-Sep-20243.8 KiB140106

crypto_pbkdf2.hD07-Sep-20242 KiB7749

crypto_random.ccD07-Sep-20246.8 KiB240195

crypto_random.hD07-Sep-20243.6 KiB131106

crypto_rsa.ccD07-Sep-202420.2 KiB652513

crypto_rsa.hD07-Sep-20243.9 KiB142110

crypto_scrypt.ccD07-Sep-20243.7 KiB145119

crypto_scrypt.hD07-Sep-20242.2 KiB8858

crypto_sig.ccD07-Sep-202425.3 KiB834703

crypto_sig.hD07-Sep-20244.5 KiB169130

crypto_spkac.ccD07-Sep-20244.7 KiB145107

crypto_spkac.hD07-Sep-2024538 2216

crypto_timing.ccD07-Sep-20241.6 KiB6047

crypto_timing.hD07-Sep-2024525 2115

crypto_tls.ccD07-Sep-202469.8 KiB2,2421,641

crypto_tls.hD07-Sep-202412 KiB305198

crypto_util.ccD07-Sep-202425.3 KiB771620

crypto_util.hD07-Sep-202425.3 KiB806599

crypto_x509.ccD07-Sep-202417.2 KiB548454

crypto_x509.hD07-Sep-20244.8 KiB141110

README.md

1# Node.js `src/crypto` documentation
2
3Welcome. You've found your way to the Node.js native crypto subsystem.
4
5Do not be afraid.
6
7While crypto may be a dark, mysterious, and forboding subject; and while
8this directory may be filled with many `*.h` and `*.cc` files, finding
9your way around is not too difficult. And I can promise you that a Gru
10will not jump out of the shadows and eat you (well, "promise" may be a
11bit too strong, a Gru may jump out of the shadows and eat you if you
12live in a place where such things are possible).
13
14## Finding your way around
15
16All of the code in this directory is structured into units organized by
17function or crypto protocol.
18
19The following provide generalized utility declarations that are used throughout
20the various other crypto files and other parts of Node.js:
21
22* `crypto_util.h` / `crypto_util.cc` (Core crypto definitions)
23* `crypto_common.h` / `crypto_common.cc` (Shared TLS utility functions)
24* `crypto_bio.h` / `crypto_bio.cc` (Custom OpenSSL i/o implementation)
25
26Of these, `crypto_util.h` and `crypto_util.cc` are the most important, as
27they provide the core declarations and utility functions used most extensively
28throughout the rest of the code.
29
30The rest of the files are structured by their function, as detailed in the
31following table:
32
33| File (\*.h/\*.cc)    | Description                                                                |
34| -------------------- | -------------------------------------------------------------------------- |
35| `crypto_aes`         | AES Cipher support.                                                        |
36| `crypto_cipher`      | General Encryption/Decryption utilities.                                   |
37| `crypto_clienthello` | TLS/SSL client hello parser implementation. Used during SSL/TLS handshake. |
38| `crypto_context`     | Implementation of the `SecureContext` object.                              |
39| `crypto_dh`          | Diffie-Hellman Key Agreement implementation.                               |
40| `crypto_dsa`         | DSA (Digital Signature) Key Generation functions.                          |
41| `crypto_ec`          | Elliptic-curve cryptography implementation.                                |
42| `crypto_hash`        | Basic hash (e.g. SHA-256) functions.                                       |
43| `crypto_hkdf`        | HKDF (Key derivation) implementation.                                      |
44| `crypto_hmac`        | HMAC implementations.                                                      |
45| `crypto_keys`        | Utilities for using and generating secret, private, and public keys.       |
46| `crypto_pbkdf2`      | PBKDF2 key / bit generation implementation.                                |
47| `crypto_rsa`         | RSA Key Generation functions.                                              |
48| `crypto_scrypt`      | Scrypt key / bit generation implementation.                                |
49| `crypto_sig`         | General digital signature and verification utilities.                      |
50| `crypto_spkac`       | Netscape SPKAC certificate utilities.                                      |
51| `crypto_ssl`         | Implementation of the `SSLWrap` object.                                    |
52| `crypto_timing`      | Implementation of the TimingSafeEqual.                                     |
53
54When new crypto protocols are added, they will be added into their own
55`crypto_` `*.h` and `*.cc` files.
56
57## Helpful concepts
58
59Node.js currently uses OpenSSL to provide it's crypto substructure.
60(Some custom Node.js distributions -- such as Electron -- use BoringSSL
61instead.)
62
63This section aims to explain some of the utilities that have been
64provided to make working with the OpenSSL APIs a bit easier.
65
66### Pointer types
67
68Most of the key OpenSSL types need to be explicitly freed when they are
69no longer needed. Failure to do so introduces memory leaks. To make this
70easier (and less error prone), the `crypto_util.h` defines a number of
71smart-pointer aliases that should be used:
72
73```cpp
74using X509Pointer = DeleteFnPtr<X509, X509_free>;
75using BIOPointer = DeleteFnPtr<BIO, BIO_free_all>;
76using SSLCtxPointer = DeleteFnPtr<SSL_CTX, SSL_CTX_free>;
77using SSLSessionPointer = DeleteFnPtr<SSL_SESSION, SSL_SESSION_free>;
78using SSLPointer = DeleteFnPtr<SSL, SSL_free>;
79using PKCS8Pointer = DeleteFnPtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
80using EVPKeyPointer = DeleteFnPtr<EVP_PKEY, EVP_PKEY_free>;
81using EVPKeyCtxPointer = DeleteFnPtr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
82using EVPMDPointer = DeleteFnPtr<EVP_MD_CTX, EVP_MD_CTX_free>;
83using RSAPointer = DeleteFnPtr<RSA, RSA_free>;
84using ECPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
85using BignumPointer = DeleteFnPtr<BIGNUM, BN_free>;
86using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
87using ECGroupPointer = DeleteFnPtr<EC_GROUP, EC_GROUP_free>;
88using ECPointPointer = DeleteFnPtr<EC_POINT, EC_POINT_free>;
89using ECKeyPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
90using DHPointer = DeleteFnPtr<DH, DH_free>;
91using ECDSASigPointer = DeleteFnPtr<ECDSA_SIG, ECDSA_SIG_free>;
92using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>;
93using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
94```
95
96Examples of these being used are pervasive through the `src/crypto` code.
97
98### `ByteSource`
99
100The `ByteSource` class is a helper utility representing a _read-only_ byte
101array. Instances can either wrap external ("foreign") data sources, such as
102an `ArrayBuffer` (`v8::BackingStore`), or allocated data.
103
104* If a pointer to external data is used to create a `ByteSource`, that pointer
105  must remain valid until the `ByteSource` is destroyed.
106* If allocated data is used, then it must have been allocated using OpenSSL's
107  allocator. It will be freed automatically when the `ByteSource` is destroyed.
108
109The `ByteSource::Builder` class can be used to allocate writable memory that can
110then be released as a `ByteSource`, making it read-only, or freed by destroying
111the `ByteSource::Builder` without releasing it as a `ByteSource`.
112
113### `ArrayBufferOrViewContents`
114
115The `ArrayBufferOrViewContents` class is a helper utility that abstracts
116`ArrayBuffer`, `TypedArray`, or `DataView` inputs and provides access to
117their underlying data pointers. It is used extensively through `src/crypto`
118to make it easier to deal with inputs that allow any `ArrayBuffer`-backed
119object.
120
121The lifetime of `ArrayBufferOrViewContents` should not exceed the
122lifetime of its input.
123
124### Key objects
125
126Most crypto operations involve the use of keys -- cryptographic inputs
127that protect data. There are three general types of keys:
128
129* Secret Keys (Symmetric)
130* Public Keys (Asymmetric)
131* Private Keys (Asymmetric)
132
133Secret keys consist of a variable number of bytes. They are "symmetrical"
134in that the same key used to encrypt data, or generate a signature, must
135be used to decrypt or validate that signature. If two people are exchanging
136messages encrypted using a secret key, both of them must have access to the
137same secret key data.
138
139Public and Private keys always come in pairs. When one is used to encrypt
140data or generate a signature, the other is used to decrypt or validate the
141signature. The Public key is intended to be shared and can be shared openly.
142The Private key must be kept secret and known only to the owner of the key.
143
144The `src/crypto` subsystem uses several objects to represent keys. These
145objects are structured in a way to allow key data to be shared across
146multiple threads (the Node.js main thread, Worker Threads, and the libuv
147threadpool).
148
149Refer to `crypto_keys.h` and `crypto_keys.cc` for all code relating to the
150core key objects.
151
152#### `ManagedEVPPKey`
153
154The `ManagedEVPPKey` class is a smart pointer for OpenSSL `EVP_PKEY`
155structures. These manage the lifecycle of Public and Private key pairs.
156
157#### `KeyObjectData`
158
159`KeyObjectData` is an internal thread-safe structure used to wrap either
160a `ManagedEVPPKey` (for Public or Private keys) or a `ByteSource` containing
161a Secret key.
162
163#### `KeyObjectHandle`
164
165The `KeyObjectHandle` provides the interface between the native C++ code
166handling keys and the public JavaScript `KeyObject` API.
167
168#### `KeyObject`
169
170A `KeyObject` is the public Node.js-specific API for keys. A single
171`KeyObject` wraps exactly one `KeyObjectHandle`.
172
173#### `CryptoKey`
174
175A `CryptoKey` is the Web Crypto API's alternative to `KeyObject`. In the
176Node.js implementation, `CryptoKey` is a thin wrapper around the
177`KeyObject` and it is largely possible to use them interchangeably.
178
179### `CryptoJob`
180
181All operations that are not either Stream-based or single-use functions
182are built around the `CryptoJob` class.
183
184A `CryptoJob` encapsulates a single crypto operation that can be
185invoked synchronously or asynchronously.
186
187The `CryptoJob` class itself is a C++ template that takes a single
188`CryptoJobTraits` struct as a parameter. The `CryptoJobTraits`
189provides the implementation detail of the job.
190
191There are (currently) four basic `CryptoJob` specializations:
192
193* `CipherJob` (defined in `src/crypto_cipher.h`) -- Used for
194  encrypt and decrypt operations.
195* `KeyGenJob` (defined in `src/crypto_keygen.h`) -- Used for
196  secret and key pair generation operations.
197* `KeyExportJob` (defined in `src/crypto_keys.h`) -- Used for
198  key export operations.
199* `DeriveBitsJob` (defined in `src/crypto_util.h`) -- Used for
200  key and byte derivation operations.
201
202Every `CryptoJobTraits` provides two fundamental operations:
203
204* Configuration -- Processes input arguments when a
205  `CryptoJob` instance is created.
206* Implementation -- Provides the specific implementation of
207  the operation.
208
209The Configuration is typically provided by an `AdditionalConfig()`
210method, the signature of which is slightly different for each
211of the above `CryptoJob` specializations. Despite the signature
212differences, the purpose of the `AdditionalConfig()` function
213remains the same: to process input arguments and set the properties
214on the `CryptoJob`'s parameters object.
215
216The parameters object is specific to each `CryptoJob` type, and
217is stored with the `CryptoJob`. It holds all of the inputs that
218are used by the Implementation. The inputs held by the parameters
219must be threadsafe.
220
221The `AdditionalConfig()` function is always called when the
222`CryptoJob` instance is being created.
223
224The Implementation function is unique to each of the `CryptoJob`
225specializations and will either be called synchronously within
226the current thread or from within the libuv threadpool.
227
228Every `CryptoJob` instance exposes a `run()` function to the
229JavaScript layer. When called, `run()` with either dispatch the
230job to the libuv threadpool or invoke the Implementation
231function synchronously. If invoked synchronously, run() will
232return a JavaScript array. The first value in the array is
233either an `Error` or `undefined`. If the operation was successful,
234the second value in the array will contain the result of the
235operation. Typically, the result is an `ArrayBuffer`, but
236certain `CryptoJob` types can alter the output.
237
238If the `CryptoJob` is processed asynchronously, then the job
239must have an `ondone` property whose value is a function that
240is invoked when the operation is complete. This function will
241be called with two arguments. The first is either an `Error`
242or `undefined`, and the second is the result of the operation
243if successful.
244
245For `CipherJob` types, the output is always an `ArrayBuffer`.
246
247For `KeyExportJob` types, the output is either an `ArrayBuffer` or
248a JavaScript object (for JWK output format);
249
250For `KeyGenJob` types, the output is either a single KeyObject,
251or an array containing a Public/Private key pair represented
252either as a `KeyObjectHandle` object or a `Buffer`.
253
254For `DeriveBitsJob` type output is typically an `ArrayBuffer` but
255can be other values (`RandomBytesJob` for instance, fills an
256input buffer and always returns `undefined`).
257
258### Errors
259
260#### `ThrowCryptoError` and the `THROW_ERR_CRYPTO_*` macros
261
262The `ThrowCryptoError()` is a legacy utility that will throw a
263JavaScript exception containing details collected from OpenSSL
264about a failed operation. `ThrowCryptoError()` should only be
265used when necessary to report low-level OpenSSL failures.
266
267In `node_errors.h`, there are a number of `ERR_CRYPTO_*`
268macro definitions that define semantically specific errors.
269These can be called from within the C++ code as functions,
270like `THROW_ERR_CRYPTO_INVALID_IV(env)`. These methods
271should be used to throw JavaScript errors when necessary.
272
273## Crypto API patterns
274
275### Operation mode
276
277All crypto functions in Node.js operate in one of three
278modes:
279
280* Synchronous single-call
281* Asynchronous single-call
282* Stream-oriented
283
284It is often possible to perform various operations across
285multiple modes. For instance, cipher and decipher operations
286can be performed in any of the three modes.
287
288Synchronous single-call operations are always blocking.
289They perform their actions immediately.
290
291```js
292// Example synchronous single-call operation
293const a = new Uint8Array(10);
294const b = new Uint8Array(10);
295crypto.timingSafeEqual(a, b);
296```
297
298Asynchronous single-call operations generally perform a
299number of synchronous input validation steps, but then
300defer the actual crypto-operation work to the libuv threadpool.
301
302```js
303// Example asynchronous single-call operation
304const buf = new Uint8Array(10);
305crypto.randomFill(buf, (err, buf) => {
306  console.log(buf);
307});
308```
309
310For the legacy Node.js crypto API, asynchronous single-call
311operations use the traditional Node.js callback pattern, as
312illustrated in the previous `randomFill()` example. In the
313Web Crypto API (accessible via `require('node:crypto').webcrypto`),
314all asynchronous single-call operations are Promise-based.
315
316```js
317// Example Web Crypto API asynchronous single-call operation
318const { subtle } = require('node:crypto').webcrypto;
319
320subtle.generateKeys({ name: 'HMAC', length: 256 }, true, ['sign'])
321  .then((key) => {
322    console.log(key);
323  })
324  .catch((error) => {
325    console.error('an error occurred');
326  });
327```
328
329In nearly every case, asynchronous single-call operations make use
330of the libuv threadpool to perform crypto operations off the main
331event loop thread.
332
333Stream-oriented operations use an object to maintain state
334over multiple individual synchronous steps. The steps themselves
335can be performed over time.
336
337```js
338// Example stream-oriented operation
339const hash = crypto.createHash('sha256');
340let updates = 10;
341setTimeout(() => {
342  hash.update('hello world');
343  setTimeout(() => {
344    console.log(hash.digest();)
345  }, 1000);
346}, 1000);
347```
348