16a3e38e25095373df7c45e4555f168b62b36d43
[platform/upstream/nodejs.git] / lib / crypto.js
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 exports.DEFAULT_ENCODING = 'buffer';
26
27 try {
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;
33 } catch (e) {
34   throw new Error('node.js not compiled with openssl crypto support.');
35 }
36
37 var constants = require('constants');
38 var stream = require('stream');
39 var util = require('util');
40
41 var DH_GENERATOR = 2;
42
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')
50       encoding = 'binary';
51     str = new Buffer(str, encoding);
52   }
53   return str;
54 }
55 exports._toBuf = toBuf;
56
57
58 var assert = require('assert');
59 var StringDecoder = require('string_decoder').StringDecoder;
60
61
62 function LazyTransform(options) {
63   this._options = options;
64 }
65 util.inherits(LazyTransform, stream.Transform);
66
67 [
68   '_readableState',
69   '_writableState',
70   '_transformState'
71 ].forEach(function(prop, i, props) {
72   Object.defineProperty(LazyTransform.prototype, prop, {
73     get: function() {
74       stream.Transform.call(this, this._options);
75       this._writableState.decodeStrings = false;
76       this._writableState.defaultEncoding = 'binary';
77       return this[prop];
78     },
79     set: function(val) {
80       Object.defineProperty(this, prop, {
81         value: val,
82         enumerable: true,
83         configurable: true,
84         writable: true
85       });
86     },
87     configurable: true,
88     enumerable: true
89   });
90 });
91
92
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);
99 }
100
101 util.inherits(Hash, LazyTransform);
102
103 Hash.prototype._transform = function(chunk, encoding, callback) {
104   this._handle.update(chunk, encoding);
105   callback();
106 };
107
108 Hash.prototype._flush = function(callback) {
109   var encoding = this._readableState.encoding || 'buffer';
110   this.push(this._handle.digest(encoding), encoding);
111   callback();
112 };
113
114 Hash.prototype.update = function(data, encoding) {
115   encoding = encoding || exports.DEFAULT_ENCODING;
116   if (encoding === 'buffer' && util.isString(data))
117     encoding = 'binary';
118   this._handle.update(data, encoding);
119   return this;
120 };
121
122
123 Hash.prototype.digest = function(outputEncoding) {
124   outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
125   return this._handle.digest(outputEncoding);
126 };
127
128
129 exports.createHmac = exports.Hmac = Hmac;
130
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);
137 }
138
139 util.inherits(Hmac, LazyTransform);
140
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;
145
146
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');
151   return decoder;
152 }
153
154
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);
160
161   this._handle.init(cipher, toBuf(password));
162   this._decoder = null;
163
164   LazyTransform.call(this, options);
165 }
166
167 util.inherits(Cipher, LazyTransform);
168
169 Cipher.prototype._transform = function(chunk, encoding, callback) {
170   this.push(this._handle.update(chunk, encoding));
171   callback();
172 };
173
174 Cipher.prototype._flush = function(callback) {
175   try {
176     this.push(this._handle.final());
177   } catch (e) {
178     callback(e);
179     return;
180   }
181   callback();
182 };
183
184 Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
185   inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
186   outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
187
188   var ret = this._handle.update(data, inputEncoding);
189
190   if (outputEncoding && outputEncoding !== 'buffer') {
191     this._decoder = getDecoder(this._decoder, outputEncoding);
192     ret = this._decoder.write(ret);
193   }
194
195   return ret;
196 };
197
198
199 Cipher.prototype.final = function(outputEncoding) {
200   outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
201   var ret = this._handle.final();
202
203   if (outputEncoding && outputEncoding !== 'buffer') {
204     this._decoder = getDecoder(this._decoder, outputEncoding);
205     ret = this._decoder.end(ret);
206   }
207
208   return ret;
209 };
210
211
212 Cipher.prototype.setAutoPadding = function(ap) {
213   this._handle.setAutoPadding(ap);
214   return this;
215 };
216
217
218
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;
226
227   LazyTransform.call(this, options);
228 }
229
230 util.inherits(Cipheriv, LazyTransform);
231
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;
237
238 Cipheriv.prototype.getAuthTag = function() {
239   return this._handle.getAuthTag();
240 };
241
242
243 Cipheriv.prototype.setAuthTag = function(tagbuf) {
244   this._handle.setAuthTag(tagbuf);
245 };
246
247 Cipheriv.prototype.setAAD = function(aadbuf) {
248   this._handle.setAAD(aadbuf);
249 };
250
251
252 exports.createDecipher = exports.Decipher = Decipher;
253 function Decipher(cipher, password, options) {
254   if (!(this instanceof Decipher))
255     return new Decipher(cipher, password, options);
256
257   this._handle = new binding.CipherBase(false);
258   this._handle.init(cipher, toBuf(password));
259   this._decoder = null;
260
261   LazyTransform.call(this, options);
262 }
263
264 util.inherits(Decipher, LazyTransform);
265
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;
272
273
274
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);
279
280   this._handle = new binding.CipherBase(false);
281   this._handle.initiv(cipher, toBuf(key), toBuf(iv));
282   this._decoder = null;
283
284   LazyTransform.call(this, options);
285 }
286
287 util.inherits(Decipheriv, LazyTransform);
288
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;
298
299
300
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);
307
308   stream.Writable.call(this, options);
309 }
310
311 util.inherits(Sign, stream.Writable);
312
313 Sign.prototype._write = function(chunk, encoding, callback) {
314   this._handle.update(chunk, encoding);
315   callback();
316 };
317
318 Sign.prototype.update = Hash.prototype.update;
319
320 Sign.prototype.sign = function(options, encoding) {
321   if (!options)
322     throw new Error('No key provided to sign');
323
324   var key = options.key || options;
325   var passphrase = options.passphrase || null;
326   var ret = this._handle.sign(toBuf(key), null, passphrase);
327
328   encoding = encoding || exports.DEFAULT_ENCODING;
329   if (encoding && encoding !== 'buffer')
330     ret = ret.toString(encoding);
331
332   return ret;
333 };
334
335
336
337 exports.createVerify = exports.Verify = Verify;
338 function Verify(algorithm, options) {
339   if (!(this instanceof Verify))
340     return new Verify(algorithm, options);
341
342   this._handle = new binding.Verify;
343   this._handle.init(algorithm);
344
345   stream.Writable.call(this, options);
346 }
347
348 util.inherits(Verify, stream.Writable);
349
350 Verify.prototype._write = Sign.prototype._write;
351 Verify.prototype.update = Sign.prototype.update;
352
353 Verify.prototype.verify = function(object, signature, sigEncoding) {
354   sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
355   return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding));
356 };
357
358 exports.publicEncrypt = function(object, buffer) {
359   return binding.publicEncrypt(toBuf(object), buffer);
360 };
361
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);
366 };
367
368
369
370 exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
371
372 function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
373   if (!(this instanceof DiffieHellman))
374     return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding);
375
376   if (keyEncoding) {
377     if (typeof keyEncoding !== 'string' ||
378         (!Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer')) {
379       genEncoding = generator;
380       generator = keyEncoding;
381       keyEncoding = false;
382     }
383   }
384
385   keyEncoding = keyEncoding || exports.DEFAULT_ENCODING;
386   genEncoding = genEncoding || exports.DEFAULT_ENCODING;
387
388   if (typeof sizeOrKey !== 'number')
389     sizeOrKey = toBuf(sizeOrKey, keyEncoding);
390
391   if (!generator)
392     generator = DH_GENERATOR;
393   else if (typeof generator !== 'number')
394     generator = toBuf(generator, genEncoding);
395
396   this._handle = new binding.DiffieHellman(sizeOrKey, generator);
397   Object.defineProperty(this, 'verifyError', {
398     enumerable: true,
399     value: this._handle.verifyError,
400     writable: false
401   });
402 }
403
404
405 exports.DiffieHellmanGroup =
406     exports.createDiffieHellmanGroup =
407     exports.getDiffieHellman = DiffieHellmanGroup;
408
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', {
414     enumerable: true,
415     value: this._handle.verifyError,
416     writable: false
417   });
418 }
419
420
421 DiffieHellmanGroup.prototype.generateKeys =
422     DiffieHellman.prototype.generateKeys =
423     dhGenerateKeys;
424
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);
430   return keys;
431 }
432
433
434 DiffieHellmanGroup.prototype.computeSecret =
435     DiffieHellman.prototype.computeSecret =
436     dhComputeSecret;
437
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);
444   return ret;
445 }
446
447
448 DiffieHellmanGroup.prototype.getPrime =
449     DiffieHellman.prototype.getPrime =
450     dhGetPrime;
451
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);
457   return prime;
458 }
459
460
461 DiffieHellmanGroup.prototype.getGenerator =
462     DiffieHellman.prototype.getGenerator =
463     dhGetGenerator;
464
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);
470   return generator;
471 }
472
473
474 DiffieHellmanGroup.prototype.getPublicKey =
475     DiffieHellman.prototype.getPublicKey =
476     dhGetPublicKey;
477
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);
483   return key;
484 }
485
486
487 DiffieHellmanGroup.prototype.getPrivateKey =
488     DiffieHellman.prototype.getPrivateKey =
489     dhGetPrivateKey;
490
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);
496   return key;
497 }
498
499
500 DiffieHellman.prototype.setPublicKey = function(key, encoding) {
501   encoding = encoding || exports.DEFAULT_ENCODING;
502   this._handle.setPublicKey(toBuf(key, encoding));
503   return this;
504 };
505
506
507 DiffieHellman.prototype.setPrivateKey = function(key, encoding) {
508   encoding = encoding || exports.DEFAULT_ENCODING;
509   this._handle.setPrivateKey(toBuf(key, encoding));
510   return this;
511 };
512
513
514
515 exports.pbkdf2 = function(password,
516                           salt,
517                           iterations,
518                           keylen,
519                           digest,
520                           callback) {
521   if (util.isFunction(digest)) {
522     callback = digest;
523     digest = undefined;
524   }
525
526   if (!util.isFunction(callback))
527     throw new Error('No callback provided to pbkdf2');
528
529   return pbkdf2(password, salt, iterations, keylen, digest, callback);
530 };
531
532
533 exports.pbkdf2Sync = function(password, salt, iterations, keylen, digest) {
534   return pbkdf2(password, salt, iterations, keylen, digest);
535 };
536
537
538 function pbkdf2(password, salt, iterations, keylen, digest, callback) {
539   password = toBuf(password);
540   salt = toBuf(salt);
541
542   if (exports.DEFAULT_ENCODING === 'buffer')
543     return binding.PBKDF2(password, salt, iterations, keylen, digest, callback);
544
545   // at this point, we need to handle encodings.
546   var encoding = exports.DEFAULT_ENCODING;
547   if (callback) {
548     function next(er, ret) {
549       if (ret)
550         ret = ret.toString(encoding);
551       callback(er, ret);
552     }
553     binding.PBKDF2(password, salt, iterations, keylen, digest, next);
554   } else {
555     var ret = binding.PBKDF2(password, salt, iterations, keylen, digest);
556     return ret.toString(encoding);
557   }
558 }
559
560
561 exports.Certificate = Certificate;
562
563 function Certificate() {
564   if (!(this instanceof Certificate))
565     return new Certificate();
566
567   this._handle = new binding.Certificate();
568 }
569
570
571 Certificate.prototype.verifySpkac = function(object) {
572   return this._handle.verifySpkac(object);
573 };
574
575
576 Certificate.prototype.exportPublicKey = function(object, encoding) {
577   return this._handle.exportPublicKey(toBuf(object, encoding));
578 };
579
580
581 Certificate.prototype.exportChallenge = function(object, encoding) {
582   return this._handle.exportChallenge(toBuf(object, encoding));
583 };
584
585
586 exports.setEngine = function setEngine(id, flags) {
587   if (!util.isString(id))
588     throw new TypeError('id should be a string');
589
590   if (flags && !util.isNumber(flags))
591     throw new TypeError('flags should be a number, if present');
592   flags = flags >>> 0;
593
594   // Use provided engine for everything by default
595   if (flags === 0)
596     flags = constants.ENGINE_METHOD_ALL;
597
598   return binding.setEngine(id, flags);
599 };
600
601 exports.randomBytes = randomBytes;
602 exports.pseudoRandomBytes = pseudoRandomBytes;
603
604 exports.rng = randomBytes;
605 exports.prng = pseudoRandomBytes;
606
607
608 exports.getCiphers = function() {
609   return filterDuplicates(getCiphers.call(null, arguments));
610 };
611
612
613 exports.getHashes = function() {
614   return filterDuplicates(getHashes.call(null, arguments));
615
616 };
617
618
619 function filterDuplicates(names) {
620   // Drop all-caps names in favor of their lowercase aliases,
621   // for example, 'sha1' instead of 'SHA1'.
622   var ctx = {};
623   names.forEach(function(name) {
624     var key = name;
625     if (/^[0-9A-Z\-]+$/.test(key)) key = key.toLowerCase();
626     if (!ctx.hasOwnProperty(key) || ctx[key] < name)
627       ctx[key] = name;
628   });
629
630   return Object.getOwnPropertyNames(ctx).map(function(key) {
631     return ctx[key];
632   }).sort();
633 }
634
635 // Legacy API
636 exports.__defineGetter__('createCredentials', util.deprecate(function() {
637   return require('tls').createSecureContext;
638 }, 'createCredentials() is deprecated, use tls.createSecureContext instead'));
639
640 exports.__defineGetter__('Credentials', util.deprecate(function() {
641   return require('tls').SecureContext;
642 }, 'Credentials is deprecated, use tls.createSecureContext instead'));