1 // Note: In 0.8 and before, crypto functions all defaulted to using
2 // binary-encoded strings rather than buffers.
6 exports.DEFAULT_ENCODING = 'buffer';
9 var binding = process.binding('crypto');
10 var randomBytes = binding.randomBytes;
11 var getCiphers = binding.getCiphers;
12 var getHashes = binding.getHashes;
13 var getCurves = binding.getCurves;
15 throw new Error('node.js not compiled with openssl crypto support.');
18 const Buffer = require('buffer').Buffer;
19 const constants = require('constants');
20 const stream = require('stream');
21 const util = require('util');
22 const internalUtil = require('internal/util');
23 const LazyTransform = require('internal/streams/lazy_transform');
25 const DH_GENERATOR = 2;
27 // This is here because many functions accepted binary strings without
28 // any explicit encoding in older versions of node, and we don't want
29 // to break them unnecessarily.
30 function toBuf(str, encoding) {
31 encoding = encoding || 'binary';
32 if (typeof str === 'string') {
33 if (encoding === 'buffer')
35 str = new Buffer(str, encoding);
39 exports._toBuf = toBuf;
42 const assert = require('assert');
43 const StringDecoder = require('string_decoder').StringDecoder;
46 exports.createHash = exports.Hash = Hash;
47 function Hash(algorithm, options) {
48 if (!(this instanceof Hash))
49 return new Hash(algorithm, options);
50 this._handle = new binding.Hash(algorithm);
51 LazyTransform.call(this, options);
54 util.inherits(Hash, LazyTransform);
56 Hash.prototype._transform = function(chunk, encoding, callback) {
57 this._handle.update(chunk, encoding);
61 Hash.prototype._flush = function(callback) {
62 this.push(this._handle.digest());
66 Hash.prototype.update = function(data, encoding) {
67 encoding = encoding || exports.DEFAULT_ENCODING;
68 if (encoding === 'buffer' && typeof data === 'string')
70 this._handle.update(data, encoding);
75 Hash.prototype.digest = function(outputEncoding) {
76 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
77 return this._handle.digest(outputEncoding);
81 exports.createHmac = exports.Hmac = Hmac;
83 function Hmac(hmac, key, options) {
84 if (!(this instanceof Hmac))
85 return new Hmac(hmac, key, options);
86 this._handle = new binding.Hmac();
87 this._handle.init(hmac, toBuf(key));
88 LazyTransform.call(this, options);
91 util.inherits(Hmac, LazyTransform);
93 Hmac.prototype.update = Hash.prototype.update;
94 Hmac.prototype.digest = Hash.prototype.digest;
95 Hmac.prototype._flush = Hash.prototype._flush;
96 Hmac.prototype._transform = Hash.prototype._transform;
99 function getDecoder(decoder, encoding) {
100 if (encoding === 'utf-8') encoding = 'utf8'; // Normalize encoding.
101 decoder = decoder || new StringDecoder(encoding);
102 assert(decoder.encoding === encoding, 'Cannot change encoding');
107 exports.createCipher = exports.Cipher = Cipher;
108 function Cipher(cipher, password, options) {
109 if (!(this instanceof Cipher))
110 return new Cipher(cipher, password, options);
111 this._handle = new binding.CipherBase(true);
113 this._handle.init(cipher, toBuf(password));
114 this._decoder = null;
116 LazyTransform.call(this, options);
119 util.inherits(Cipher, LazyTransform);
121 Cipher.prototype._transform = function(chunk, encoding, callback) {
122 this.push(this._handle.update(chunk, encoding));
126 Cipher.prototype._flush = function(callback) {
128 this.push(this._handle.final());
136 Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
137 inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
138 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
140 var ret = this._handle.update(data, inputEncoding);
142 if (outputEncoding && outputEncoding !== 'buffer') {
143 this._decoder = getDecoder(this._decoder, outputEncoding);
144 ret = this._decoder.write(ret);
151 Cipher.prototype.final = function(outputEncoding) {
152 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
153 var ret = this._handle.final();
155 if (outputEncoding && outputEncoding !== 'buffer') {
156 this._decoder = getDecoder(this._decoder, outputEncoding);
157 ret = this._decoder.end(ret);
164 Cipher.prototype.setAutoPadding = function(ap) {
165 this._handle.setAutoPadding(ap);
169 Cipher.prototype.getAuthTag = function() {
170 return this._handle.getAuthTag();
174 Cipher.prototype.setAuthTag = function(tagbuf) {
175 this._handle.setAuthTag(tagbuf);
178 Cipher.prototype.setAAD = function(aadbuf) {
179 this._handle.setAAD(aadbuf);
182 exports.createCipheriv = exports.Cipheriv = Cipheriv;
183 function Cipheriv(cipher, key, iv, options) {
184 if (!(this instanceof Cipheriv))
185 return new Cipheriv(cipher, key, iv, options);
186 this._handle = new binding.CipherBase(true);
187 this._handle.initiv(cipher, toBuf(key), toBuf(iv));
188 this._decoder = null;
190 LazyTransform.call(this, options);
193 util.inherits(Cipheriv, LazyTransform);
195 Cipheriv.prototype._transform = Cipher.prototype._transform;
196 Cipheriv.prototype._flush = Cipher.prototype._flush;
197 Cipheriv.prototype.update = Cipher.prototype.update;
198 Cipheriv.prototype.final = Cipher.prototype.final;
199 Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
200 Cipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag;
201 Cipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag;
202 Cipheriv.prototype.setAAD = Cipher.prototype.setAAD;
204 exports.createDecipher = exports.Decipher = Decipher;
205 function Decipher(cipher, password, options) {
206 if (!(this instanceof Decipher))
207 return new Decipher(cipher, password, options);
209 this._handle = new binding.CipherBase(false);
210 this._handle.init(cipher, toBuf(password));
211 this._decoder = null;
213 LazyTransform.call(this, options);
216 util.inherits(Decipher, LazyTransform);
218 Decipher.prototype._transform = Cipher.prototype._transform;
219 Decipher.prototype._flush = Cipher.prototype._flush;
220 Decipher.prototype.update = Cipher.prototype.update;
221 Decipher.prototype.final = Cipher.prototype.final;
222 Decipher.prototype.finaltol = Cipher.prototype.final;
223 Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
224 Decipher.prototype.getAuthTag = Cipher.prototype.getAuthTag;
225 Decipher.prototype.setAuthTag = Cipher.prototype.setAuthTag;
226 Decipher.prototype.setAAD = Cipher.prototype.setAAD;
229 exports.createDecipheriv = exports.Decipheriv = Decipheriv;
230 function Decipheriv(cipher, key, iv, options) {
231 if (!(this instanceof Decipheriv))
232 return new Decipheriv(cipher, key, iv, options);
234 this._handle = new binding.CipherBase(false);
235 this._handle.initiv(cipher, toBuf(key), toBuf(iv));
236 this._decoder = null;
238 LazyTransform.call(this, options);
241 util.inherits(Decipheriv, LazyTransform);
243 Decipheriv.prototype._transform = Cipher.prototype._transform;
244 Decipheriv.prototype._flush = Cipher.prototype._flush;
245 Decipheriv.prototype.update = Cipher.prototype.update;
246 Decipheriv.prototype.final = Cipher.prototype.final;
247 Decipheriv.prototype.finaltol = Cipher.prototype.final;
248 Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
249 Decipheriv.prototype.getAuthTag = Cipher.prototype.getAuthTag;
250 Decipheriv.prototype.setAuthTag = Cipher.prototype.setAuthTag;
251 Decipheriv.prototype.setAAD = Cipher.prototype.setAAD;
254 exports.createSign = exports.Sign = Sign;
255 function Sign(algorithm, options) {
256 if (!(this instanceof Sign))
257 return new Sign(algorithm, options);
258 this._handle = new binding.Sign();
259 this._handle.init(algorithm);
261 stream.Writable.call(this, options);
264 util.inherits(Sign, stream.Writable);
266 Sign.prototype._write = function(chunk, encoding, callback) {
267 this._handle.update(chunk, encoding);
271 Sign.prototype.update = Hash.prototype.update;
273 Sign.prototype.sign = function(options, encoding) {
275 throw new Error('No key provided to sign');
277 var key = options.key || options;
278 var passphrase = options.passphrase || null;
279 var ret = this._handle.sign(toBuf(key), null, passphrase);
281 encoding = encoding || exports.DEFAULT_ENCODING;
282 if (encoding && encoding !== 'buffer')
283 ret = ret.toString(encoding);
289 exports.createVerify = exports.Verify = Verify;
290 function Verify(algorithm, options) {
291 if (!(this instanceof Verify))
292 return new Verify(algorithm, options);
294 this._handle = new binding.Verify();
295 this._handle.init(algorithm);
297 stream.Writable.call(this, options);
300 util.inherits(Verify, stream.Writable);
302 Verify.prototype._write = Sign.prototype._write;
303 Verify.prototype.update = Sign.prototype.update;
305 Verify.prototype.verify = function(object, signature, sigEncoding) {
306 sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
307 return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding));
310 function rsaPublic(method, defaultPadding) {
311 return function(options, buffer) {
312 var key = options.key || options;
313 var padding = options.padding || defaultPadding;
314 var passphrase = options.passphrase || null;
315 return method(toBuf(key), buffer, padding, passphrase);
319 function rsaPrivate(method, defaultPadding) {
320 return function(options, buffer) {
321 var key = options.key || options;
322 var passphrase = options.passphrase || null;
323 var padding = options.padding || defaultPadding;
324 return method(toBuf(key), buffer, padding, passphrase);
328 exports.publicEncrypt = rsaPublic(binding.publicEncrypt,
329 constants.RSA_PKCS1_OAEP_PADDING);
330 exports.publicDecrypt = rsaPublic(binding.publicDecrypt,
331 constants.RSA_PKCS1_PADDING);
332 exports.privateEncrypt = rsaPrivate(binding.privateEncrypt,
333 constants.RSA_PKCS1_PADDING);
334 exports.privateDecrypt = rsaPrivate(binding.privateDecrypt,
335 constants.RSA_PKCS1_OAEP_PADDING);
338 exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
340 function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
341 if (!(this instanceof DiffieHellman))
342 return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding);
344 if (!(sizeOrKey instanceof Buffer) &&
345 typeof sizeOrKey !== 'number' &&
346 typeof sizeOrKey !== 'string')
347 throw new TypeError('First argument should be number, string or Buffer');
350 if (typeof keyEncoding !== 'string' ||
351 (!Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer')) {
352 genEncoding = generator;
353 generator = keyEncoding;
358 keyEncoding = keyEncoding || exports.DEFAULT_ENCODING;
359 genEncoding = genEncoding || exports.DEFAULT_ENCODING;
361 if (typeof sizeOrKey !== 'number')
362 sizeOrKey = toBuf(sizeOrKey, keyEncoding);
365 generator = DH_GENERATOR;
366 else if (typeof generator !== 'number')
367 generator = toBuf(generator, genEncoding);
369 this._handle = new binding.DiffieHellman(sizeOrKey, generator);
370 Object.defineProperty(this, 'verifyError', {
372 value: this._handle.verifyError,
378 exports.DiffieHellmanGroup =
379 exports.createDiffieHellmanGroup =
380 exports.getDiffieHellman = DiffieHellmanGroup;
382 function DiffieHellmanGroup(name) {
383 if (!(this instanceof DiffieHellmanGroup))
384 return new DiffieHellmanGroup(name);
385 this._handle = new binding.DiffieHellmanGroup(name);
386 Object.defineProperty(this, 'verifyError', {
388 value: this._handle.verifyError,
394 DiffieHellmanGroup.prototype.generateKeys =
395 DiffieHellman.prototype.generateKeys =
398 function dhGenerateKeys(encoding) {
399 var keys = this._handle.generateKeys();
400 encoding = encoding || exports.DEFAULT_ENCODING;
401 if (encoding && encoding !== 'buffer')
402 keys = keys.toString(encoding);
407 DiffieHellmanGroup.prototype.computeSecret =
408 DiffieHellman.prototype.computeSecret =
411 function dhComputeSecret(key, inEnc, outEnc) {
412 inEnc = inEnc || exports.DEFAULT_ENCODING;
413 outEnc = outEnc || exports.DEFAULT_ENCODING;
414 var ret = this._handle.computeSecret(toBuf(key, inEnc));
415 if (outEnc && outEnc !== 'buffer')
416 ret = ret.toString(outEnc);
421 DiffieHellmanGroup.prototype.getPrime =
422 DiffieHellman.prototype.getPrime =
425 function dhGetPrime(encoding) {
426 var prime = this._handle.getPrime();
427 encoding = encoding || exports.DEFAULT_ENCODING;
428 if (encoding && encoding !== 'buffer')
429 prime = prime.toString(encoding);
434 DiffieHellmanGroup.prototype.getGenerator =
435 DiffieHellman.prototype.getGenerator =
438 function dhGetGenerator(encoding) {
439 var generator = this._handle.getGenerator();
440 encoding = encoding || exports.DEFAULT_ENCODING;
441 if (encoding && encoding !== 'buffer')
442 generator = generator.toString(encoding);
447 DiffieHellmanGroup.prototype.getPublicKey =
448 DiffieHellman.prototype.getPublicKey =
451 function dhGetPublicKey(encoding) {
452 var key = this._handle.getPublicKey();
453 encoding = encoding || exports.DEFAULT_ENCODING;
454 if (encoding && encoding !== 'buffer')
455 key = key.toString(encoding);
460 DiffieHellmanGroup.prototype.getPrivateKey =
461 DiffieHellman.prototype.getPrivateKey =
464 function dhGetPrivateKey(encoding) {
465 var key = this._handle.getPrivateKey();
466 encoding = encoding || exports.DEFAULT_ENCODING;
467 if (encoding && encoding !== 'buffer')
468 key = key.toString(encoding);
473 DiffieHellman.prototype.setPublicKey = function(key, encoding) {
474 encoding = encoding || exports.DEFAULT_ENCODING;
475 this._handle.setPublicKey(toBuf(key, encoding));
480 DiffieHellman.prototype.setPrivateKey = function(key, encoding) {
481 encoding = encoding || exports.DEFAULT_ENCODING;
482 this._handle.setPrivateKey(toBuf(key, encoding));
487 function ECDH(curve) {
488 if (typeof curve !== 'string')
489 throw new TypeError('curve should be a string');
491 this._handle = new binding.ECDH(curve);
494 exports.createECDH = function createECDH(curve) {
495 return new ECDH(curve);
498 ECDH.prototype.computeSecret = DiffieHellman.prototype.computeSecret;
499 ECDH.prototype.setPrivateKey = DiffieHellman.prototype.setPrivateKey;
500 ECDH.prototype.setPublicKey = DiffieHellman.prototype.setPublicKey;
501 ECDH.prototype.getPrivateKey = DiffieHellman.prototype.getPrivateKey;
503 ECDH.prototype.generateKeys = function generateKeys(encoding, format) {
504 this._handle.generateKeys();
506 return this.getPublicKey(encoding, format);
509 ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) {
512 if (typeof format === 'number')
514 if (format === 'compressed')
515 f = constants.POINT_CONVERSION_COMPRESSED;
516 else if (format === 'hybrid')
517 f = constants.POINT_CONVERSION_HYBRID;
519 else if (format === 'uncompressed')
520 f = constants.POINT_CONVERSION_UNCOMPRESSED;
522 throw new TypeError('Bad format: ' + format);
524 f = constants.POINT_CONVERSION_UNCOMPRESSED;
526 var key = this._handle.getPublicKey(f);
527 encoding = encoding || exports.DEFAULT_ENCODING;
528 if (encoding && encoding !== 'buffer')
529 key = key.toString(encoding);
534 exports.pbkdf2 = function(password,
540 if (typeof digest === 'function') {
545 if (typeof callback !== 'function')
546 throw new Error('No callback provided to pbkdf2');
548 return pbkdf2(password, salt, iterations, keylen, digest, callback);
552 exports.pbkdf2Sync = function(password, salt, iterations, keylen, digest) {
553 return pbkdf2(password, salt, iterations, keylen, digest);
557 function pbkdf2(password, salt, iterations, keylen, digest, callback) {
558 password = toBuf(password);
561 if (exports.DEFAULT_ENCODING === 'buffer')
562 return binding.PBKDF2(password, salt, iterations, keylen, digest, callback);
564 // at this point, we need to handle encodings.
565 var encoding = exports.DEFAULT_ENCODING;
567 var next = function(er, ret) {
569 ret = ret.toString(encoding);
572 binding.PBKDF2(password, salt, iterations, keylen, digest, next);
574 var ret = binding.PBKDF2(password, salt, iterations, keylen, digest);
575 return ret.toString(encoding);
580 exports.Certificate = Certificate;
582 function Certificate() {
583 if (!(this instanceof Certificate))
584 return new Certificate();
586 this._handle = new binding.Certificate();
590 Certificate.prototype.verifySpkac = function(object) {
591 return this._handle.verifySpkac(object);
595 Certificate.prototype.exportPublicKey = function(object, encoding) {
596 return this._handle.exportPublicKey(toBuf(object, encoding));
600 Certificate.prototype.exportChallenge = function(object, encoding) {
601 return this._handle.exportChallenge(toBuf(object, encoding));
605 exports.setEngine = function setEngine(id, flags) {
606 if (typeof id !== 'string')
607 throw new TypeError('id should be a string');
609 if (flags && typeof flags !== 'number')
610 throw new TypeError('flags should be a number, if present');
613 // Use provided engine for everything by default
615 flags = constants.ENGINE_METHOD_ALL;
617 return binding.setEngine(id, flags);
620 exports.randomBytes = exports.pseudoRandomBytes = randomBytes;
622 exports.rng = exports.prng = randomBytes;
624 exports.getCiphers = function() {
625 return filterDuplicates(getCiphers());
629 exports.getHashes = function() {
630 return filterDuplicates(getHashes());
634 exports.getCurves = function() {
635 return filterDuplicates(getCurves());
639 function filterDuplicates(names) {
640 // Drop all-caps names in favor of their lowercase aliases,
641 // for example, 'sha1' instead of 'SHA1'.
643 names.forEach(function(name) {
645 if (/^[0-9A-Z\-]+$/.test(key)) key = key.toLowerCase();
646 if (!ctx.hasOwnProperty(key) || ctx[key] < name)
650 return Object.getOwnPropertyNames(ctx).map(function(key) {
656 exports.__defineGetter__('createCredentials',
657 internalUtil.deprecate(function() {
658 return require('tls').createSecureContext;
659 }, 'crypto.createCredentials is deprecated. ' +
660 'Use tls.createSecureContext instead.'));
662 exports.__defineGetter__('Credentials', internalUtil.deprecate(function() {
663 return require('tls').SecureContext;
664 }, 'crypto.Credentials is deprecated. ' +
665 'Use tls.createSecureContext instead.'));