1 // Copyright Joyent, Inc. and other Node contributors.
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:
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
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.
22 // Note: In 0.8 and before, crypto functions all defaulted to using
23 // binary-encoded strings rather than buffers.
25 exports.DEFAULT_ENCODING = 'buffer';
28 var binding = process.binding('crypto');
29 var randomBytes = binding.randomBytes;
30 var pseudoRandomBytes = binding.pseudoRandomBytes;
31 var getCiphers = binding.getCiphers;
32 var getHashes = binding.getHashes;
34 throw new Error('node.js not compiled with openssl crypto support.');
37 var constants = require('constants');
38 var stream = require('stream');
39 var util = require('util');
43 // This is here because many functions accepted binary strings without
44 // any explicit encoding in older versions of node, and we don't want
45 // to break them unnecessarily.
46 function toBuf(str, encoding) {
47 encoding = encoding || 'binary';
48 if (util.isString(str)) {
49 if (encoding === 'buffer')
51 str = new Buffer(str, encoding);
55 exports._toBuf = toBuf;
58 var assert = require('assert');
59 var StringDecoder = require('string_decoder').StringDecoder;
62 function LazyTransform(options) {
63 this._options = options;
65 util.inherits(LazyTransform, stream.Transform);
71 ].forEach(function(prop, i, props) {
72 Object.defineProperty(LazyTransform.prototype, prop, {
74 stream.Transform.call(this, this._options);
75 this._writableState.decodeStrings = false;
76 this._writableState.defaultEncoding = 'binary';
80 Object.defineProperty(this, prop, {
93 exports.createHash = exports.Hash = Hash;
94 function Hash(algorithm, options) {
95 if (!(this instanceof Hash))
96 return new Hash(algorithm, options);
97 this._handle = new binding.Hash(algorithm);
98 LazyTransform.call(this, options);
101 util.inherits(Hash, LazyTransform);
103 Hash.prototype._transform = function(chunk, encoding, callback) {
104 this._handle.update(chunk, encoding);
108 Hash.prototype._flush = function(callback) {
109 var encoding = this._readableState.encoding || 'buffer';
110 this.push(this._handle.digest(encoding), encoding);
114 Hash.prototype.update = function(data, encoding) {
115 encoding = encoding || exports.DEFAULT_ENCODING;
116 if (encoding === 'buffer' && util.isString(data))
118 this._handle.update(data, encoding);
123 Hash.prototype.digest = function(outputEncoding) {
124 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
125 return this._handle.digest(outputEncoding);
129 exports.createHmac = exports.Hmac = Hmac;
131 function Hmac(hmac, key, options) {
132 if (!(this instanceof Hmac))
133 return new Hmac(hmac, key, options);
134 this._handle = new binding.Hmac();
135 this._handle.init(hmac, toBuf(key));
136 LazyTransform.call(this, options);
139 util.inherits(Hmac, LazyTransform);
141 Hmac.prototype.update = Hash.prototype.update;
142 Hmac.prototype.digest = Hash.prototype.digest;
143 Hmac.prototype._flush = Hash.prototype._flush;
144 Hmac.prototype._transform = Hash.prototype._transform;
147 function getDecoder(decoder, encoding) {
148 if (encoding === 'utf-8') encoding = 'utf8'; // Normalize encoding.
149 decoder = decoder || new StringDecoder(encoding);
150 assert(decoder.encoding === encoding, 'Cannot change encoding');
155 exports.createCipher = exports.Cipher = Cipher;
156 function Cipher(cipher, password, options) {
157 if (!(this instanceof Cipher))
158 return new Cipher(cipher, password, options);
159 this._handle = new binding.CipherBase(true);
161 this._handle.init(cipher, toBuf(password));
162 this._decoder = null;
164 LazyTransform.call(this, options);
167 util.inherits(Cipher, LazyTransform);
169 Cipher.prototype._transform = function(chunk, encoding, callback) {
170 this.push(this._handle.update(chunk, encoding));
174 Cipher.prototype._flush = function(callback) {
176 this.push(this._handle.final());
184 Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
185 inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
186 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
188 var ret = this._handle.update(data, inputEncoding);
190 if (outputEncoding && outputEncoding !== 'buffer') {
191 this._decoder = getDecoder(this._decoder, outputEncoding);
192 ret = this._decoder.write(ret);
199 Cipher.prototype.final = function(outputEncoding) {
200 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
201 var ret = this._handle.final();
203 if (outputEncoding && outputEncoding !== 'buffer') {
204 this._decoder = getDecoder(this._decoder, outputEncoding);
205 ret = this._decoder.end(ret);
212 Cipher.prototype.setAutoPadding = function(ap) {
213 this._handle.setAutoPadding(ap);
219 exports.createCipheriv = exports.Cipheriv = Cipheriv;
220 function Cipheriv(cipher, key, iv, options) {
221 if (!(this instanceof Cipheriv))
222 return new Cipheriv(cipher, key, iv, options);
223 this._handle = new binding.CipherBase(true);
224 this._handle.initiv(cipher, toBuf(key), toBuf(iv));
225 this._decoder = null;
227 LazyTransform.call(this, options);
230 util.inherits(Cipheriv, LazyTransform);
232 Cipheriv.prototype._transform = Cipher.prototype._transform;
233 Cipheriv.prototype._flush = Cipher.prototype._flush;
234 Cipheriv.prototype.update = Cipher.prototype.update;
235 Cipheriv.prototype.final = Cipher.prototype.final;
236 Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
238 Cipheriv.prototype.getAuthTag = function() {
239 return this._handle.getAuthTag();
243 Cipheriv.prototype.setAuthTag = function(tagbuf) {
244 this._handle.setAuthTag(tagbuf);
247 Cipheriv.prototype.setAAD = function(aadbuf) {
248 this._handle.setAAD(aadbuf);
252 exports.createDecipher = exports.Decipher = Decipher;
253 function Decipher(cipher, password, options) {
254 if (!(this instanceof Decipher))
255 return new Decipher(cipher, password, options);
257 this._handle = new binding.CipherBase(false);
258 this._handle.init(cipher, toBuf(password));
259 this._decoder = null;
261 LazyTransform.call(this, options);
264 util.inherits(Decipher, LazyTransform);
266 Decipher.prototype._transform = Cipher.prototype._transform;
267 Decipher.prototype._flush = Cipher.prototype._flush;
268 Decipher.prototype.update = Cipher.prototype.update;
269 Decipher.prototype.final = Cipher.prototype.final;
270 Decipher.prototype.finaltol = Cipher.prototype.final;
271 Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
275 exports.createDecipheriv = exports.Decipheriv = Decipheriv;
276 function Decipheriv(cipher, key, iv, options) {
277 if (!(this instanceof Decipheriv))
278 return new Decipheriv(cipher, key, iv, options);
280 this._handle = new binding.CipherBase(false);
281 this._handle.initiv(cipher, toBuf(key), toBuf(iv));
282 this._decoder = null;
284 LazyTransform.call(this, options);
287 util.inherits(Decipheriv, LazyTransform);
289 Decipheriv.prototype._transform = Cipher.prototype._transform;
290 Decipheriv.prototype._flush = Cipher.prototype._flush;
291 Decipheriv.prototype.update = Cipher.prototype.update;
292 Decipheriv.prototype.final = Cipher.prototype.final;
293 Decipheriv.prototype.finaltol = Cipher.prototype.final;
294 Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
295 Decipheriv.prototype.getAuthTag = Cipheriv.prototype.getAuthTag;
296 Decipheriv.prototype.setAuthTag = Cipheriv.prototype.setAuthTag;
297 Decipheriv.prototype.setAAD = Cipheriv.prototype.setAAD;
301 exports.createSign = exports.Sign = Sign;
302 function Sign(algorithm, options) {
303 if (!(this instanceof Sign))
304 return new Sign(algorithm, options);
305 this._handle = new binding.Sign();
306 this._handle.init(algorithm);
308 stream.Writable.call(this, options);
311 util.inherits(Sign, stream.Writable);
313 Sign.prototype._write = function(chunk, encoding, callback) {
314 this._handle.update(chunk, encoding);
318 Sign.prototype.update = Hash.prototype.update;
320 Sign.prototype.sign = function(options, encoding) {
322 throw new Error('No key provided to sign');
324 var key = options.key || options;
325 var passphrase = options.passphrase || null;
326 var ret = this._handle.sign(toBuf(key), null, passphrase);
328 encoding = encoding || exports.DEFAULT_ENCODING;
329 if (encoding && encoding !== 'buffer')
330 ret = ret.toString(encoding);
337 exports.createVerify = exports.Verify = Verify;
338 function Verify(algorithm, options) {
339 if (!(this instanceof Verify))
340 return new Verify(algorithm, options);
342 this._handle = new binding.Verify;
343 this._handle.init(algorithm);
345 stream.Writable.call(this, options);
348 util.inherits(Verify, stream.Writable);
350 Verify.prototype._write = Sign.prototype._write;
351 Verify.prototype.update = Sign.prototype.update;
353 Verify.prototype.verify = function(object, signature, sigEncoding) {
354 sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
355 return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding));
358 exports.publicEncrypt = function(object, buffer) {
359 return binding.publicEncrypt(toBuf(object), buffer);
362 exports.privateDecrypt = function(options, buffer) {
363 var key = options.key || options;
364 var passphrase = options.passphrase || null;
365 return binding.privateDecrypt(toBuf(key), buffer, passphrase);
370 exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
372 function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
373 if (!(this instanceof DiffieHellman))
374 return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding);
377 if (typeof keyEncoding !== 'string' ||
378 (!Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer')) {
379 genEncoding = generator;
380 generator = keyEncoding;
385 keyEncoding = keyEncoding || exports.DEFAULT_ENCODING;
386 genEncoding = genEncoding || exports.DEFAULT_ENCODING;
388 if (typeof sizeOrKey !== 'number')
389 sizeOrKey = toBuf(sizeOrKey, keyEncoding);
392 generator = DH_GENERATOR;
393 else if (typeof generator !== 'number')
394 generator = toBuf(generator, genEncoding);
396 this._handle = new binding.DiffieHellman(sizeOrKey, generator);
397 Object.defineProperty(this, 'verifyError', {
399 value: this._handle.verifyError,
405 exports.DiffieHellmanGroup =
406 exports.createDiffieHellmanGroup =
407 exports.getDiffieHellman = DiffieHellmanGroup;
409 function DiffieHellmanGroup(name) {
410 if (!(this instanceof DiffieHellmanGroup))
411 return new DiffieHellmanGroup(name);
412 this._handle = new binding.DiffieHellmanGroup(name);
413 Object.defineProperty(this, 'verifyError', {
415 value: this._handle.verifyError,
421 DiffieHellmanGroup.prototype.generateKeys =
422 DiffieHellman.prototype.generateKeys =
425 function dhGenerateKeys(encoding) {
426 var keys = this._handle.generateKeys();
427 encoding = encoding || exports.DEFAULT_ENCODING;
428 if (encoding && encoding !== 'buffer')
429 keys = keys.toString(encoding);
434 DiffieHellmanGroup.prototype.computeSecret =
435 DiffieHellman.prototype.computeSecret =
438 function dhComputeSecret(key, inEnc, outEnc) {
439 inEnc = inEnc || exports.DEFAULT_ENCODING;
440 outEnc = outEnc || exports.DEFAULT_ENCODING;
441 var ret = this._handle.computeSecret(toBuf(key, inEnc));
442 if (outEnc && outEnc !== 'buffer')
443 ret = ret.toString(outEnc);
448 DiffieHellmanGroup.prototype.getPrime =
449 DiffieHellman.prototype.getPrime =
452 function dhGetPrime(encoding) {
453 var prime = this._handle.getPrime();
454 encoding = encoding || exports.DEFAULT_ENCODING;
455 if (encoding && encoding !== 'buffer')
456 prime = prime.toString(encoding);
461 DiffieHellmanGroup.prototype.getGenerator =
462 DiffieHellman.prototype.getGenerator =
465 function dhGetGenerator(encoding) {
466 var generator = this._handle.getGenerator();
467 encoding = encoding || exports.DEFAULT_ENCODING;
468 if (encoding && encoding !== 'buffer')
469 generator = generator.toString(encoding);
474 DiffieHellmanGroup.prototype.getPublicKey =
475 DiffieHellman.prototype.getPublicKey =
478 function dhGetPublicKey(encoding) {
479 var key = this._handle.getPublicKey();
480 encoding = encoding || exports.DEFAULT_ENCODING;
481 if (encoding && encoding !== 'buffer')
482 key = key.toString(encoding);
487 DiffieHellmanGroup.prototype.getPrivateKey =
488 DiffieHellman.prototype.getPrivateKey =
491 function dhGetPrivateKey(encoding) {
492 var key = this._handle.getPrivateKey();
493 encoding = encoding || exports.DEFAULT_ENCODING;
494 if (encoding && encoding !== 'buffer')
495 key = key.toString(encoding);
500 DiffieHellman.prototype.setPublicKey = function(key, encoding) {
501 encoding = encoding || exports.DEFAULT_ENCODING;
502 this._handle.setPublicKey(toBuf(key, encoding));
507 DiffieHellman.prototype.setPrivateKey = function(key, encoding) {
508 encoding = encoding || exports.DEFAULT_ENCODING;
509 this._handle.setPrivateKey(toBuf(key, encoding));
515 exports.pbkdf2 = function(password,
521 if (util.isFunction(digest)) {
526 if (!util.isFunction(callback))
527 throw new Error('No callback provided to pbkdf2');
529 return pbkdf2(password, salt, iterations, keylen, digest, callback);
533 exports.pbkdf2Sync = function(password, salt, iterations, keylen, digest) {
534 return pbkdf2(password, salt, iterations, keylen, digest);
538 function pbkdf2(password, salt, iterations, keylen, digest, callback) {
539 password = toBuf(password);
542 if (exports.DEFAULT_ENCODING === 'buffer')
543 return binding.PBKDF2(password, salt, iterations, keylen, digest, callback);
545 // at this point, we need to handle encodings.
546 var encoding = exports.DEFAULT_ENCODING;
548 function next(er, ret) {
550 ret = ret.toString(encoding);
553 binding.PBKDF2(password, salt, iterations, keylen, digest, next);
555 var ret = binding.PBKDF2(password, salt, iterations, keylen, digest);
556 return ret.toString(encoding);
561 exports.Certificate = Certificate;
563 function Certificate() {
564 if (!(this instanceof Certificate))
565 return new Certificate();
567 this._handle = new binding.Certificate();
571 Certificate.prototype.verifySpkac = function(object) {
572 return this._handle.verifySpkac(object);
576 Certificate.prototype.exportPublicKey = function(object, encoding) {
577 return this._handle.exportPublicKey(toBuf(object, encoding));
581 Certificate.prototype.exportChallenge = function(object, encoding) {
582 return this._handle.exportChallenge(toBuf(object, encoding));
586 exports.setEngine = function setEngine(id, flags) {
587 if (!util.isString(id))
588 throw new TypeError('id should be a string');
590 if (flags && !util.isNumber(flags))
591 throw new TypeError('flags should be a number, if present');
594 // Use provided engine for everything by default
596 flags = constants.ENGINE_METHOD_ALL;
598 return binding.setEngine(id, flags);
601 exports.randomBytes = randomBytes;
602 exports.pseudoRandomBytes = pseudoRandomBytes;
604 exports.rng = randomBytes;
605 exports.prng = pseudoRandomBytes;
608 exports.getCiphers = function() {
609 return filterDuplicates(getCiphers.call(null, arguments));
613 exports.getHashes = function() {
614 return filterDuplicates(getHashes.call(null, arguments));
619 function filterDuplicates(names) {
620 // Drop all-caps names in favor of their lowercase aliases,
621 // for example, 'sha1' instead of 'SHA1'.
623 names.forEach(function(name) {
625 if (/^[0-9A-Z\-]+$/.test(key)) key = key.toLowerCase();
626 if (!ctx.hasOwnProperty(key) || ctx[key] < name)
630 return Object.getOwnPropertyNames(ctx).map(function(key) {
636 exports.__defineGetter__('createCredentials', util.deprecate(function() {
637 return require('tls').createSecureContext;
638 }, 'createCredentials() is deprecated, use tls.createSecureContext instead'));
640 exports.__defineGetter__('Credentials', util.deprecate(function() {
641 return require('tls').SecureContext;
642 }, 'Credentials is deprecated, use tls.createSecureContext instead'));