The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / lib / crypto.js @ a241deb1

History | View | Annotate | Download (16 KB)

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 SecureContext = binding.SecureContext;
30
  var randomBytes = binding.randomBytes;
31
  var pseudoRandomBytes = binding.pseudoRandomBytes;
32
  var getCiphers = binding.getCiphers;
33
  var getHashes = binding.getHashes;
34
  var crypto = true;
35
} catch (e) {
36

    
37
  var crypto = false;
38
}
39

    
40
var stream = require('stream');
41
var util = require('util');
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 (typeof str === 'string') {
49
    if (encoding === 'buffer')
50
      encoding = 'binary';
51
    str = new Buffer(str, encoding);
52
  }
53
  return str;
54
}
55

    
56

    
57
var assert = require('assert');
58
var StringDecoder = require('string_decoder').StringDecoder;
59

    
60
function Credentials(secureProtocol, flags, context) {
61
  if (!(this instanceof Credentials)) {
62
    return new Credentials(secureProtocol, flags, context);
63
  }
64

    
65
  if (!crypto) {
66
    throw new Error('node.js not compiled with openssl crypto support.');
67
  }
68

    
69
  if (context) {
70
    this.context = context;
71
  } else {
72
    this.context = new SecureContext();
73

    
74
    if (secureProtocol) {
75
      this.context.init(secureProtocol);
76
    } else {
77
      this.context.init();
78
    }
79
  }
80

    
81
  if (flags) this.context.setOptions(flags);
82
}
83

    
84
exports.Credentials = Credentials;
85

    
86

    
87
exports.createCredentials = function(options, context) {
88
  if (!options) options = {};
89

    
90
  var c = new Credentials(options.secureProtocol,
91
                          options.secureOptions,
92
                          context);
93

    
94
  if (context) return c;
95

    
96
  if (options.key) {
97
    if (options.passphrase) {
98
      c.context.setKey(options.key, options.passphrase);
99
    } else {
100
      c.context.setKey(options.key);
101
    }
102
  }
103

    
104
  if (options.cert) c.context.setCert(options.cert);
105

    
106
  if (options.ciphers) c.context.setCiphers(options.ciphers);
107

    
108
  if (options.ca) {
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]);
112
      }
113
    } else {
114
      c.context.addCACert(options.ca);
115
    }
116
  } else {
117
    c.context.addRootCerts();
118
  }
119

    
120
  if (options.crl) {
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]);
124
      }
125
    } else {
126
      c.context.addCRL(options.crl);
127
    }
128
  }
129

    
130
  if (options.sessionIdContext) {
131
    c.context.setSessionIdContext(options.sessionIdContext);
132
  }
133

    
134
  if (options.pfx) {
135
    var pfx = options.pfx;
136
    var passphrase = options.passphrase;
137

    
138
    pfx = toBuf(pfx);
139
    if (passphrase)
140
      passphrase = toBuf(passphrase);
141

    
142
    if (passphrase) {
143
      c.context.loadPKCS12(pfx, passphrase);
144
    } else {
145
      c.context.loadPKCS12(pfx);
146
    }
147
  }
148

    
149
  return c;
150
};
151

    
152

    
153
function LazyTransform(options) {
154
  this._options = options;
155
}
156
util.inherits(LazyTransform, stream.Transform);
157

    
158
[
159
  '_readableState',
160
  '_writableState',
161
  '_transformState'
162
].forEach(function(prop, i, props) {
163
  Object.defineProperty(LazyTransform.prototype, prop, {
164
    get: function() {
165
      stream.Transform.call(this, this._options);
166
      this._writableState.decodeStrings = false;
167
      this._writableState.defaultEncoding = 'binary';
168
      return this[prop];
169
    },
170
    set: function(val) {
171
      Object.defineProperty(this, prop, {
172
        value: val,
173
        enumerable: true,
174
        configurable: true,
175
        writable: true
176
      });
177
    },
178
    configurable: true,
179
    enumerable: true
180
  });
181
});
182

    
183

    
184
exports.createHash = exports.Hash = Hash;
185
function Hash(algorithm, options) {
186
  if (!(this instanceof Hash))
187
    return new Hash(algorithm, options);
188
  this._binding = new binding.Hash(algorithm);
189
  LazyTransform.call(this, options);
190
}
191

    
192
util.inherits(Hash, LazyTransform);
193

    
194
Hash.prototype._transform = function(chunk, encoding, callback) {
195
  this._binding.update(chunk, encoding);
196
  callback();
197
};
198

    
199
Hash.prototype._flush = function(callback) {
200
  var encoding = this._readableState.encoding || 'buffer';
201
  this.push(this._binding.digest(encoding), encoding);
202
  callback();
203
};
204

    
205
Hash.prototype.update = function(data, encoding) {
206
  encoding = encoding || exports.DEFAULT_ENCODING;
207
  if (encoding === 'buffer' && typeof data === 'string')
208
    encoding = 'binary';
209
  this._binding.update(data, encoding);
210
  return this;
211
};
212

    
213

    
214
Hash.prototype.digest = function(outputEncoding) {
215
  outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
216
  return this._binding.digest(outputEncoding);
217
};
218

    
219

    
220
exports.createHmac = exports.Hmac = Hmac;
221

    
222
function Hmac(hmac, key, options) {
223
  if (!(this instanceof Hmac))
224
    return new Hmac(hmac, key, options);
225
  this._binding = new binding.Hmac();
226
  this._binding.init(hmac, toBuf(key));
227
  LazyTransform.call(this, options);
228
}
229

    
230
util.inherits(Hmac, LazyTransform);
231

    
232
Hmac.prototype.update = Hash.prototype.update;
233
Hmac.prototype.digest = Hash.prototype.digest;
234
Hmac.prototype._flush = Hash.prototype._flush;
235
Hmac.prototype._transform = Hash.prototype._transform;
236

    
237

    
238
function getDecoder(decoder, encoding) {
239
  decoder = decoder || new StringDecoder(encoding);
240
  assert(decoder.encoding === encoding, 'Cannot change encoding');
241
  return decoder;
242
}
243

    
244

    
245
exports.createCipher = exports.Cipher = Cipher;
246
function Cipher(cipher, password, options) {
247
  if (!(this instanceof Cipher))
248
    return new Cipher(cipher, password, options);
249
  this._binding = new binding.Cipher;
250

    
251
  this._binding.init(cipher, toBuf(password));
252
  this._decoder = null;
253

    
254
  LazyTransform.call(this, options);
255
}
256

    
257
util.inherits(Cipher, LazyTransform);
258

    
259
Cipher.prototype._transform = function(chunk, encoding, callback) {
260
  this.push(this._binding.update(chunk, encoding));
261
  callback();
262
};
263

    
264
Cipher.prototype._flush = function(callback) {
265
  this.push(this._binding.final());
266
  callback();
267
};
268

    
269
Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
270
  inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
271
  outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
272

    
273
  var ret = this._binding.update(data, inputEncoding);
274

    
275
  if (outputEncoding && outputEncoding !== 'buffer') {
276
    this._decoder = getDecoder(this._decoder, outputEncoding);
277
    ret = this._decoder.write(ret);
278
  }
279

    
280
  return ret;
281
};
282

    
283

    
284
Cipher.prototype.final = function(outputEncoding) {
285
  outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
286
  var ret = this._binding.final();
287

    
288
  if (outputEncoding && outputEncoding !== 'buffer') {
289
    this._decoder = getDecoder(this._decoder, outputEncoding);
290
    ret = this._decoder.end(ret);
291
  }
292

    
293
  return ret;
294
};
295

    
296

    
297
Cipher.prototype.setAutoPadding = function(ap) {
298
  this._binding.setAutoPadding(ap);
299
  return this;
300
};
301

    
302

    
303

    
304
exports.createCipheriv = exports.Cipheriv = Cipheriv;
305
function Cipheriv(cipher, key, iv, options) {
306
  if (!(this instanceof Cipheriv))
307
    return new Cipheriv(cipher, key, iv, options);
308
  this._binding = new binding.Cipher();
309
  this._binding.initiv(cipher, toBuf(key), toBuf(iv));
310
  this._decoder = null;
311

    
312
  LazyTransform.call(this, options);
313
}
314

    
315
util.inherits(Cipheriv, LazyTransform);
316

    
317
Cipheriv.prototype._transform = Cipher.prototype._transform;
318
Cipheriv.prototype._flush = Cipher.prototype._flush;
319
Cipheriv.prototype.update = Cipher.prototype.update;
320
Cipheriv.prototype.final = Cipher.prototype.final;
321
Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
322

    
323

    
324

    
325
exports.createDecipher = exports.Decipher = Decipher;
326
function Decipher(cipher, password, options) {
327
  if (!(this instanceof Decipher))
328
    return new Decipher(cipher, password, options);
329

    
330
  this._binding = new binding.Decipher;
331
  this._binding.init(cipher, toBuf(password));
332
  this._decoder = null;
333

    
334
  LazyTransform.call(this, options);
335
}
336

    
337
util.inherits(Decipher, LazyTransform);
338

    
339
Decipher.prototype._transform = Cipher.prototype._transform;
340
Decipher.prototype._flush = Cipher.prototype._flush;
341
Decipher.prototype.update = Cipher.prototype.update;
342
Decipher.prototype.final = Cipher.prototype.final;
343
Decipher.prototype.finaltol = Cipher.prototype.final;
344
Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
345

    
346

    
347

    
348
exports.createDecipheriv = exports.Decipheriv = Decipheriv;
349
function Decipheriv(cipher, key, iv, options) {
350
  if (!(this instanceof Decipheriv))
351
    return new Decipheriv(cipher, key, iv, options);
352

    
353
  this._binding = new binding.Decipher;
354
  this._binding.initiv(cipher, toBuf(key), toBuf(iv));
355
  this._decoder = null;
356

    
357
  LazyTransform.call(this, options);
358
}
359

    
360
util.inherits(Decipheriv, LazyTransform);
361

    
362
Decipheriv.prototype._transform = Cipher.prototype._transform;
363
Decipheriv.prototype._flush = Cipher.prototype._flush;
364
Decipheriv.prototype.update = Cipher.prototype.update;
365
Decipheriv.prototype.final = Cipher.prototype.final;
366
Decipheriv.prototype.finaltol = Cipher.prototype.final;
367
Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
368

    
369

    
370

    
371
exports.createSign = exports.Sign = Sign;
372
function Sign(algorithm, options) {
373
  if (!(this instanceof Sign))
374
    return new Sign(algorithm, options);
375
  this._binding = new binding.Sign();
376
  this._binding.init(algorithm);
377

    
378
  stream.Writable.call(this, options);
379
}
380

    
381
util.inherits(Sign, stream.Writable);
382

    
383
Sign.prototype._write = function(chunk, encoding, callback) {
384
  this._binding.update(chunk, encoding);
385
  callback();
386
};
387

    
388
Sign.prototype.update = Hash.prototype.update;
389

    
390
Sign.prototype.sign = function(key, encoding) {
391
  encoding = encoding || exports.DEFAULT_ENCODING;
392
  var ret = this._binding.sign(toBuf(key));
393

    
394
  if (encoding && encoding !== 'buffer')
395
    ret = ret.toString(encoding);
396

    
397
  return ret;
398
};
399

    
400

    
401

    
402
exports.createVerify = exports.Verify = Verify;
403
function Verify(algorithm, options) {
404
  if (!(this instanceof Verify))
405
    return new Verify(algorithm, options);
406

    
407
  this._binding = new binding.Verify;
408
  this._binding.init(algorithm);
409

    
410
  stream.Writable.call(this, options);
411
}
412

    
413
util.inherits(Verify, stream.Writable);
414

    
415
Verify.prototype._write = Sign.prototype._write;
416
Verify.prototype.update = Sign.prototype.update;
417

    
418
Verify.prototype.verify = function(object, signature, sigEncoding) {
419
  sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
420
  return this._binding.verify(toBuf(object), toBuf(signature, sigEncoding));
421
};
422

    
423

    
424

    
425
exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
426

    
427
function DiffieHellman(sizeOrKey, encoding) {
428
  if (!(this instanceof DiffieHellman))
429
    return new DiffieHellman(sizeOrKey, encoding);
430

    
431
  if (!sizeOrKey)
432
    this._binding = new binding.DiffieHellman();
433
  else {
434
    encoding = encoding || exports.DEFAULT_ENCODING;
435
    sizeOrKey = toBuf(sizeOrKey, encoding);
436
    this._binding = new binding.DiffieHellman(sizeOrKey);
437
  }
438
}
439

    
440

    
441
exports.DiffieHellmanGroup =
442
    exports.createDiffieHellmanGroup =
443
    exports.getDiffieHellman = DiffieHellmanGroup;
444

    
445
function DiffieHellmanGroup(name) {
446
  if (!(this instanceof DiffieHellmanGroup))
447
    return new DiffieHellmanGroup(name);
448
  this._binding = new binding.DiffieHellmanGroup(name);
449
}
450

    
451

    
452
DiffieHellmanGroup.prototype.generateKeys =
453
    DiffieHellman.prototype.generateKeys =
454
    dhGenerateKeys;
455

    
456
function dhGenerateKeys(encoding) {
457
  var keys = this._binding.generateKeys();
458
  encoding = encoding || exports.DEFAULT_ENCODING;
459
  if (encoding && encoding !== 'buffer')
460
    keys = keys.toString(encoding);
461
  return keys;
462
}
463

    
464

    
465
DiffieHellmanGroup.prototype.computeSecret =
466
    DiffieHellman.prototype.computeSecret =
467
    dhComputeSecret;
468

    
469
function dhComputeSecret(key, inEnc, outEnc) {
470
  inEnc = inEnc || exports.DEFAULT_ENCODING;
471
  outEnc = outEnc || exports.DEFAULT_ENCODING;
472
  var ret = this._binding.computeSecret(toBuf(key, inEnc));
473
  if (outEnc && outEnc !== 'buffer')
474
    ret = ret.toString(outEnc);
475
  return ret;
476
}
477

    
478

    
479
DiffieHellmanGroup.prototype.getPrime =
480
    DiffieHellman.prototype.getPrime =
481
    dhGetPrime;
482

    
483
function dhGetPrime(encoding) {
484
  var prime = this._binding.getPrime();
485
  encoding = encoding || exports.DEFAULT_ENCODING;
486
  if (encoding && encoding !== 'buffer')
487
    prime = prime.toString(encoding);
488
  return prime;
489
}
490

    
491

    
492
DiffieHellmanGroup.prototype.getGenerator =
493
    DiffieHellman.prototype.getGenerator =
494
    dhGetGenerator;
495

    
496
function dhGetGenerator(encoding) {
497
  var generator = this._binding.getGenerator();
498
  encoding = encoding || exports.DEFAULT_ENCODING;
499
  if (encoding && encoding !== 'buffer')
500
    generator = generator.toString(encoding);
501
  return generator;
502
}
503

    
504

    
505
DiffieHellmanGroup.prototype.getPublicKey =
506
    DiffieHellman.prototype.getPublicKey =
507
    dhGetPublicKey;
508

    
509
function dhGetPublicKey(encoding) {
510
  var key = this._binding.getPublicKey();
511
  encoding = encoding || exports.DEFAULT_ENCODING;
512
  if (encoding && encoding !== 'buffer')
513
    key = key.toString(encoding);
514
  return key;
515
}
516

    
517

    
518
DiffieHellmanGroup.prototype.getPrivateKey =
519
    DiffieHellman.prototype.getPrivateKey =
520
    dhGetPrivateKey;
521

    
522
function dhGetPrivateKey(encoding) {
523
  var key = this._binding.getPrivateKey();
524
  encoding = encoding || exports.DEFAULT_ENCODING;
525
  if (encoding && encoding !== 'buffer')
526
    key = key.toString(encoding);
527
  return key;
528
}
529

    
530

    
531
DiffieHellman.prototype.setPublicKey = function(key, encoding) {
532
  encoding = encoding || exports.DEFAULT_ENCODING;
533
  this._binding.setPublicKey(toBuf(key, encoding));
534
  return this;
535
};
536

    
537

    
538
DiffieHellman.prototype.setPrivateKey = function(key, encoding) {
539
  encoding = encoding || exports.DEFAULT_ENCODING;
540
  this._binding.setPrivateKey(toBuf(key, encoding));
541
  return this;
542
};
543

    
544

    
545

    
546
exports.pbkdf2 = function(password, salt, iterations, keylen, callback) {
547
  if (typeof callback !== 'function')
548
    throw new Error('No callback provided to pbkdf2');
549

    
550
  return pbkdf2(password, salt, iterations, keylen, callback);
551
};
552

    
553

    
554
exports.pbkdf2Sync = function(password, salt, iterations, keylen) {
555
  return pbkdf2(password, salt, iterations, keylen);
556
};
557

    
558

    
559
function pbkdf2(password, salt, iterations, keylen, callback) {
560
  password = toBuf(password);
561
  salt = toBuf(salt);
562

    
563
  if (exports.DEFAULT_ENCODING === 'buffer')
564
    return binding.PBKDF2(password, salt, iterations, keylen, callback);
565

    
566
  // at this point, we need to handle encodings.
567
  var encoding = exports.DEFAULT_ENCODING;
568
  if (callback) {
569
    binding.PBKDF2(password, salt, iterations, keylen, function(er, ret) {
570
      if (ret)
571
        ret = ret.toString(encoding);
572
      callback(er, ret);
573
    });
574
  } else {
575
    var ret = binding.PBKDF2(password, salt, iterations, keylen);
576
    return ret.toString(encoding);
577
  }
578
}
579

    
580

    
581

    
582
exports.randomBytes = randomBytes;
583
exports.pseudoRandomBytes = pseudoRandomBytes;
584

    
585
exports.rng = randomBytes;
586
exports.prng = pseudoRandomBytes;
587

    
588

    
589
exports.getCiphers = function() {
590
  return filterDuplicates(getCiphers.call(null, arguments));
591
};
592

    
593

    
594
exports.getHashes = function() {
595
  return filterDuplicates(getHashes.call(null, arguments));
596

    
597
};
598

    
599

    
600
function filterDuplicates(names) {
601
  // Drop all-caps names in favor of their lowercase aliases,
602
  // for example, 'sha1' instead of 'SHA1'.
603
  var ctx = {};
604
  names.forEach(function(name) {
605
    if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase();
606
    ctx[name] = true;
607
  });
608
  return Object.getOwnPropertyNames(ctx).sort();
609
}