Skip to content
File

Blob: src/node/crypto.ts

typescript738 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4//
5import { ERR_METHOD_NOT_IMPLEMENTED } from 'node-internal:internal_errors';
6 
7export const getRandomValues = crypto.getRandomValues.bind(crypto);
8export const subtle = crypto.subtle;
9export const webcrypto = crypto;
10 
11export function timingSafeEqual(
12 a: NodeJS.ArrayBufferView,
13 b: NodeJS.ArrayBufferView
14): boolean {
15 return (subtle as any).timingSafeEqual(a, b); // eslint-disable-line
16}
17 
18import {
19 DiffieHellman,
20 DiffieHellmanGroup,
21 createDiffieHellman,
22 createDiffieHellmanGroup,
23 getDiffieHellman,
24 diffieHellman,
25 createECDH,
26 ECDH,
27} from 'node-internal:crypto_dh';
28 
29import {
30 randomBytes,
31 randomFillSync,
32 randomFill,
33 randomInt,
34 randomUUID,
35 type PrimeNum,
36 type GeneratePrimeOptions,
37 type CheckPrimeOptions,
38 generatePrime,
39 generatePrimeSync,
40 checkPrime,
41 checkPrimeSync,
42} from 'node-internal:crypto_random';
43 
44import {
45 createHash,
46 createHmac,
47 Hash,
48 type HashOptions,
49 Hmac,
50 hash,
51} from 'node-internal:crypto_hash';
52 
53import {
54 createSign,
55 createVerify,
56 sign,
57 verify,
58 Sign,
59 Verify,
60} from 'node-internal:crypto_sign';
61 
62import {
63 Cipheriv,
64 Decipheriv,
65 createCipheriv,
66 createDecipheriv,
67 publicDecrypt,
68 publicEncrypt,
69 privateDecrypt,
70 privateEncrypt,
71 getCipherInfo,
72 getCiphers,
73} from 'node-internal:crypto_cipher';
74 
75import { hkdf, hkdfSync } from 'node-internal:crypto_hkdf';
76 
77import {
78 pbkdf2,
79 pbkdf2Sync,
80 type ArrayLike,
81} from 'node-internal:crypto_pbkdf2';
82 
83import { scrypt, scryptSync } from 'node-internal:crypto_scrypt';
84 
85import {
86 KeyObject,
87 PublicKeyObject,
88 PrivateKeyObject,
89 SecretKeyObject,
90 generateKey,
91 generateKeyPair,
92 generateKeyPairSync,
93 generateKeySync,
94 createPrivateKey,
95 createPublicKey,
96 createSecretKey,
97} from 'node-internal:crypto_keys';
98 
99import { Certificate } from 'node-internal:crypto_spkac';
100 
101import { X509Certificate } from 'node-internal:crypto_x509';
102 
103export {
104 // DH
105 DiffieHellman,
106 DiffieHellmanGroup,
107 createDiffieHellman,
108 createDiffieHellmanGroup,
109 getDiffieHellman,
110 diffieHellman,
111 ECDH,
112 createECDH,
113 // Random
114 randomBytes,
115 randomFillSync,
116 randomFill,
117 randomInt,
118 randomUUID,
119 // Primes
120 type PrimeNum as primeNum,
121 type GeneratePrimeOptions as generatePrimeOptions,
122 type CheckPrimeOptions as checkPrimeOptions,
123 generatePrime,
124 generatePrimeSync,
125 checkPrime,
126 checkPrimeSync,
127 // Hash and Hmac
128 createHash,
129 createHmac,
130 Hash,
131 type HashOptions,
132 Hmac,
133 hash,
134 // Hkdf
135 hkdf,
136 hkdfSync,
137 // Pbkdf2
138 pbkdf2,
139 pbkdf2Sync,
140 // Scrypt
141 scrypt,
142 scryptSync,
143 type ArrayLike as arrayLike,
144 // Keys
145 KeyObject,
146 PublicKeyObject,
147 PrivateKeyObject,
148 SecretKeyObject,
149 generateKey,
150 generateKeyPair,
151 generateKeyPairSync,
152 generateKeySync,
153 createPrivateKey,
154 createPublicKey,
155 createSecretKey,
156 // Spkac
157 Certificate,
158 // X509
159 X509Certificate,
160 // Sign/Verify
161 createSign,
162 createVerify,
163 sign,
164 verify,
165 Sign,
166 Verify,
167 // Cipher/Decipher
168 Cipheriv,
169 Decipheriv,
170 createCipheriv,
171 createDecipheriv,
172 publicDecrypt,
173 publicEncrypt,
174 privateDecrypt,
175 privateEncrypt,
176 getCipherInfo,
177 getCiphers,
178};
179 
180export function getCurves(): string[] {
181 // Hardcoded list of supported curves. Note that prime256v1 is equivalent to secp256r1, we follow
182 // OpenSSL's and bssl's nomenclature here.
183 
184 // prettier-ignore
185 return ['secp224r1', 'prime256v1', 'secp384r1', 'secp521r1'];
186}
187 
188export function getHashes(): string[] {
189 // Hardcoded list of hashes supported in BoringSSL, node's approach looks pretty clunky. This is
190 // expected to change infrequently based of bssl's stability-focused approach.
191 
192 // prettier-ignore
193 return ['md4', 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5-sha1', 'RSA-MD5',
194 'RSA-SHA1', 'RSA-SHA224', 'RSA-SHA256', 'RSA-SHA384', 'RSA-SHA512', 'DSA-SHA',
195 'DSA-SHA1', 'ecdsa-with-SHA1'];
196}
197 
198// We do not implement the openssl secure heap.
199export function secureHeapUsed(): Record<string, unknown> {
200 return {
201 total: 0,
202 used: 0,
203 utilization: 0,
204 min: 0,
205 };
206}
207 
208// We do not allow users to set the engine used.
209export function setEngine(_1: string, _2?: number): void {
210 throw new ERR_METHOD_NOT_IMPLEMENTED('setEngine');
211}
212 
213// We do not allow users to modify the FIPS enablement.
214export function setFips(_: boolean): void {
215 throw new ERR_METHOD_NOT_IMPLEMENTED('setFips');
216}
217 
218// We always run in FIPS mode.
219export const fips = true;
220export function getFips(): boolean {
221 return fips;
222}
223 
224export const constants: Record<string, number | string> = Object.create(
225 null
226) as Record<string, number | string>;
227Object.defineProperties(constants, {
228 DH_CHECK_P_NOT_SAFE_PRIME: {
229 value: 2,
230 configurable: false,
231 writable: false,
232 },
233 DH_CHECK_P_NOT_PRIME: {
234 value: 1,
235 configurable: false,
236 writable: false,
237 },
238 DH_UNABLE_TO_CHECK_GENERATOR: {
239 value: 4,
240 configurable: false,
241 writable: false,
242 },
243 DH_NOT_SUITABLE_GENERATOR: {
244 value: 8,
245 configurable: false,
246 writable: false,
247 },
248 RSA_PKCS1_PADDING: {
249 value: 1,
250 configurable: false,
251 writable: false,
252 },
253 RSA_NO_PADDING: {
254 value: 3,
255 configurable: false,
256 writable: false,
257 },
258 RSA_PKCS1_OAEP_PADDING: {
259 value: 4,
260 configurable: false,
261 writable: false,
262 },
263 RSA_X931_PADDING: {
264 value: 5,
265 configurable: false,
266 writable: false,
267 },
268 RSA_PKCS1_PSS_PADDING: {
269 value: 6,
270 configurable: false,
271 writable: false,
272 },
273 RSA_PSS_SALTLEN_DIGEST: {
274 value: -1,
275 configurable: false,
276 writable: false,
277 },
278 RSA_PSS_SALTLEN_MAX_SIGN: {
279 value: -2,
280 configurable: false,
281 writable: false,
282 },
283 RSA_PSS_SALTLEN_AUTO: {
284 value: -2,
285 configurable: false,
286 writable: false,
287 },
288 POINT_CONVERSION_COMPRESSED: {
289 value: 2,
290 configurable: false,
291 writable: false,
292 },
293 POINT_CONVERSION_UNCOMPRESSED: {
294 value: 4,
295 configurable: false,
296 writable: false,
297 },
298 POINT_CONVERSION_HYBRID: {
299 value: 6,
300 configurable: false,
301 writable: false,
302 },
303 
304 // The following constants aren't actually used by anything in workers and
305 // are provided solely for nomimal compatibility with Node.js.
306 
307 // This one is particularly silly to define since we don't actually
308 // use openssl but the constant exists in Node.js so we'll define it
309 // also. However, we set the value to 0 instead of an actual openssl
310 // version number to hopefully avoid confusion ... we don't want code
311 // out there inspecting this and assuming openssl is present because
312 // we hard coded it to a real openssl version number.
313 OPENSSL_VERSION_NUMBER: {
314 value: 0,
315 configurable: false,
316 writable: false,
317 },
318 SSL_OP_ALL: {
319 value: 2147485776,
320 configurable: false,
321 writable: false,
322 },
323 SSL_OP_ALLOW_NO_DHE_KEX: {
324 value: 1024,
325 configurable: false,
326 writable: false,
327 },
328 SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: {
329 value: 262144,
330 configurable: false,
331 writable: false,
332 },
333 SSL_OP_CIPHER_SERVER_PREFERENCE: {
334 value: 4194304,
335 configurable: false,
336 writable: false,
337 },
338 SSL_OP_CISCO_ANYCONNECT: {
339 value: 32768,
340 configurable: false,
341 writable: false,
342 },
343 SSL_OP_COOKIE_EXCHANGE: {
344 value: 8192,
345 configurable: false,
346 writable: false,
347 },
348 SSL_OP_CRYPTOPRO_TLSEXT_BUG: {
349 value: 2147483648,
350 configurable: false,
351 writable: false,
352 },
353 SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: {
354 value: 2048,
355 configurable: false,
356 writable: false,
357 },
358 SSL_OP_LEGACY_SERVER_CONNECT: {
359 value: 4,
360 configurable: false,
361 writable: false,
362 },
363 SSL_OP_NO_COMPRESSION: {
364 value: 131072,
365 configurable: false,
366 writable: false,
367 },
368 SSL_OP_NO_ENCRYPT_THEN_MAC: {
369 value: 524288,
370 configurable: false,
371 writable: false,
372 },
373 SSL_OP_NO_QUERY_MTU: {
374 value: 4096,
375 configurable: false,
376 writable: false,
377 },
378 SSL_OP_NO_RENEGOTIATION: {
379 value: 1073741824,
380 configurable: false,
381 writable: false,
382 },
383 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: {
384 value: 65536,
385 configurable: false,
386 writable: false,
387 },
388 SSL_OP_NO_SSLv2: {
389 value: 0,
390 configurable: false,
391 writable: false,
392 },
393 SSL_OP_NO_SSLv3: {
394 value: 33554432,
395 configurable: false,
396 writable: false,
397 },
398 SSL_OP_NO_TICKET: {
399 value: 16384,
400 configurable: false,
401 writable: false,
402 },
403 SSL_OP_NO_TLSv1: {
404 value: 67108864,
405 configurable: false,
406 writable: false,
407 },
408 SSL_OP_NO_TLSv1_1: {
409 value: 268435456,
410 configurable: false,
411 writable: false,
412 },
413 SSL_OP_NO_TLSv1_2: {
414 value: 134217728,
415 configurable: false,
416 writable: false,
417 },
418 SSL_OP_NO_TLSv1_3: {
419 value: 536870912,
420 configurable: false,
421 writable: false,
422 },
423 SSL_OP_PRIORITIZE_CHACHA: {
424 value: 2097152,
425 configurable: false,
426 writable: false,
427 },
428 SSL_OP_TLS_ROLLBACK_BUG: {
429 value: 8388608,
430 configurable: false,
431 writable: false,
432 },
433 ENGINE_METHOD_RSA: {
434 value: 1,
435 configurable: false,
436 writable: false,
437 },
438 ENGINE_METHOD_DSA: {
439 value: 2,
440 configurable: false,
441 writable: false,
442 },
443 ENGINE_METHOD_DH: {
444 value: 4,
445 configurable: false,
446 writable: false,
447 },
448 ENGINE_METHOD_RAND: {
449 value: 8,
450 configurable: false,
451 writable: false,
452 },
453 ENGINE_METHOD_EC: {
454 value: 2048,
455 configurable: false,
456 writable: false,
457 },
458 ENGINE_METHOD_CIPHERS: {
459 value: 64,
460 configurable: false,
461 writable: false,
462 },
463 ENGINE_METHOD_DIGESTS: {
464 value: 128,
465 configurable: false,
466 writable: false,
467 },
468 ENGINE_METHOD_PKEY_METHS: {
469 value: 512,
470 configurable: false,
471 writable: false,
472 },
473 ENGINE_METHOD_PKEY_ASN1_METHS: {
474 value: 1024,
475 configurable: false,
476 writable: false,
477 },
478 ENGINE_METHOD_ALL: {
479 value: 65535,
480 configurable: false,
481 writable: false,
482 },
483 ENGINE_METHOD_NONE: {
484 value: 0,
485 configurable: false,
486 writable: false,
487 },
488 // The default coreCipherList in Node.js is configurable at build time.
489 // It is used as a configuration option in TLS client and server connections.
490 // We do not actually use this option in our implementation of TLS, however
491 // since we do not actually handle the TLS protocol directly in the runtime.
492 // There is no need for this value to match the defaultCoreCipherList in the
493 // official Node.js binary.
494 defaultCoreCipherList: {
495 value: '',
496 configurable: false,
497 writable: false,
498 },
499 TLS1_VERSION: {
500 value: 769,
501 configurable: false,
502 writable: false,
503 },
504 TLS1_1_VERSION: {
505 value: 770,
506 configurable: false,
507 writable: false,
508 },
509 TLS1_2_VERSION: {
510 value: 771,
511 configurable: false,
512 writable: false,
513 },
514 TLS1_3_VERSION: {
515 value: 772,
516 configurable: false,
517 writable: false,
518 },
519 // This last one is silly. It's defined on the crypto.constants object
520 // in Node.js but is not actually a constant. We also don't actually
521 // use it anywhere ourselves. Since we don't actually have a default
522 // cipher list in our implementation, we just set it to an empty string
523 // initially.
524 defaultCipherList: {
525 value: '',
526 configurable: true,
527 writable: true,
528 },
529});
530 
531// Deprecated but required for backwards compatibility.
532export const pseudoRandomBytes = randomBytes;
533 
534export const CryptoKey = globalThis.CryptoKey;
535 
536export let createCipher: (() => void) | undefined = undefined;
537export let createDecipher: (() => void) | undefined = undefined;
538export let Cipher: (() => void) | undefined = undefined;
539export let Decipher: (() => void) | undefined = undefined;
540 
541if (!Cloudflare.compatibilityFlags.remove_nodejs_compat_eol_v22) {
542 createCipher = (): void => {
543 throw new ERR_METHOD_NOT_IMPLEMENTED('createCipher');
544 };
545 createDecipher = (): void => {
546 throw new ERR_METHOD_NOT_IMPLEMENTED('createDecipher');
547 };
548 Cipher = (): void => {
549 throw new ERR_METHOD_NOT_IMPLEMENTED('Cipher');
550 };
551 Decipher = (): void => {
552 throw new ERR_METHOD_NOT_IMPLEMENTED('Decipher');
553 };
554}
555export default {
556 constants,
557 // DH
558 DiffieHellman,
559 DiffieHellmanGroup,
560 createDiffieHellman,
561 createDiffieHellmanGroup,
562 getDiffieHellman,
563 ECDH,
564 createECDH,
565 // Keys,
566 KeyObject,
567 PublicKeyObject,
568 PrivateKeyObject,
569 SecretKeyObject,
570 generateKey,
571 generateKeyPair,
572 generateKeyPairSync,
573 generateKeySync,
574 createPrivateKey,
575 createPublicKey,
576 createSecretKey,
577 // Random
578 getRandomValues,
579 pseudoRandomBytes,
580 randomBytes,
581 randomFillSync,
582 randomFill,
583 randomInt,
584 randomUUID,
585 generatePrime,
586 generatePrimeSync,
587 checkPrime,
588 checkPrimeSync,
589 // Hash and Hmac
590 Hash,
591 Hmac,
592 createHash,
593 createHmac,
594 getHashes,
595 hash,
596 // Hkdf
597 hkdf,
598 hkdfSync,
599 // Pbkdf2
600 pbkdf2,
601 pbkdf2Sync,
602 // Scrypt
603 scrypt,
604 scryptSync,
605 // Misc
606 getCiphers,
607 getCurves,
608 secureHeapUsed,
609 setEngine,
610 timingSafeEqual,
611 // Fips
612 getFips,
613 setFips,
614 get fips(): boolean {
615 return getFips();
616 },
617 set fips(_: boolean) {
618 setFips(_);
619 },
620 // WebCrypto
621 subtle,
622 webcrypto,
623 // Spkac
624 Certificate,
625 // X509
626 X509Certificate,
627 // Sign/Verify
628 createSign,
629 createVerify,
630 sign,
631 verify,
632 Sign,
633 Verify,
634 // Cipher/Decipher
635 Cipheriv,
636 Decipheriv,
637 createCipheriv,
638 createDecipheriv,
639 publicDecrypt,
640 publicEncrypt,
641 privateDecrypt,
642 privateEncrypt,
643 getCipherInfo,
644 CryptoKey,
645 
646 // EOL
647 createCipher,
648 createDecipher,
649 Cipher,
650 Decipher,
651};
652 
653// Classes
654// * [x] crypto.Certificate
655// * [x] crypto.Cipher
656// * [x] crypto.Decipher
657// * [x] crypto.DiffieHellman
658// * [x] crypto.DiffieHellmanGroup
659// * [x] crypto.ECDH
660// * [x] crypto.Hash
661// * [x] crypto.Hmac
662// * [x] crypto.KeyObject
663// * [x] crypto.Sign
664// * [x] crypto.Verify
665// * [x] crypto.X509Certificate
666// * [x] crypto.constants
667// * [ ] crypto.DEFAULT_ENCODING
668// * Primes
669// * [x] crypto.checkPrime(candidate[, options], callback)
670// * [x] crypto.checkPrimeSync(candidate[, options])
671// * [x] crypto.generatePrime(size[, options[, callback]])
672// * [x] crypto.generatePrimeSync(size[, options])
673// * Ciphers
674// * [x] crypto.createCipher(algorithm, password[, options])
675// * [x] crypto.createCipheriv(algorithm, key, iv[, options])
676// * [x] crypto.createDecipher(algorithm, password[, options])
677// * [x] crypto.createDecipheriv(algorithm, key, iv[, options])
678// * [x] crypto.privateDecrypt(privateKey, buffer)
679// * [x] crypto.privateEncrypt(privateKey, buffer)
680// * [x] crypto.publicDecrypt(key, buffer)
681// * [x] crypto.publicEncrypt(key, buffer)
682// * [x] crypto.Decipher
683// * [x] crypto.Cipher
684// * DiffieHellman
685// * [x] crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding])
686// * [x] crypto.createDiffieHellman(primeLength[, generator])
687// * [x] crypto.createDiffieHellmanGroup(name)
688// * [x] crypto.createECDH(curveName)
689// * [x] crypto.diffieHellman(options)
690// * [x] crypto.getDiffieHellman(groupName)
691// * Hash
692// * [x] crypto.createHash(algorithm[, options])
693// * [x] crypto.createHmac(algorithm, key[, options])
694// * [x] crypto.getHashes()
695// * [x] crypto.hash()
696// * Keys, not implemented yet. Calling the following APIs will throw a ERR_METHOD_NOT_IMPLEMENTED
697// * [x] crypto.createPrivateKey(key)
698// * [x] crypto.createPublicKey(key)
699// * [x] crypto.createSecretKey(key[, encoding])
700// * [x] crypto.generateKey(type, options, callback)
701// * [x] crypto.generateKeyPair(type, options, callback)
702// * [x] crypto.generateKeyPairSync(type, options)
703// * [x] crypto.generateKeySync(type, options)
704// * Sign/Verify
705// * [x] crypto.createSign(algorithm[, options])
706// * [x] crypto.createVerify(algorithm[, options])
707// * [x] crypto.sign(algorithm, data, key[, callback])
708// * [x] crypto.verify(algorithm, data, key, signature[, callback])
709// * Misc
710// * [x] crypto.getCipherInfo(nameOrNid[, options])
711// * [x] crypto.getCiphers()
712// * [x] crypto.getCurves()
713// * [x] crypto.secureHeapUsed()
714// * [x] crypto.setEngine(engine[, flags])
715// * [x] crypto.timingSafeEqual(a, b)
716// * Fips
717// * [x] crypto.getFips()
718// * [x] crypto.fips
719// * [x] crypto.setFips(bool)
720// * Random
721// * [x] crypto.getRandomValues(typedArray)
722// * [x] crypto.randomBytes(size[, callback])
723// * [x] crypto.randomFillSync(buffer[, offset][, size])
724// * [x] crypto.randomFill(buffer[, offset][, size], callback)
725// * [x] crypto.randomInt([min, ]max[, callback])
726// * [x] crypto.randomUUID([options])
727// * Key Derivation
728// * [x] crypto.hkdf(digest, ikm, salt, info, keylen, callback)
729// * [x] crypto.hkdfSync(digest, ikm, salt, info, keylen)
730// * [x] crypto.pbkdf2(password, salt, iterations, keylen, digest, callback)
731// * [x] crypto.pbkdf2Sync(password, salt, iterations, keylen, digest)
732// * [x] crypto.scrypt(password, salt, keylen[, options], callback)
733// * [x] crypto.scryptSync(password, salt, keylen[, options])
734// * WebCrypto
735// * [x] crypto.subtle
736// * [x] crypto.webcrypto
737// * [x] crypto.CryptoKey