1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22// Note: In 0.8 and before, crypto functions all defaulted to using 23// binary-encoded strings rather than buffers. 24 25'use strict'; 26 27const { 28 ObjectDefineProperty, 29 ObjectDefineProperties, 30} = primordials; 31 32const { 33 assertCrypto, 34 deprecate, 35} = require('internal/util'); 36assertCrypto(); 37 38const { 39 ERR_CRYPTO_FIPS_FORCED, 40} = require('internal/errors').codes; 41const constants = internalBinding('constants').crypto; 42const { getOptionValue } = require('internal/options'); 43const { 44 getFipsCrypto, 45 setFipsCrypto, 46 timingSafeEqual, 47} = internalBinding('crypto'); 48const { 49 checkPrime, 50 checkPrimeSync, 51 generatePrime, 52 generatePrimeSync, 53 randomBytes, 54 randomFill, 55 randomFillSync, 56 randomInt, 57 randomUUID, 58} = require('internal/crypto/random'); 59const { 60 pbkdf2, 61 pbkdf2Sync, 62} = require('internal/crypto/pbkdf2'); 63const { 64 scrypt, 65 scryptSync, 66} = require('internal/crypto/scrypt'); 67const { 68 hkdf, 69 hkdfSync, 70} = require('internal/crypto/hkdf'); 71const { 72 generateKeyPair, 73 generateKeyPairSync, 74 generateKey, 75 generateKeySync, 76} = require('internal/crypto/keygen'); 77const { 78 createSecretKey, 79 createPublicKey, 80 createPrivateKey, 81 KeyObject, 82} = require('internal/crypto/keys'); 83const { 84 DiffieHellman, 85 DiffieHellmanGroup, 86 ECDH, 87 diffieHellman, 88} = require('internal/crypto/diffiehellman'); 89const { 90 Cipher, 91 Cipheriv, 92 Decipher, 93 Decipheriv, 94 privateDecrypt, 95 privateEncrypt, 96 publicDecrypt, 97 publicEncrypt, 98 getCipherInfo, 99} = require('internal/crypto/cipher'); 100const { 101 Sign, 102 signOneShot, 103 Verify, 104 verifyOneShot, 105} = require('internal/crypto/sig'); 106const { 107 Hash, 108 Hmac, 109} = require('internal/crypto/hash'); 110const { 111 X509Certificate, 112} = require('internal/crypto/x509'); 113const { 114 getCiphers, 115 getCurves, 116 getDefaultEncoding, 117 getHashes, 118 setDefaultEncoding, 119 setEngine, 120 secureHeapUsed, 121} = require('internal/crypto/util'); 122const Certificate = require('internal/crypto/certificate'); 123 124let webcrypto; 125function lazyWebCrypto() { 126 webcrypto ??= require('internal/crypto/webcrypto'); 127 return webcrypto; 128} 129 130// These helper functions are needed because the constructors can 131// use new, in which case V8 cannot inline the recursive constructor call 132function createHash(algorithm, options) { 133 return new Hash(algorithm, options); 134} 135 136function createCipher(cipher, password, options) { 137 return new Cipher(cipher, password, options); 138} 139 140function createCipheriv(cipher, key, iv, options) { 141 return new Cipheriv(cipher, key, iv, options); 142} 143 144function createDecipher(cipher, password, options) { 145 return new Decipher(cipher, password, options); 146} 147 148function createDecipheriv(cipher, key, iv, options) { 149 return new Decipheriv(cipher, key, iv, options); 150} 151 152function createDiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) { 153 return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding); 154} 155 156function createDiffieHellmanGroup(name) { 157 return new DiffieHellmanGroup(name); 158} 159 160function createECDH(curve) { 161 return new ECDH(curve); 162} 163 164function createHmac(hmac, key, options) { 165 return new Hmac(hmac, key, options); 166} 167 168function createSign(algorithm, options) { 169 return new Sign(algorithm, options); 170} 171 172function createVerify(algorithm, options) { 173 return new Verify(algorithm, options); 174} 175 176module.exports = { 177 // Methods 178 checkPrime, 179 checkPrimeSync, 180 createCipheriv, 181 createDecipheriv, 182 createDiffieHellman, 183 createDiffieHellmanGroup, 184 createECDH, 185 createHash, 186 createHmac, 187 createPrivateKey, 188 createPublicKey, 189 createSecretKey, 190 createSign, 191 createVerify, 192 diffieHellman, 193 generatePrime, 194 generatePrimeSync, 195 getCiphers, 196 getCipherInfo, 197 getCurves, 198 getDiffieHellman: createDiffieHellmanGroup, 199 getHashes, 200 hkdf, 201 hkdfSync, 202 pbkdf2, 203 pbkdf2Sync, 204 generateKeyPair, 205 generateKeyPairSync, 206 generateKey, 207 generateKeySync, 208 privateDecrypt, 209 privateEncrypt, 210 publicDecrypt, 211 publicEncrypt, 212 randomBytes, 213 randomFill, 214 randomFillSync, 215 randomInt, 216 randomUUID, 217 scrypt, 218 scryptSync, 219 sign: signOneShot, 220 setEngine, 221 timingSafeEqual, 222 getFips, 223 setFips, 224 verify: verifyOneShot, 225 226 // Classes 227 Certificate, 228 Cipher, 229 Cipheriv, 230 Decipher, 231 Decipheriv, 232 DiffieHellman, 233 DiffieHellmanGroup, 234 ECDH, 235 Hash, 236 Hmac, 237 KeyObject, 238 Sign, 239 Verify, 240 X509Certificate, 241 secureHeapUsed, 242}; 243 244function getFips() { 245 return getOptionValue('--force-fips') ? 1 : getFipsCrypto(); 246} 247 248function setFips(val) { 249 if (getOptionValue('--force-fips')) { 250 if (val) return; 251 throw new ERR_CRYPTO_FIPS_FORCED(); 252 } else { 253 setFipsCrypto(val); 254 } 255} 256 257function getRandomValues(array) { 258 return lazyWebCrypto().crypto.getRandomValues(array); 259} 260 261ObjectDefineProperty(constants, 'defaultCipherList', { 262 __proto__: null, 263 get() { 264 const value = getOptionValue('--tls-cipher-list'); 265 ObjectDefineProperty(this, 'defaultCipherList', { 266 __proto__: null, 267 writable: true, 268 configurable: true, 269 enumerable: true, 270 value, 271 }); 272 return value; 273 }, 274 set(val) { 275 ObjectDefineProperty(this, 'defaultCipherList', { 276 __proto__: null, 277 writable: true, 278 configurable: true, 279 enumerable: true, 280 value: val, 281 }); 282 }, 283 configurable: true, 284 enumerable: true, 285}); 286 287function getRandomBytesAlias(key) { 288 return { 289 enumerable: false, 290 configurable: true, 291 get() { 292 let value; 293 if (getOptionValue('--pending-deprecation')) { 294 value = deprecate( 295 randomBytes, 296 `crypto.${key} is deprecated.`, 297 'DEP0115'); 298 } else { 299 value = randomBytes; 300 } 301 ObjectDefineProperty( 302 this, 303 key, 304 { 305 __proto__: null, 306 enumerable: false, 307 configurable: true, 308 writable: true, 309 value: value, 310 }, 311 ); 312 return value; 313 }, 314 set(value) { 315 ObjectDefineProperty( 316 this, 317 key, 318 { 319 __proto__: null, 320 enumerable: true, 321 configurable: true, 322 writable: true, 323 value, 324 }, 325 ); 326 }, 327 }; 328} 329 330ObjectDefineProperties(module.exports, { 331 createCipher: { 332 __proto__: null, 333 enumerable: false, 334 value: deprecate(createCipher, 335 'crypto.createCipher is deprecated.', 'DEP0106'), 336 }, 337 createDecipher: { 338 __proto__: null, 339 enumerable: false, 340 value: deprecate(createDecipher, 341 'crypto.createDecipher is deprecated.', 'DEP0106'), 342 }, 343 // crypto.fips is deprecated. DEP0093. Use crypto.getFips()/crypto.setFips() 344 fips: { 345 __proto__: null, 346 get: getFips, 347 set: setFips, 348 }, 349 DEFAULT_ENCODING: { 350 __proto__: null, 351 enumerable: false, 352 configurable: true, 353 get: deprecate(getDefaultEncoding, 354 'crypto.DEFAULT_ENCODING is deprecated.', 'DEP0091'), 355 set: deprecate(setDefaultEncoding, 356 'crypto.DEFAULT_ENCODING is deprecated.', 'DEP0091'), 357 }, 358 constants: { 359 __proto__: null, 360 configurable: false, 361 enumerable: true, 362 value: constants, 363 }, 364 365 webcrypto: { 366 __proto__: null, 367 configurable: false, 368 enumerable: true, 369 get() { return lazyWebCrypto().crypto; }, 370 set: undefined, 371 }, 372 373 subtle: { 374 __proto__: null, 375 configurable: false, 376 enumerable: true, 377 get() { return lazyWebCrypto().crypto.subtle; }, 378 set: undefined, 379 }, 380 381 getRandomValues: { 382 __proto__: null, 383 configurable: false, 384 enumerable: true, 385 get: () => getRandomValues, 386 set: undefined, 387 }, 388 389 // Aliases for randomBytes are deprecated. 390 // The ecosystem needs those to exist for backwards compatibility. 391 prng: getRandomBytesAlias('prng'), 392 pseudoRandomBytes: getRandomBytesAlias('pseudoRandomBytes'), 393 rng: getRandomBytesAlias('rng'), 394}); 395