revise installing a license file
[platform/upstream/nodejs.git] / lib / crypto.js
1 // Note: In 0.8 and before, crypto functions all defaulted to using
2 // binary-encoded strings rather than buffers.
3
4 'use strict';
5
6 exports.DEFAULT_ENCODING = 'buffer';
7
8 try {
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;
14 } catch (e) {
15   throw new Error('node.js not compiled with openssl crypto support.');
16 }
17
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');
24
25 const DH_GENERATOR = 2;
26
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')
34       encoding = 'binary';
35     str = new Buffer(str, encoding);
36   }
37   return str;
38 }
39 exports._toBuf = toBuf;
40
41
42 const assert = require('assert');
43 const StringDecoder = require('string_decoder').StringDecoder;
44
45
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);
52 }
53
54 util.inherits(Hash, LazyTransform);
55
56 Hash.prototype._transform = function(chunk, encoding, callback) {
57   this._handle.update(chunk, encoding);
58   callback();
59 };
60
61 Hash.prototype._flush = function(callback) {
62   this.push(this._handle.digest());
63   callback();
64 };
65
66 Hash.prototype.update = function(data, encoding) {
67   encoding = encoding || exports.DEFAULT_ENCODING;
68   if (encoding === 'buffer' && typeof data === 'string')
69     encoding = 'binary';
70   this._handle.update(data, encoding);
71   return this;
72 };
73
74
75 Hash.prototype.digest = function(outputEncoding) {
76   outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
77   return this._handle.digest(outputEncoding);
78 };
79
80
81 exports.createHmac = exports.Hmac = Hmac;
82
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);
89 }
90
91 util.inherits(Hmac, LazyTransform);
92
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;
97
98
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');
103   return decoder;
104 }
105
106
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);
112
113   this._handle.init(cipher, toBuf(password));
114   this._decoder = null;
115
116   LazyTransform.call(this, options);
117 }
118
119 util.inherits(Cipher, LazyTransform);
120
121 Cipher.prototype._transform = function(chunk, encoding, callback) {
122   this.push(this._handle.update(chunk, encoding));
123   callback();
124 };
125
126 Cipher.prototype._flush = function(callback) {
127   try {
128     this.push(this._handle.final());
129   } catch (e) {
130     callback(e);
131     return;
132   }
133   callback();
134 };
135
136 Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
137   inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
138   outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
139
140   var ret = this._handle.update(data, inputEncoding);
141
142   if (outputEncoding && outputEncoding !== 'buffer') {
143     this._decoder = getDecoder(this._decoder, outputEncoding);
144     ret = this._decoder.write(ret);
145   }
146
147   return ret;
148 };
149
150
151 Cipher.prototype.final = function(outputEncoding) {
152   outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
153   var ret = this._handle.final();
154
155   if (outputEncoding && outputEncoding !== 'buffer') {
156     this._decoder = getDecoder(this._decoder, outputEncoding);
157     ret = this._decoder.end(ret);
158   }
159
160   return ret;
161 };
162
163
164 Cipher.prototype.setAutoPadding = function(ap) {
165   this._handle.setAutoPadding(ap);
166   return this;
167 };
168
169 Cipher.prototype.getAuthTag = function() {
170   return this._handle.getAuthTag();
171 };
172
173
174 Cipher.prototype.setAuthTag = function(tagbuf) {
175   this._handle.setAuthTag(tagbuf);
176 };
177
178 Cipher.prototype.setAAD = function(aadbuf) {
179   this._handle.setAAD(aadbuf);
180 };
181
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;
189
190   LazyTransform.call(this, options);
191 }
192
193 util.inherits(Cipheriv, LazyTransform);
194
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;
203
204 exports.createDecipher = exports.Decipher = Decipher;
205 function Decipher(cipher, password, options) {
206   if (!(this instanceof Decipher))
207     return new Decipher(cipher, password, options);
208
209   this._handle = new binding.CipherBase(false);
210   this._handle.init(cipher, toBuf(password));
211   this._decoder = null;
212
213   LazyTransform.call(this, options);
214 }
215
216 util.inherits(Decipher, LazyTransform);
217
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;
227
228
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);
233
234   this._handle = new binding.CipherBase(false);
235   this._handle.initiv(cipher, toBuf(key), toBuf(iv));
236   this._decoder = null;
237
238   LazyTransform.call(this, options);
239 }
240
241 util.inherits(Decipheriv, LazyTransform);
242
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;
252
253
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);
260
261   stream.Writable.call(this, options);
262 }
263
264 util.inherits(Sign, stream.Writable);
265
266 Sign.prototype._write = function(chunk, encoding, callback) {
267   this._handle.update(chunk, encoding);
268   callback();
269 };
270
271 Sign.prototype.update = Hash.prototype.update;
272
273 Sign.prototype.sign = function(options, encoding) {
274   if (!options)
275     throw new Error('No key provided to sign');
276
277   var key = options.key || options;
278   var passphrase = options.passphrase || null;
279   var ret = this._handle.sign(toBuf(key), null, passphrase);
280
281   encoding = encoding || exports.DEFAULT_ENCODING;
282   if (encoding && encoding !== 'buffer')
283     ret = ret.toString(encoding);
284
285   return ret;
286 };
287
288
289 exports.createVerify = exports.Verify = Verify;
290 function Verify(algorithm, options) {
291   if (!(this instanceof Verify))
292     return new Verify(algorithm, options);
293
294   this._handle = new binding.Verify();
295   this._handle.init(algorithm);
296
297   stream.Writable.call(this, options);
298 }
299
300 util.inherits(Verify, stream.Writable);
301
302 Verify.prototype._write = Sign.prototype._write;
303 Verify.prototype.update = Sign.prototype.update;
304
305 Verify.prototype.verify = function(object, signature, sigEncoding) {
306   sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
307   return this._handle.verify(toBuf(object), toBuf(signature, sigEncoding));
308 };
309
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);
316   };
317 }
318
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);
325   };
326 }
327
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);
336
337
338 exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
339
340 function DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding) {
341   if (!(this instanceof DiffieHellman))
342     return new DiffieHellman(sizeOrKey, keyEncoding, generator, genEncoding);
343
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');
348
349   if (keyEncoding) {
350     if (typeof keyEncoding !== 'string' ||
351         (!Buffer.isEncoding(keyEncoding) && keyEncoding !== 'buffer')) {
352       genEncoding = generator;
353       generator = keyEncoding;
354       keyEncoding = false;
355     }
356   }
357
358   keyEncoding = keyEncoding || exports.DEFAULT_ENCODING;
359   genEncoding = genEncoding || exports.DEFAULT_ENCODING;
360
361   if (typeof sizeOrKey !== 'number')
362     sizeOrKey = toBuf(sizeOrKey, keyEncoding);
363
364   if (!generator)
365     generator = DH_GENERATOR;
366   else if (typeof generator !== 'number')
367     generator = toBuf(generator, genEncoding);
368
369   this._handle = new binding.DiffieHellman(sizeOrKey, generator);
370   Object.defineProperty(this, 'verifyError', {
371     enumerable: true,
372     value: this._handle.verifyError,
373     writable: false
374   });
375 }
376
377
378 exports.DiffieHellmanGroup =
379     exports.createDiffieHellmanGroup =
380     exports.getDiffieHellman = DiffieHellmanGroup;
381
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', {
387     enumerable: true,
388     value: this._handle.verifyError,
389     writable: false
390   });
391 }
392
393
394 DiffieHellmanGroup.prototype.generateKeys =
395     DiffieHellman.prototype.generateKeys =
396     dhGenerateKeys;
397
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);
403   return keys;
404 }
405
406
407 DiffieHellmanGroup.prototype.computeSecret =
408     DiffieHellman.prototype.computeSecret =
409     dhComputeSecret;
410
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);
417   return ret;
418 }
419
420
421 DiffieHellmanGroup.prototype.getPrime =
422     DiffieHellman.prototype.getPrime =
423     dhGetPrime;
424
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);
430   return prime;
431 }
432
433
434 DiffieHellmanGroup.prototype.getGenerator =
435     DiffieHellman.prototype.getGenerator =
436     dhGetGenerator;
437
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);
443   return generator;
444 }
445
446
447 DiffieHellmanGroup.prototype.getPublicKey =
448     DiffieHellman.prototype.getPublicKey =
449     dhGetPublicKey;
450
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);
456   return key;
457 }
458
459
460 DiffieHellmanGroup.prototype.getPrivateKey =
461     DiffieHellman.prototype.getPrivateKey =
462     dhGetPrivateKey;
463
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);
469   return key;
470 }
471
472
473 DiffieHellman.prototype.setPublicKey = function(key, encoding) {
474   encoding = encoding || exports.DEFAULT_ENCODING;
475   this._handle.setPublicKey(toBuf(key, encoding));
476   return this;
477 };
478
479
480 DiffieHellman.prototype.setPrivateKey = function(key, encoding) {
481   encoding = encoding || exports.DEFAULT_ENCODING;
482   this._handle.setPrivateKey(toBuf(key, encoding));
483   return this;
484 };
485
486
487 function ECDH(curve) {
488   if (typeof curve !== 'string')
489     throw new TypeError('curve should be a string');
490
491   this._handle = new binding.ECDH(curve);
492 }
493
494 exports.createECDH = function createECDH(curve) {
495   return new ECDH(curve);
496 };
497
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;
502
503 ECDH.prototype.generateKeys = function generateKeys(encoding, format) {
504   this._handle.generateKeys();
505
506   return this.getPublicKey(encoding, format);
507 };
508
509 ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) {
510   var f;
511   if (format) {
512     if (typeof format === 'number')
513       f = format;
514     if (format === 'compressed')
515       f = constants.POINT_CONVERSION_COMPRESSED;
516     else if (format === 'hybrid')
517       f = constants.POINT_CONVERSION_HYBRID;
518     // Default
519     else if (format === 'uncompressed')
520       f = constants.POINT_CONVERSION_UNCOMPRESSED;
521     else
522       throw new TypeError('Bad format: ' + format);
523   } else {
524     f = constants.POINT_CONVERSION_UNCOMPRESSED;
525   }
526   var key = this._handle.getPublicKey(f);
527   encoding = encoding || exports.DEFAULT_ENCODING;
528   if (encoding && encoding !== 'buffer')
529     key = key.toString(encoding);
530   return key;
531 };
532
533
534 exports.pbkdf2 = function(password,
535                           salt,
536                           iterations,
537                           keylen,
538                           digest,
539                           callback) {
540   if (typeof digest === 'function') {
541     callback = digest;
542     digest = undefined;
543   }
544
545   if (typeof callback !== 'function')
546     throw new Error('No callback provided to pbkdf2');
547
548   return pbkdf2(password, salt, iterations, keylen, digest, callback);
549 };
550
551
552 exports.pbkdf2Sync = function(password, salt, iterations, keylen, digest) {
553   return pbkdf2(password, salt, iterations, keylen, digest);
554 };
555
556
557 function pbkdf2(password, salt, iterations, keylen, digest, callback) {
558   password = toBuf(password);
559   salt = toBuf(salt);
560
561   if (exports.DEFAULT_ENCODING === 'buffer')
562     return binding.PBKDF2(password, salt, iterations, keylen, digest, callback);
563
564   // at this point, we need to handle encodings.
565   var encoding = exports.DEFAULT_ENCODING;
566   if (callback) {
567     var next = function(er, ret) {
568       if (ret)
569         ret = ret.toString(encoding);
570       callback(er, ret);
571     };
572     binding.PBKDF2(password, salt, iterations, keylen, digest, next);
573   } else {
574     var ret = binding.PBKDF2(password, salt, iterations, keylen, digest);
575     return ret.toString(encoding);
576   }
577 }
578
579
580 exports.Certificate = Certificate;
581
582 function Certificate() {
583   if (!(this instanceof Certificate))
584     return new Certificate();
585
586   this._handle = new binding.Certificate();
587 }
588
589
590 Certificate.prototype.verifySpkac = function(object) {
591   return this._handle.verifySpkac(object);
592 };
593
594
595 Certificate.prototype.exportPublicKey = function(object, encoding) {
596   return this._handle.exportPublicKey(toBuf(object, encoding));
597 };
598
599
600 Certificate.prototype.exportChallenge = function(object, encoding) {
601   return this._handle.exportChallenge(toBuf(object, encoding));
602 };
603
604
605 exports.setEngine = function setEngine(id, flags) {
606   if (typeof id !== 'string')
607     throw new TypeError('id should be a string');
608
609   if (flags && typeof flags !== 'number')
610     throw new TypeError('flags should be a number, if present');
611   flags = flags >>> 0;
612
613   // Use provided engine for everything by default
614   if (flags === 0)
615     flags = constants.ENGINE_METHOD_ALL;
616
617   return binding.setEngine(id, flags);
618 };
619
620 exports.randomBytes = exports.pseudoRandomBytes = randomBytes;
621
622 exports.rng = exports.prng = randomBytes;
623
624 exports.getCiphers = function() {
625   return filterDuplicates(getCiphers());
626 };
627
628
629 exports.getHashes = function() {
630   return filterDuplicates(getHashes());
631 };
632
633
634 exports.getCurves = function() {
635   return filterDuplicates(getCurves());
636 };
637
638
639 function filterDuplicates(names) {
640   // Drop all-caps names in favor of their lowercase aliases,
641   // for example, 'sha1' instead of 'SHA1'.
642   var ctx = {};
643   names.forEach(function(name) {
644     var key = name;
645     if (/^[0-9A-Z\-]+$/.test(key)) key = key.toLowerCase();
646     if (!ctx.hasOwnProperty(key) || ctx[key] < name)
647       ctx[key] = name;
648   });
649
650   return Object.getOwnPropertyNames(ctx).map(function(key) {
651     return ctx[key];
652   }).sort();
653 }
654
655 // Legacy API
656 exports.__defineGetter__('createCredentials',
657   internalUtil.deprecate(function() {
658     return require('tls').createSecureContext;
659   }, 'crypto.createCredentials is deprecated. ' +
660      'Use tls.createSecureContext instead.'));
661
662 exports.__defineGetter__('Credentials', internalUtil.deprecate(function() {
663   return require('tls').SecureContext;
664 }, 'crypto.Credentials is deprecated. ' +
665    'Use tls.createSecureContext instead.'));