xml-encryption
Advanced tools
Comparing version 0.9.0 to 0.10.0
@@ -13,3 +13,3 @@ var crypto = require('crypto'); | ||
var base64EncodedEncryptedKey = new Buffer(encrypted, 'binary').toString('base64'); | ||
var params = { | ||
@@ -20,3 +20,3 @@ encryptedKey: base64EncodedEncryptedKey, | ||
}; | ||
var result = utils.renderTemplate('keyinfo', params); | ||
@@ -36,3 +36,3 @@ callback(null, result); | ||
return callback(new Error('must provide options.pem with certificate')); | ||
if (!options.keyEncryptionAlgorighm) | ||
@@ -128,4 +128,2 @@ return callback(new Error('encryption without encrypted key is not supported yet')); | ||
return callback(new Error('key option is mandatory and you should provide a valid RSA private key')); | ||
var decrypted; | ||
@@ -139,47 +137,13 @@ try { | ||
var decipher; | ||
var padding; | ||
var encryptedContent = xpath.select("//*[local-name(.)='EncryptedData']/*[local-name(.)='CipherData']/*[local-name(.)='CipherValue']", doc)[0]; | ||
var encrypted = new Buffer(encryptedContent.textContent, 'base64'); | ||
switch (encryptionAlgorithm) { | ||
case 'http://www.w3.org/2001/04/xmlenc#aes128-cbc': | ||
decipher = crypto.createDecipheriv('aes-128-cbc', symmetricKey, encrypted.slice(0, 16)); | ||
decipher.setAutoPadding(false); | ||
decrypted = decipher.update(encrypted.slice(16), null, 'binary') + decipher.final('binary'); | ||
// Remove padding bytes equal to the value of the last byte of the returned data. | ||
padding = decrypted.charCodeAt(decrypted.length - 1); | ||
if (1 <= padding && padding <= 16) { | ||
decrypted = decrypted.substr(0, decrypted.length - padding); | ||
} else { | ||
callback(new Error('padding length invalid')); | ||
return; | ||
} | ||
decrypted = new Buffer(decrypted, 'binary').toString('utf8'); | ||
break; | ||
return callback(null, decryptWithAlgorithm('aes-128-cbc', symmetricKey, 16, encrypted)); | ||
case 'http://www.w3.org/2001/04/xmlenc#aes256-cbc': | ||
decipher = crypto.createDecipheriv('aes-256-cbc', symmetricKey, encrypted.slice(0, 16)); | ||
decipher.setAutoPadding(false); | ||
decrypted = decipher.update(encrypted.slice(16), null, 'binary') + decipher.final('binary'); | ||
// Remove padding bytes equal to the value of the last byte of the returned data. | ||
padding = decrypted.charCodeAt(decrypted.length - 1); | ||
if (1 <= padding && padding <= 16) { | ||
decrypted = decrypted.substr(0, decrypted.length - padding); | ||
} else { | ||
callback(new Error('padding length invalid')); | ||
return; | ||
} | ||
decrypted = new Buffer(decrypted, 'binary').toString('utf8'); | ||
break; | ||
return callback(null, decryptWithAlgorithm('aes-256-cbc', symmetricKey, 16, encrypted)); | ||
case 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc': | ||
decipher = crypto.createDecipheriv('des-ede3-cbc', symmetricKey, encrypted.slice(0,8)); | ||
decrypted = decipher.update(encrypted.slice(8), null, 'binary') + decipher.final('binary'); | ||
decrypted = new Buffer(decrypted, 'binary').toString('utf8'); | ||
break; | ||
return callback(null, decryptWithAlgorithm('des-ede3-cbc', symmetricKey, 8, encrypted)); | ||
default: | ||
@@ -191,4 +155,2 @@ return callback(new Error('encryption algorithm ' + encryptionAlgorithm + ' not supported')); | ||
} | ||
callback(null, decrypted); | ||
} | ||
@@ -202,3 +164,3 @@ | ||
var keyEncryptionMethod = xpath.select("//*[local-name(.)='KeyInfo']/*[local-name(.)='EncryptedKey']/*[local-name(.)='EncryptionMethod']", doc)[0]; | ||
if (!keyEncryptionMethod) { // try with EncryptedData->KeyInfo->RetrievalMethod | ||
@@ -245,3 +207,3 @@ var keyRetrievalMethod = xpath.select("//*[local-name(.)='EncryptedData']/*[local-name(.)='KeyInfo']/*[local-name(.)='RetrievalMethod']", doc)[0]; | ||
if (err) return callback(err); | ||
var cipher = crypto.createCipheriv(algorithm, symmetricKey, iv); | ||
@@ -254,2 +216,20 @@ // encrypted content | ||
function decryptWithAlgorithm(algorithm, symmetricKey, ivLength, content) { | ||
var decipher = crypto.createDecipheriv(algorithm, symmetricKey, content.slice(0,ivLength)); | ||
decipher.setAutoPadding(false); | ||
var decrypted = decipher.update(content.slice(ivLength), null, 'binary') + decipher.final('binary'); | ||
// Remove padding bytes equal to the value of the last byte of the returned data. | ||
var padding = decrypted.charCodeAt(decrypted.length - 1); | ||
if (1 <= padding && padding <= ivLength) { | ||
decrypted = decrypted.substr(0, decrypted.length - padding); | ||
} else { | ||
callback(new Error('padding length invalid')); | ||
return; | ||
} | ||
return new Buffer(decrypted, 'binary').toString('utf8'); | ||
} | ||
exports = module.exports = { | ||
@@ -256,0 +236,0 @@ decrypt: decrypt, |
{ | ||
"name": "xml-encryption", | ||
"version": "0.9.0", | ||
"version": "0.10.0", | ||
"devDependencies": { | ||
@@ -5,0 +5,0 @@ "mocha": "*", |
@@ -11,81 +11,30 @@ var assert = require('assert'), | ||
it('should encrypt and decrypt xml (aes256-cbc)', function (done) { | ||
// cert created with: | ||
// openssl req -x509 -new -newkey rsa:2048 -nodes -subj '/CN=auth0.auth0.com/O=Auth0 LLC/C=US/ST=Washington/L=Redmond' -keyout auth0.key -out auth0.pem | ||
// pub key extracted from (only the RSA public key between BEGIN PUBLIC KEY and END PUBLIC KEY) | ||
// openssl x509 -in "test-auth0.pem" -pubkey | ||
var options = { | ||
rsa_pub: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'), | ||
pem: fs.readFileSync(__dirname + '/test-auth0.pem'), | ||
key: fs.readFileSync(__dirname + '/test-auth0.key'), | ||
var algorithms = [{ | ||
name: 'aes-256-cbc', | ||
encryptionOptions: { | ||
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc', | ||
keyEncryptionAlgorighm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' | ||
}; | ||
xmlenc.encrypt('content to encrypt', options, function(err, result) { | ||
xmlenc.decrypt(result, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function(err, decrypted) { | ||
assert.equal(decrypted, 'content to encrypt'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('should encrypt and decrypt xml (aes256-cbc with utf8 chars)', function (done) { | ||
// cert created with: | ||
// openssl req -x509 -new -newkey rsa:2048 -nodes -subj '/CN=auth0.auth0.com/O=Auth0 LLC/C=US/ST=Washington/L=Redmond' -keyout auth0.key -out auth0.pem | ||
// pub key extracted from (only the RSA public key between BEGIN PUBLIC KEY and END PUBLIC KEY) | ||
// openssl x509 -in "test-auth0.pem" -pubkey | ||
var options = { | ||
rsa_pub: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'), | ||
pem: fs.readFileSync(__dirname + '/test-auth0.pem'), | ||
key: fs.readFileSync(__dirname + '/test-auth0.key'), | ||
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc', | ||
keyEncryptionAlgorighm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' | ||
}; | ||
xmlenc.encrypt('Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge', options, function(err, result) { | ||
xmlenc.decrypt(result, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function(err, decrypted) { | ||
assert.equal(decrypted, 'Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge'); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
it('should encrypt and decrypt xml (aes128-cbc) with utf8 chars', function (done) { | ||
// cert created with: | ||
// openssl req -x509 -new -newkey rsa:2048 -nodes -subj '/CN=auth0.auth0.com/O=Auth0 LLC/C=US/ST=Washington/L=Redmond' -keyout auth0.key -out auth0.pem | ||
// pub key extracted from (only the RSA public key between BEGIN PUBLIC KEY and END PUBLIC KEY) | ||
// openssl x509 -in "test-auth0.pem" -pubkey | ||
var options = { | ||
rsa_pub: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'), | ||
pem: fs.readFileSync(__dirname + '/test-auth0.pem'), | ||
key: fs.readFileSync(__dirname + '/test-auth0.key'), | ||
} | ||
}, { | ||
name: 'aes-128-cbc', | ||
encryptionOptions: { | ||
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes128-cbc', | ||
keyEncryptionAlgorighm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' | ||
}; | ||
} | ||
}, { | ||
name: 'des-ede3-cbc', | ||
encryptionOptions: { | ||
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc', | ||
keyEncryptionAlgorighm: 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' | ||
} | ||
}]; | ||
xmlenc.encrypt('Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge', options, function (err, result) { | ||
xmlenc.decrypt(result, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function (err, decrypted) { | ||
assert.equal(decrypted, 'Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge'); | ||
done(); | ||
algorithms.forEach(function (algorithm) { | ||
describe(algorithm.name, function () { | ||
it('should encrypt and decrypt xml', function (done) { | ||
_shouldEncryptAndDecrypt('content to encrypt', algorithm.encryptionOptions, done); | ||
}); | ||
}); | ||
}); | ||
it('should encrypt and decrypt xml (aes128-cbc)', function (done) { | ||
var options = { | ||
rsa_pub: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'), | ||
pem: fs.readFileSync(__dirname + '/test-auth0.pem'), | ||
key: fs.readFileSync(__dirname + '/test-auth0.key'), | ||
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes128-cbc', | ||
keyEncryptionAlgorighm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' | ||
}; | ||
xmlenc.encrypt('content to encrypt', options, function (err, result) { | ||
xmlenc.decrypt(result, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function (err, decrypted) { | ||
assert.equal(decrypted, 'content to encrypt'); | ||
done(); | ||
it('should encrypt and decrypt xml with utf8 chars', function (done) { | ||
_shouldEncryptAndDecrypt('Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge Gnügge', algorithm.encryptionOptions, done); | ||
}); | ||
@@ -95,23 +44,19 @@ }); | ||
it('should encrypt and decrypt xml (encryption: http://www.w3.org/2001/04/xmlenc#tripledes-cbc, keyEncryption: http://www.w3.org/2001/04/xmlenc#rsa-1_5)', function (done) { | ||
function _shouldEncryptAndDecrypt(content, options, done) { | ||
// cert created with: | ||
// openssl req -x509 -new -newkey rsa:2048 -nodes -subj '/CN=auth0.auth0.com/O=Auth0 LLC/C=US/ST=Washington/L=Redmond' -keyout auth0.key -out auth0.pem | ||
// pub key extracted from (only the RSA public key between BEGIN PUBLIC KEY and END PUBLIC KEY) | ||
// openssl x509 -in "test-auth0.pem" -pubkey | ||
// openssl x509 -in "test-auth0.pem" -pubkey | ||
var options = { | ||
rsa_pub: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'), | ||
pem: fs.readFileSync(__dirname + '/test-auth0.pem'), | ||
key: fs.readFileSync(__dirname + '/test-auth0.key'), | ||
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc', | ||
keyEncryptionAlgorighm: 'http://www.w3.org/2001/04/xmlenc#rsa-1_5' | ||
}; | ||
options.rsa_pub = fs.readFileSync(__dirname + '/test-auth0_rsa.pub'), | ||
options.pem = fs.readFileSync(__dirname + '/test-auth0.pem'), | ||
options.key = fs.readFileSync(__dirname + '/test-auth0.key'), | ||
xmlenc.encrypt('content to encrypt', options, function(err, result) { | ||
xmlenc.decrypt(result, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function(err, decrypted) { | ||
assert.equal(decrypted, 'content to encrypt'); | ||
xmlenc.encrypt(content, options, function(err, result) { | ||
xmlenc.decrypt(result, { key: fs.readFileSync(__dirname + '/test-auth0.key')}, function (err, decrypted) { | ||
assert.equal(decrypted, content); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
} | ||
@@ -127,3 +72,3 @@ it('should encrypt and decrypt keyinfo', function (done) { | ||
if (err) return done(err); | ||
xmlenc.encryptKeyInfo(randomBytes, options, function(err, result) { | ||
xmlenc.encryptKeyInfo(randomBytes, options, function(err, result) { | ||
if (err) return done(err); | ||
@@ -130,0 +75,0 @@ var decryptedRandomBytes = xmlenc.decryptKeyInfo(result, { key: fs.readFileSync(__dirname + '/test-auth0.key')}); |
50051
317