Browse Source

crypto: Clean up buffer handling and DH methods

v0.9.3-release
isaacs 12 years ago
parent
commit
c87b524c5f
  1. 248
      lib/crypto.js
  2. 8
      src/node_crypto.cc

248
lib/crypto.js

@ -37,6 +37,20 @@ try {
var crypto = false; var crypto = false;
} }
// This is here because many functions accepted binary strings without
// any explicit encoding in older versions of node, and we don't want
// to break them unnecessarily.
function toBuf(str, encoding) {
encoding = encoding || 'binary';
if (typeof str === 'string') {
if (encoding === 'buffer')
encoding = 'binary';
str = new Buffer(str, encoding);
}
return str;
}
var assert = require('assert'); var assert = require('assert');
var StringDecoder = require('string_decoder').StringDecoder; var StringDecoder = require('string_decoder').StringDecoder;
@ -117,11 +131,11 @@ exports.createCredentials = function(options, context) {
if (options.pfx) { if (options.pfx) {
var pfx = options.pfx; var pfx = options.pfx;
var passphrase = options.passphrase; var passphrase = options.passphrase;
// legacy
if (typeof pfx === 'string') pfx = toBuf(pfx);
pfx = new Buffer(pfx, 'binary'); if (passphrase)
if (passphrase && typeof passphrase === 'string') passphrase = toBuf(passphrase);
passphrase = new Buffer(passphrase, 'binary');
if (passphrase) { if (passphrase) {
c.context.loadPKCS12(pfx, passphrase); c.context.loadPKCS12(pfx, passphrase);
} else { } else {
@ -140,19 +154,18 @@ function Hash(algorithm) {
this._binding = new binding.Hash(algorithm); this._binding = new binding.Hash(algorithm);
} }
Hash.prototype.update = function(data, encoding) { Hash.prototype.update = function(data, encoding) {
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding === 'buffer') data = toBuf(data, encoding);
encoding = null;
if (typeof data === 'string')
data = new Buffer(data, encoding);
this._binding.update(data); this._binding.update(data);
return this; return this;
}; };
Hash.prototype.digest = function(outputEncoding) { Hash.prototype.digest = function(outputEncoding) {
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
var result = this._binding.digest('buffer'); var result = this._binding.digest();
if (outputEncoding && outputEncoding !== 'buffer') if (outputEncoding && outputEncoding !== 'buffer')
result = result.toString(outputEncoding); result = result.toString(outputEncoding);
return result; return result;
@ -165,12 +178,10 @@ function Hmac(hmac, key) {
if (!(this instanceof Hmac)) if (!(this instanceof Hmac))
return new Hmac(hmac, key); return new Hmac(hmac, key);
this._binding = new binding.Hmac(); this._binding = new binding.Hmac();
// legacy this._binding.init(hmac, toBuf(key));
if (typeof key === 'string')
key = new Buffer(key, 'binary');
this._binding.init(hmac, key);
} }
Hmac.prototype.update = Hash.prototype.update; Hmac.prototype.update = Hash.prototype.update;
Hmac.prototype.digest = Hash.prototype.digest; Hmac.prototype.digest = Hash.prototype.digest;
@ -188,21 +199,17 @@ function Cipher(cipher, password) {
return new Cipher(cipher, password); return new Cipher(cipher, password);
this._binding = new binding.Cipher; this._binding = new binding.Cipher;
// legacy. this._binding.init(cipher, toBuf(password));
if (typeof password === 'string')
password = new Buffer(password, 'binary');
this._binding.init(cipher, password);
this._decoder = null; this._decoder = null;
} }
Cipher.prototype.update = function(data, inputEncoding, outputEncoding) { Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
inputEncoding = inputEncoding || exports.DEFAULT_ENCODING; inputEncoding = inputEncoding || exports.DEFAULT_ENCODING;
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
if (inputEncoding && inputEncoding !== 'buffer') data = toBuf(data, inputEncoding);
data = new Buffer(data, inputEncoding);
var ret = this._binding.update(data, 'buffer', 'buffer'); var ret = this._binding.update(data);
if (outputEncoding && outputEncoding !== 'buffer') { if (outputEncoding && outputEncoding !== 'buffer') {
this._decoder = getDecoder(this._decoder, outputEncoding); this._decoder = getDecoder(this._decoder, outputEncoding);
@ -212,9 +219,10 @@ Cipher.prototype.update = function(data, inputEncoding, outputEncoding) {
return ret; return ret;
}; };
Cipher.prototype.final = function(outputEncoding) { Cipher.prototype.final = function(outputEncoding) {
outputEncoding = outputEncoding || exports.DEFAULT_ENCODING; outputEncoding = outputEncoding || exports.DEFAULT_ENCODING;
var ret = this._binding.final('buffer'); var ret = this._binding.final();
if (outputEncoding && outputEncoding !== 'buffer') { if (outputEncoding && outputEncoding !== 'buffer') {
this._decoder = getDecoder(this._decoder, outputEncoding); this._decoder = getDecoder(this._decoder, outputEncoding);
@ -224,6 +232,7 @@ Cipher.prototype.final = function(outputEncoding) {
return ret; return ret;
}; };
Cipher.prototype.setAutoPadding = function(ap) { Cipher.prototype.setAutoPadding = function(ap) {
this._binding.setAutoPadding(ap); this._binding.setAutoPadding(ap);
return this; return this;
@ -235,61 +244,54 @@ exports.createCipheriv = exports.Cipheriv = Cipheriv;
function Cipheriv(cipher, key, iv) { function Cipheriv(cipher, key, iv) {
if (!(this instanceof Cipheriv)) if (!(this instanceof Cipheriv))
return new Cipheriv(cipher, key, iv); return new Cipheriv(cipher, key, iv);
// legacy
if (typeof key === 'string')
key = new Buffer(key, 'binary');
if (typeof iv === 'string')
iv = new Buffer(iv, 'binary');
this._binding = new binding.Cipher(); this._binding = new binding.Cipher();
this._binding.initiv(cipher, key, iv); this._binding.initiv(cipher, toBuf(key), toBuf(iv));
this._decoder = null; this._decoder = null;
} }
Cipheriv.prototype.update = Cipher.prototype.update; Cipheriv.prototype.update = Cipher.prototype.update;
Cipheriv.prototype.final = Cipher.prototype.final; Cipheriv.prototype.final = Cipher.prototype.final;
Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; Cipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
exports.createDecipher = exports.Decipher = Decipher; exports.createDecipher = exports.Decipher = Decipher;
function Decipher(cipher, password) { function Decipher(cipher, password) {
if (!(this instanceof Decipher)) if (!(this instanceof Decipher))
return new Decipher(cipher, password); return new Decipher(cipher, password);
// legacy.
if (typeof password === 'string')
password = new Buffer(password, 'binary');
this._binding = new binding.Decipher; this._binding = new binding.Decipher;
this._binding.init(cipher, password); this._binding.init(cipher, toBuf(password));
this._decoder = null; this._decoder = null;
} }
Decipher.prototype.update = Cipher.prototype.update; Decipher.prototype.update = Cipher.prototype.update;
Decipher.prototype.final = Cipher.prototype.final; Decipher.prototype.final = Cipher.prototype.final;
Decipher.prototype.finaltol = Cipher.prototype.final; Decipher.prototype.finaltol = Cipher.prototype.final;
Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; Decipher.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
exports.createDecipheriv = exports.Decipheriv = Decipheriv; exports.createDecipheriv = exports.Decipheriv = Decipheriv;
function Decipheriv(cipher, key, iv) { function Decipheriv(cipher, key, iv) {
if (!(this instanceof Decipheriv)) if (!(this instanceof Decipheriv))
return new Decipheriv(cipher, key, iv); return new Decipheriv(cipher, key, iv);
// legacy
if (typeof key === 'string')
key = new Buffer(key, 'binary');
if (typeof iv === 'string')
iv = new Buffer(iv, 'binary');
this._binding = new binding.Decipher; this._binding = new binding.Decipher;
this._binding.initiv(cipher, key, iv); this._binding.initiv(cipher, toBuf(key), toBuf(iv));
this._decoder = null; this._decoder = null;
} }
Decipheriv.prototype.update = Cipher.prototype.update; Decipheriv.prototype.update = Cipher.prototype.update;
Decipheriv.prototype.final = Cipher.prototype.final; Decipheriv.prototype.final = Cipher.prototype.final;
Decipheriv.prototype.finaltol = Cipher.prototype.final; Decipheriv.prototype.finaltol = Cipher.prototype.final;
Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding; Decipheriv.prototype.setAutoPadding = Cipher.prototype.setAutoPadding;
exports.createSign = exports.Sign = Sign; exports.createSign = exports.Sign = Sign;
function Sign(algorithm) { function Sign(algorithm) {
if (!(this instanceof Sign)) if (!(this instanceof Sign))
@ -298,21 +300,22 @@ function Sign(algorithm) {
this._binding.init(algorithm); this._binding.init(algorithm);
} }
Sign.prototype.update = Hash.prototype.update; Sign.prototype.update = Hash.prototype.update;
Sign.prototype.sign = function(key, encoding) {
// legacy.
if (typeof key === 'string')
key = new Buffer(key, 'binary');
Sign.prototype.sign = function(key, encoding) {
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
var ret = this._binding.sign(key, 'buffer'); var ret = this._binding.sign(toBuf(key));
if (encoding && encoding !== 'buffer') if (encoding && encoding !== 'buffer')
ret = ret.toString(encoding); ret = ret.toString(encoding);
return ret; return ret;
}; };
exports.createVerify = exports.Verify = Verify; exports.createVerify = exports.Verify = Verify;
function Verify(algorithm) { function Verify(algorithm) {
if (!(this instanceof Verify)) if (!(this instanceof Verify))
@ -322,22 +325,17 @@ function Verify(algorithm) {
this._binding.init(algorithm); this._binding.init(algorithm);
} }
Verify.prototype.update = Hash.prototype.update; Verify.prototype.update = Hash.prototype.update;
Verify.prototype.verify = function(object, signature, sigEncoding) {
// legacy.
if (typeof object === 'string')
object = new Buffer(object, 'binary');
Verify.prototype.verify = function(object, signature, sigEncoding) {
sigEncoding = sigEncoding || exports.DEFAULT_ENCODING; sigEncoding = sigEncoding || exports.DEFAULT_ENCODING;
if (sigEncoding === 'buffer') return this._binding.verify(toBuf(object), toBuf(signature, sigEncoding));
sigEncoding = null;
if (sigEncoding || typeof signature === 'string')
signature = new Buffer(signature, sigEncoding);
return this._binding.verify(object, signature, 'buffer');
}; };
exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman; exports.createDiffieHellman = exports.DiffieHellman = DiffieHellman;
function DiffieHellman(sizeOrKey, encoding) { function DiffieHellman(sizeOrKey, encoding) {
@ -348,124 +346,120 @@ function DiffieHellman(sizeOrKey, encoding) {
this._binding = new binding.DiffieHellman(); this._binding = new binding.DiffieHellman();
else { else {
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding === 'buffer') sizeOrKey = toBuf(sizeOrKey, encoding);
encoding = null; this._binding = new binding.DiffieHellman(sizeOrKey);
if (typeof sizeOrKey === 'string')
sizeOrKey = new Buffer(sizeOrKey, encoding);
this._binding = new binding.DiffieHellman(sizeOrKey, 'buffer');
} }
} }
DiffieHellman.prototype.generateKeys = function(encoding) {
var keys = this._binding.generateKeys('buffer'); exports.DiffieHellmanGroup =
exports.createDiffieHellmanGroup =
exports.getDiffieHellman = DiffieHellmanGroup;
function DiffieHellmanGroup(name) {
if (!(this instanceof DiffieHellmanGroup))
return new DiffieHellmanGroup(name);
this._binding = new binding.DiffieHellmanGroup(name);
}
DiffieHellmanGroup.prototype.generateKeys =
DiffieHellman.prototype.generateKeys =
dhGenerateKeys;
function dhGenerateKeys(encoding) {
var keys = this._binding.generateKeys();
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer') if (encoding && encoding !== 'buffer')
keys = keys.toString(encoding); keys = keys.toString(encoding);
return keys; return keys;
}; }
DiffieHellmanGroup.prototype.computeSecret =
DiffieHellman.prototype.computeSecret =
dhComputeSecret;
DiffieHellman.prototype.computeSecret = function(key, inEnc, outEnc) { function dhComputeSecret(key, inEnc, outEnc) {
inEnc = inEnc || exports.DEFAULT_ENCODING; inEnc = inEnc || exports.DEFAULT_ENCODING;
outEnc = outEnc || exports.DEFAULT_ENCODING; outEnc = outEnc || exports.DEFAULT_ENCODING;
if (inEnc === 'buffer') var ret = this._binding.computeSecret(toBuf(key, inEnc));
inEnc = null; if (outEnc && outEnc !== 'buffer')
if (outEnc === 'buffer')
outEnc = null;
if (inEnc || typeof key === 'string')
key = new Buffer(key, inEnc);
var ret = this._binding.computeSecret(key, 'buffer', 'buffer');
if (outEnc)
ret = ret.toString(outEnc); ret = ret.toString(outEnc);
return ret; return ret;
}; }
DiffieHellman.prototype.getPrime = function(encoding) { DiffieHellmanGroup.prototype.getPrime =
var prime = this._binding.getPrime('buffer'); DiffieHellman.prototype.getPrime =
dhGetPrime;
function dhGetPrime(encoding) {
var prime = this._binding.getPrime();
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer') if (encoding && encoding !== 'buffer')
prime = prime.toString(encoding); prime = prime.toString(encoding);
return prime; return prime;
}; }
DiffieHellman.prototype.getGenerator = function(encoding) { DiffieHellmanGroup.prototype.getGenerator =
var generator = this._binding.getGenerator('buffer'); DiffieHellman.prototype.getGenerator =
dhGetGenerator;
function dhGetGenerator(encoding) {
var generator = this._binding.getGenerator();
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer') if (encoding && encoding !== 'buffer')
generator = generator.toString(encoding); generator = generator.toString(encoding);
return generator; return generator;
}; }
DiffieHellmanGroup.prototype.getPublicKey =
DiffieHellman.prototype.getPublicKey =
dhGetPublicKey;
DiffieHellman.prototype.getPublicKey = function(encoding) { function dhGetPublicKey(encoding) {
var key = this._binding.getPublicKey('buffer'); var key = this._binding.getPublicKey();
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer') if (encoding && encoding !== 'buffer')
key = key.toString(encoding); key = key.toString(encoding);
return key; return key;
}; }
DiffieHellman.prototype.getPrivateKey = function(encoding) { DiffieHellmanGroup.prototype.getPrivateKey =
var key = this._binding.getPrivateKey('buffer'); DiffieHellman.prototype.getPrivateKey =
dhGetPrivateKey;
function dhGetPrivateKey(encoding) {
var key = this._binding.getPrivateKey();
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding && encoding !== 'buffer') if (encoding && encoding !== 'buffer')
key = key.toString(encoding); key = key.toString(encoding);
return key; return key;
}; }
DiffieHellman.prototype.setPublicKey = function(key, encoding) { DiffieHellman.prototype.setPublicKey = function(key, encoding) {
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding === 'buffer') this._binding.setPublicKey(toBuf(key, encoding));
encoding = null;
if (encoding || typeof key === 'string')
key = new Buffer(key, encoding);
this._binding.setPublicKey(key, 'buffer');
return this; return this;
}; };
DiffieHellman.prototype.setPrivateKey = function(key, encoding) { DiffieHellman.prototype.setPrivateKey = function(key, encoding) {
encoding = encoding || exports.DEFAULT_ENCODING; encoding = encoding || exports.DEFAULT_ENCODING;
if (encoding === 'buffer') this._binding.setPrivateKey(toBuf(key, encoding));
encoding = null;
if (encoding || typeof key === 'string')
key = new Buffer(key, encoding);
this._binding.setPrivateKey(key, 'buffer');
return this; return this;
}; };
exports.DiffieHellmanGroup =
exports.createDiffieHellmanGroup =
exports.getDiffieHellman = DiffieHellmanGroup;
function DiffieHellmanGroup(name) {
if (!(this instanceof DiffieHellmanGroup))
return new DiffieHellmanGroup(name);
this._binding = new binding.DiffieHellmanGroup(name);
}
DiffieHellmanGroup.prototype.generateKeys =
DiffieHellman.prototype.generateKeys;
DiffieHellmanGroup.prototype.computeSecret =
DiffieHellman.prototype.computeSecret;
DiffieHellmanGroup.prototype.getPrime =
DiffieHellman.prototype.getPrime;
DiffieHellmanGroup.prototype.getGenerator =
DiffieHellman.prototype.getGenerator;
DiffieHellmanGroup.prototype.getPublicKey =
DiffieHellman.prototype.getPublicKey;
DiffieHellmanGroup.prototype.getPrivateKey =
DiffieHellman.prototype.getPrivateKey;
exports.pbkdf2 = function(password, salt, iterations, keylen, callback) { exports.pbkdf2 = function(password, salt, iterations, keylen, callback) {
if (typeof password === 'string') password = toBuf(password);
password = new Buffer(password, 'binary'); salt = toBuf(salt);
if (typeof salt === 'string')
salt = new Buffer(salt, 'binary');
if (exports.DEFAULT_ENCODING === 'buffer') if (exports.DEFAULT_ENCODING === 'buffer')
return binding.PBKDF2(password, salt, iterations, keylen, callback); return binding.PBKDF2(password, salt, iterations, keylen, callback);

8
src/node_crypto.cc

@ -3602,13 +3602,7 @@ class DiffieHellman : public ObjectWrap {
Local<Value> outString; Local<Value> outString;
if (args.Length() > 2 && args[2]->IsString()) { outString = Encode(data, dataSize, BUFFER);
outString = EncodeWithEncoding(args[2], data, dataSize);
} else if (args.Length() > 1 && args[1]->IsString()) {
outString = EncodeWithEncoding(args[1], data, dataSize);
} else {
outString = Encode(data, dataSize, BUFFER);
}
delete[] data; delete[] data;
return scope.Close(outString); return scope.Close(outString);

Loading…
Cancel
Save