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 SecureContext = binding.SecureContext;
30 var randomBytes = binding.randomBytes;
31 var pseudoRandomBytes = binding.pseudoRandomBytes;
32 var getCiphers = binding.getCiphers;
33 var getHashes = binding.getHashes;
40 var stream = require('stream');
41 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 (typeof str === 'string') {
49 if (encoding === 'buffer')
51 str = new Buffer(str, encoding);
57 var assert = require('assert');
58 var StringDecoder = require('string_decoder').StringDecoder;
60 function Credentials(secureProtocol, flags, context) {
61 if (!(this instanceof Credentials)) {
62 return new Credentials(secureProtocol, flags, context);
66 throw new Error('node.js not compiled with openssl crypto support.');
70 this.context = context;
72 this.context = new SecureContext();
75 this.context.init(secureProtocol);
81 if (flags) this.context.setOptions(flags);
84 exports.Credentials = Credentials;
87 exports.createCredentials = function(options, context) {
88 if (!options) options = {};
90 var c = new Credentials(options.secureProtocol,
91 options.secureOptions,
94 if (context) return c;
97 if (options.passphrase) {
98 c.context.setKey(options.key, options.passphrase);
100 c.context.setKey(options.key);
104 if (options.cert) c.context.setCert(options.cert);
106 if (options.ciphers) c.context.setCiphers(options.ciphers);
109 if (Array.isArray(options.ca)) {
110 for (var i = 0, len = options.ca.length; i < len; i++) {
111 c.context.addCACert(options.ca[i]);
114 c.context.addCACert(options.ca);
117 c.context.addRootCerts();
121 if (Array.isArray(options.crl)) {
122 for (var i = 0, len = options.crl.length; i < len; i++) {
123 c.context.addCRL(options.crl[i]);
126 c.context.addCRL(options.crl);
130 if (options.sessionIdContext) {
131 c.context.setSessionIdContext(options.sessionIdContext);
135 var pfx = options.pfx;
136 var passphrase = options.passphrase;
140 passphrase = toBuf(passphrase);
143 c.context.loadPKCS12(pfx, passphrase);
145 c.context.loadPKCS12(pfx);
153 function LazyTransform(options) {
154 this._options = options;
156 util.inherits(LazyTransform, stream.Transform);
158 var transformMethods = ['read', 'write', 'end', 'pipe', 'unpipe',
159 'setEncoding', 'pause', 'resume'];
161 transformMethods.forEach(function(action, i, actions) {
162 LazyTransform.prototype[action] = function() {
163 stream.Transform.call(this, this._options);
165 actions.forEach(function(action) {
166 this[action] = stream.Transform.prototype[action];
169 return this[action].apply(this, arguments);
174 exports.createHash = exports.Hash = Hash;
175 function Hash(algorithm, options) {
176 if (!(this instanceof Hash))
177 return new Hash(algorithm, options);
178 this._binding = new binding.Hash(algorithm);
179 LazyTransform.call(this, options);
182 util.inherits(Hash, LazyTransform);
184 Hash.prototype._transform = function(chunk, encoding, callback) {
185 this._binding.update(chunk, encoding);
189 Hash.prototype._flush = function(callback) {
190 this.push(this._binding.digest());
194 Hash.prototype.update = function(data, encoding) {
195 encoding = encoding || exports.DEFAULT_ENCODING;
196 data = toBuf(data, encoding);
197 this._binding.update(data);
202 Hash.prototype.digest = function(outputEncoding) {
203 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
204 var result = this._binding.digest();
205 if (outputEncoding && outputEncoding !== 'buffer')
206 result = result.toString(outputEncoding);
211 exports.createHmac = exports.Hmac = Hmac;
213 function Hmac(hmac, key, options) {
214 if (!(this instanceof Hmac))
215 return new Hmac(hmac, key, options);
216 this._binding = new binding.Hmac();
217 this._binding.init(hmac, toBuf(key));
218 LazyTransform.call(this, options);
221 util.inherits(Hmac, LazyTransform);
223 Hmac.prototype.update = Hash.prototype.update;
224 Hmac.prototype.digest = Hash.prototype.digest;
225 Hmac.prototype._flush = Hash.prototype._flush;
226 Hmac.prototype._transform = Hash.prototype._transform;
229 function getDecoder(decoder, encoding) {
230 decoder = decoder || new StringDecoder(encoding);
231 assert(decoder.encoding === encoding, 'Cannot change encoding');
236 exports.createCipher = exports.Cipher = Cipher;
237 function Cipher(cipher, password, options) {
238 if (!(this instanceof Cipher))
239 return new Cipher(cipher, password, options);
240 this._binding = new binding.CipherBase(true);
242 this._binding.init(cipher, toBuf(password));
243 this._decoder = null;
245 LazyTransform.call(this, options);
248 util.inherits(Cipher, LazyTransform);
250 Cipher.prototype._transform = function(chunk, encoding, callback) {
251 this.push(this._binding.update(chunk, encoding));
255 Cipher.prototype._flush = function(callback) {
256 this.push(this._binding.final());
260 Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
261 inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
262 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
263 data = toBuf(data, inputEncoding);
265 var ret = this._binding.update(data);
267 if (outputEncoding && outputEncoding !== 'buffer') {
268 this._decoder = getDecoder(this._decoder, outputEncoding);
269 ret = this._decoder.write(ret);
276 Cipher.prototype.final = function(outputEncoding) {
277 outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
278 var ret = this._binding.final();
280 if (outputEncoding && outputEncoding !== 'buffer') {
281 this._decoder = getDecoder(this._decoder, outputEncoding);
282 ret = this._decoder.end(ret);
289 Cipher.prototype.setAutoPadding = function(ap) {
290 this._binding.setAutoPadding(ap);
296 exports.createCipheriv = exports.Cipheriv = Cipheriv;
297 function Cipheriv(cipher, key, iv, options) {
298 if (!(this instanceof Cipheriv))
299 return new Cipheriv(cipher, key, iv, options);
300 this._binding = new binding.CipherBase(true);
301 this._binding.initiv(cipher, toBuf(key), toBuf(iv));
302 this._decoder = null;
304 LazyTransform.call(this, options);
307 util.inherits(Cipheriv, LazyTransform);
309 Cipheriv.prototype._transform = Cipher.prototype._transform;
310 Cipheriv.prototype._flush = Cipher.prototype._flush;
311 Cipheriv.prototype.update = Cipher.prototype.update;
312 Cipheriv.prototype.final = Cipher.prototype.final;
313 Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
317 exports.createDecipher = exports.Decipher = Decipher;
318 function Decipher(cipher, password, options) {
319 if (!(this instanceof Decipher))
320 return new Decipher(cipher, password, options);
322 this._binding = new binding.CipherBase(false);
323 this._binding.init(cipher, toBuf(password));
324 this._decoder = null;
326 LazyTransform.call(this, options);
329 util.inherits(Decipher, LazyTransform);
331 Decipher.prototype._transform = Cipher.prototype._transform;
332 Decipher.prototype._flush = Cipher.prototype._flush;
333 Decipher.prototype.update = Cipher.prototype.update;
334 Decipher.prototype.final = Cipher.prototype.final;
335 Decipher.prototype.finaltol = Cipher.prototype.final;
336 Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
340 exports.createDecipheriv = exports.Decipheriv = Decipheriv;
341 function Decipheriv(cipher, key, iv, options) {
342 if (!(this instanceof Decipheriv))
343 return new Decipheriv(cipher, key, iv, options);
345 this._binding = new binding.CipherBase(false);
346 this._binding.initiv(cipher, toBuf(key), toBuf(iv));
347 this._decoder = null;
349 LazyTransform.call(this, options);
352 util.inherits(Decipheriv, LazyTransform);
354 Decipheriv.prototype._transform = Cipher.prototype._transform;
355 Decipheriv.prototype._flush = Cipher.prototype._flush;
356 Decipheriv.prototype.update = Cipher.prototype.update;
357 Decipheriv.prototype.final = Cipher.prototype.final;
358 Decipheriv.prototype.finaltol = Cipher.prototype.final;
359 Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
363 exports.createSign = exports.Sign = Sign;
364 function Sign(algorithm, options) {
365 if (!(this instanceof Sign))
366 return new Sign(algorithm, options);
367 this._binding = new binding.Sign();
368 this._binding.init(algorithm);
370 stream.Writable.call(this, options);
373 util.inherits(Sign, stream.Writable);
375 Sign.prototype._write = function(chunk, encoding, callback) {
376 this._binding.update(chunk, encoding);
380 Sign.prototype.update = Hash.prototype.update;
382 Sign.prototype.sign = function(key, encoding) {
383 encoding = encoding || exports.DEFAULT_ENCODING;
384 var ret = this._binding.sign(toBuf(key));
386 if (encoding && encoding !== 'buffer')
387 ret = ret.toString(encoding);
394 exports.createVerify = exports.Verify = Verify;
395 function Verify(algorithm, options) {
396 if (!(this instanceof Verify))
397 return new Verify(algorithm, options);
399 this._binding = new binding.Verify;
400 this._binding.init(algorithm);
402 stream.Writable.call(this, options);
405 util.inherits(Verify, stream.Writable);
407 Verify.prototype._write = Sign.prototype._write;
408 Verify.prototype.update = Sign.prototype.update;
410 Verify.prototype.verify = function(object, signature, sigEncoding) {
411 sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
412 return this._binding.verify(toBuf(object), toBuf(signature, sigEncoding));
417 exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
419 function DiffieHellman(sizeOrKey, encoding) {
420 if (!(this instanceof DiffieHellman))
421 return new DiffieHellman(sizeOrKey, encoding);
424 this._binding = new binding.DiffieHellman();
426 encoding = encoding || exports.DEFAULT_ENCODING;
427 sizeOrKey = toBuf(sizeOrKey, encoding);
428 this._binding = new binding.DiffieHellman(sizeOrKey);
433 exports.DiffieHellmanGroup =
434 exports.createDiffieHellmanGroup =
435 exports.getDiffieHellman = DiffieHellmanGroup;
437 function DiffieHellmanGroup(name) {
438 if (!(this instanceof DiffieHellmanGroup))
439 return new DiffieHellmanGroup(name);
440 this._binding = new binding.DiffieHellmanGroup(name);
444 DiffieHellmanGroup.prototype.generateKeys =
445 DiffieHellman.prototype.generateKeys =
448 function dhGenerateKeys(encoding) {
449 var keys = this._binding.generateKeys();
450 encoding = encoding || exports.DEFAULT_ENCODING;
451 if (encoding && encoding !== 'buffer')
452 keys = keys.toString(encoding);
457 DiffieHellmanGroup.prototype.computeSecret =
458 DiffieHellman.prototype.computeSecret =
461 function dhComputeSecret(key, inEnc, outEnc) {
462 inEnc = inEnc || exports.DEFAULT_ENCODING;
463 outEnc = outEnc || exports.DEFAULT_ENCODING;
464 var ret = this._binding.computeSecret(toBuf(key, inEnc));
465 if (outEnc && outEnc !== 'buffer')
466 ret = ret.toString(outEnc);
471 DiffieHellmanGroup.prototype.getPrime =
472 DiffieHellman.prototype.getPrime =
475 function dhGetPrime(encoding) {
476 var prime = this._binding.getPrime();
477 encoding = encoding || exports.DEFAULT_ENCODING;
478 if (encoding && encoding !== 'buffer')
479 prime = prime.toString(encoding);
484 DiffieHellmanGroup.prototype.getGenerator =
485 DiffieHellman.prototype.getGenerator =
488 function dhGetGenerator(encoding) {
489 var generator = this._binding.getGenerator();
490 encoding = encoding || exports.DEFAULT_ENCODING;
491 if (encoding && encoding !== 'buffer')
492 generator = generator.toString(encoding);
497 DiffieHellmanGroup.prototype.getPublicKey =
498 DiffieHellman.prototype.getPublicKey =
501 function dhGetPublicKey(encoding) {
502 var key = this._binding.getPublicKey();
503 encoding = encoding || exports.DEFAULT_ENCODING;
504 if (encoding && encoding !== 'buffer')
505 key = key.toString(encoding);
510 DiffieHellmanGroup.prototype.getPrivateKey =
511 DiffieHellman.prototype.getPrivateKey =
514 function dhGetPrivateKey(encoding) {
515 var key = this._binding.getPrivateKey();
516 encoding = encoding || exports.DEFAULT_ENCODING;
517 if (encoding && encoding !== 'buffer')
518 key = key.toString(encoding);
523 DiffieHellman.prototype.setPublicKey = function(key, encoding) {
524 encoding = encoding || exports.DEFAULT_ENCODING;
525 this._binding.setPublicKey(toBuf(key, encoding));
530 DiffieHellman.prototype.setPrivateKey = function(key, encoding) {
531 encoding = encoding || exports.DEFAULT_ENCODING;
532 this._binding.setPrivateKey(toBuf(key, encoding));
538 exports.pbkdf2 = function(password, salt, iterations, keylen, callback) {
539 if (typeof callback !== 'function')
540 throw new Error('No callback provided to pbkdf2');
542 return pbkdf2(password, salt, iterations, keylen, callback);
546 exports.pbkdf2Sync = function(password, salt, iterations, keylen) {
547 return pbkdf2(password, salt, iterations, keylen);
551 function pbkdf2(password, salt, iterations, keylen, callback) {
552 password = toBuf(password);
555 if (exports.DEFAULT_ENCODING === 'buffer')
556 return binding.PBKDF2(password, salt, iterations, keylen, callback);
558 // at this point, we need to handle encodings.
559 var encoding = exports.DEFAULT_ENCODING;
561 binding.PBKDF2(password, salt, iterations, keylen, function(er, ret) {
563 ret = ret.toString(encoding);
567 var ret = binding.PBKDF2(password, salt, iterations, keylen);
568 return ret.toString(encoding);
574 exports.randomBytes = randomBytes;
575 exports.pseudoRandomBytes = pseudoRandomBytes;
577 exports.rng = randomBytes;
578 exports.prng = pseudoRandomBytes;
581 exports.getCiphers = function() {
582 return filterDuplicates(getCiphers.call(null, arguments));
586 exports.getHashes = function() {
587 return filterDuplicates(getHashes.call(null, arguments));
592 function filterDuplicates(names) {
593 // Drop all-caps names in favor of their lowercase aliases,
594 // for example, 'sha1' instead of 'SHA1'.
596 names.forEach(function(name) {
597 if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase();
600 return Object.getOwnPropertyNames(ctx).sort();