Skip to content

Commit 41d5738

Browse files
authored
feat: update default encryption algorithm & block insecure algorithms by default (#113)
BREAKING CHANGE: changing default encryption algorithm to http://www.w3.org/2009/xmlenc11#aes256-gcm, adding disallowEncryptionWithInsecureAlgorithm flag to use insecure algorithms for legacy compatibility
1 parent e7856b6 commit 41d5738

File tree

7 files changed

+164
-3
lines changed

7 files changed

+164
-3
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@ var signedAssertion = saml.create(options);
3232

3333
Everything except the cert and key is optional.
3434

35+
### Encryption
36+
37+
SAML assertions can optionally be encrypted, by providing a certificate and public key, as follows:
38+
39+
```js
40+
var saml = require('saml').Saml20; // or Saml11
41+
42+
var options = {
43+
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
44+
key: fs.readFileSync(__dirname + '/test-auth0.key'),
45+
nameIdentifier: 'foo',
46+
encryptionPublicKey: fs.readFileSync(__dirname + '/encryption-key.pub'),
47+
encryptionCert: fs.readFileSync(__dirname + '/encryption-cert.pem'),
48+
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc', // Defaults to http://www.w3.org/2009/xmlenc11#aes256-gcm if not specified
49+
disallowEncryptionWithInsecureAlgorithm: true,
50+
warnOnInsecureEncryptionAlgorithm: true
51+
}
52+
```
53+
54+
See [node-xml-encryption](https://github.com/auth0/node-xml-encryption) for documentation on the allowed algorithms. If using algorithms treated as insecure by [node-xml-encryption](https://github.com/auth0/node-xml-encryption), you must provide disallowEncryptionWithInsecureAlgorithm option set to false.
55+
A warning will be piped to `stderr` using console.warn() by default when the insecure algorithms are used and above mentioned flag is false. This can be disabled via the `warnOnInsecureEncryptionAlgorithm` flag.
56+
57+
3558
## Issue Reporting
3659

3760
If you have found a bug or if you have a feature request, please report them at this repository issues section. Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues.

lib/saml11.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ function extractSaml11Options(opts) {
5656
* @param [options.encryptionPublicKey] {Buffer}
5757
* @param [options.encryptionAlgorithm] {string}
5858
* @param [options.keyEncryptionAlgorithm] {string}
59+
* @param [options.disallowEncryptionWithInsecureAlgorithm] {boolean}
60+
* @param [options.warnOnInsecureEncryptionAlgorithm] {boolean}
5961
*
6062
* @param {Function} [callback] required if encrypting
6163
* @return {String|*}
@@ -89,6 +91,8 @@ exports.create = function(options, callback) {
8991
* @param [options.encryptionPublicKey] {Buffer}
9092
* @param [options.encryptionAlgorithm] {string}
9193
* @param [options.keyEncryptionAlgorithm] {string}
94+
* @param [options.disallowEncryptionWithInsecureAlgorithm] {boolean}
95+
* @param [options.warnOnInsecureEncryptionAlgorithm] {boolean}
9296
*
9397
* @param {Function} [callback] required if encrypting
9498
* @return {String|*}

lib/saml20.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ function extractSaml20Options(opts) {
9595
* @param [options.encryptionPublicKey] {Buffer}
9696
* @param [options.encryptionAlgorithm] {string}
9797
* @param [options.keyEncryptionAlgorithm] {string}
98+
* @param [options.disallowEncryptionWithInsecureAlgorithm] {boolean}
99+
* @param [options.warnOnInsecureEncryptionAlgorithm] {boolean}
98100
*
99101
* @param {Function} [callback] required if encrypting
100102
* @return {*}
@@ -134,6 +136,8 @@ exports.create = function createSignedAssertion(options, callback) {
134136
* @param [options.encryptionPublicKey] {Buffer}
135137
* @param [options.encryptionAlgorithm] {string}
136138
* @param [options.keyEncryptionAlgorithm] {string}
139+
* @param [options.disallowEncryptionWithInsecureAlgorithm] {boolean}
140+
* @param [options.warnOnInsecureEncryptionAlgorithm] {boolean}
137141
*
138142
* @param {Function} [callback] required if encrypting
139143
* @return {*}

lib/xml/encrypt.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ exports.fromEncryptXmlOptions = function (options) {
99
const encryptOptions = {
1010
rsa_pub: options.encryptionPublicKey,
1111
pem: options.encryptionCert,
12-
encryptionAlgorithm: options.encryptionAlgorithm || 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
12+
encryptionAlgorithm: options.encryptionAlgorithm || 'http://www.w3.org/2009/xmlenc11#aes256-gcm',
1313
keyEncryptionAlgorithm: options.keyEncryptionAlgorithm || 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p',
14+
disallowEncryptionWithInsecureAlgorithm: options?.disallowEncryptionWithInsecureAlgorithm !== false,
15+
warnInsecureAlgorithm: options?.warnOnInsecureEncryptionAlgorithm !== false,
1416
};
1517

1618
// expose the encryptOptions as these are needed when adding the SubjectConfirmation

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"husky": "^9.1.7",
1313
"mocha": "^8.2.0",
1414
"semantic-release": "^25.0.2",
15-
"should": "~1.2.1"
15+
"should": "~1.2.1",
16+
"sinon": "^9.0.2"
1617
},
1718
"files": [
1819
"lib"
@@ -31,7 +32,7 @@
3132
"moment": "^2.29.4",
3233
"valid-url": "~1.0.9",
3334
"xml-crypto": "^2.1.3",
34-
"xml-encryption": "^2.0.0",
35+
"xml-encryption": "^4.0.0",
3536
"xml-name-validator": "~2.0.1",
3637
"xpath": "0.0.5"
3738
},

test/saml11.tests.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ var xmlenc = require('xml-encryption');
77

88
var utils = require('./utils');
99
var saml11 = require('../lib/saml11');
10+
var sinon = require('sinon');
1011

1112
describe('saml 1.1', function () {
1213

@@ -356,6 +357,14 @@ describe('saml 1.1', function () {
356357
});
357358

358359
describe('encryption', function () {
360+
let consoleSpy = null;
361+
beforeEach(function() {
362+
consoleSpy = sinon.spy(console, 'warn');
363+
});
364+
365+
afterEach(function() {
366+
consoleSpy.restore();
367+
});
359368

360369
it('should create a saml 1.1 encrypted assertion', function (done) {
361370
var options = {
@@ -483,6 +492,60 @@ describe('saml 1.1', function () {
483492
});
484493
});
485494
});
495+
496+
it('should use aes256-gcm as the default encryption algorithm', function (done) {
497+
var options = {
498+
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
499+
key: fs.readFileSync(__dirname + '/test-auth0.key'),
500+
encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
501+
encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem'),
502+
};
503+
504+
saml11[createAssertion](options, function (err, encrypted) {
505+
if (err) return done(err);
506+
var doc = new xmldom.DOMParser().parseFromString(encrypted);
507+
var encryptionMethod = doc.getElementsByTagName('xenc:EncryptionMethod')[0];
508+
assert.equal('http://www.w3.org/2009/xmlenc11#aes256-gcm', encryptionMethod.getAttribute('Algorithm'));
509+
done();
510+
})
511+
});
512+
513+
it('should allow aes256-cbc when disallowEncryptionWithInsecureAlgorithm is false', function (done) {
514+
var options = {
515+
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
516+
key: fs.readFileSync(__dirname + '/test-auth0.key'),
517+
encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
518+
encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem'),
519+
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
520+
disallowEncryptionWithInsecureAlgorithm: false,
521+
warnOnInsecureEncryptionAlgorithm: true,
522+
};
523+
524+
saml11[createAssertion](options, function (err, encrypted) {
525+
if (err) return done(err);
526+
var doc = new xmldom.DOMParser().parseFromString(encrypted);
527+
var encryptionMethod = doc.getElementsByTagName('xenc:EncryptionMethod')[0];
528+
assert.equal('http://www.w3.org/2001/04/xmlenc#aes256-cbc', encryptionMethod.getAttribute('Algorithm'));
529+
assert.equal(consoleSpy.called, true);
530+
done();
531+
});
532+
});
533+
534+
it('should not allow aes256-cbc when disallowEncryptionWithInsecureAlgorithm is true', function (done) {
535+
var options = {
536+
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
537+
key: fs.readFileSync(__dirname + '/test-auth0.key'),
538+
encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
539+
encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem'),
540+
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
541+
disallowEncryptionWithInsecureAlgorithm: true
542+
};
543+
544+
saml11[createAssertion](options, function (err, encrypted) {
545+
assert.ok(err);
546+
done();
547+
});
548+
});
486549
});
487550
});
488551
}

test/saml20.tests.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var moment = require('moment');
55
var should = require('should');
66
var xmldom = require('@xmldom/xmldom');
77
var xmlenc = require('xml-encryption');
8+
var sinon = require('sinon');
89

910
var saml = require('../lib/saml20');
1011

@@ -581,6 +582,14 @@ describe('saml 2.0', function () {
581582
});
582583

583584
describe('encryption', function () {
585+
let consoleSpy = null;
586+
beforeEach(function() {
587+
consoleSpy = sinon.spy(console, 'warn');
588+
});
589+
590+
afterEach(function() {
591+
consoleSpy.restore();
592+
});
584593

585594
it('should create a saml 2.0 signed and encrypted assertion', function (done) {
586595
var options = {
@@ -682,6 +691,61 @@ describe('saml 2.0', function () {
682691
});
683692
});
684693
});
694+
695+
it('should use aes256-gcm as the default encryption algorithm', function (done) {
696+
var options = {
697+
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
698+
key: fs.readFileSync(__dirname + '/test-auth0.key'),
699+
encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
700+
encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem'),
701+
};
702+
703+
saml[createAssertion](options, function (err, encrypted) {
704+
if (err) return done(err);
705+
var encryptedData = utils.getEncryptedData(encrypted);
706+
var encryptionMethod = encryptedData.getElementsByTagName('xenc:EncryptionMethod')[0];
707+
assert.equal('http://www.w3.org/2009/xmlenc11#aes256-gcm', encryptionMethod.getAttribute('Algorithm'));
708+
done();
709+
})
710+
});
711+
712+
it('should allow aes256-cbc when disallowEncryptionWithInsecureAlgorithm is false', function (done) {
713+
var options = {
714+
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
715+
key: fs.readFileSync(__dirname + '/test-auth0.key'),
716+
encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
717+
encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem'),
718+
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
719+
disallowEncryptionWithInsecureAlgorithm: false,
720+
warnOnInsecureEncryptionAlgorithm: true,
721+
};
722+
723+
saml[createAssertion](options, function (err, encrypted) {
724+
if (err) return done(err);
725+
var encryptedData = utils.getEncryptedData(encrypted);
726+
var encryptionMethod = encryptedData.getElementsByTagName('xenc:EncryptionMethod')[0];
727+
assert.equal('http://www.w3.org/2001/04/xmlenc#aes256-cbc', encryptionMethod.getAttribute('Algorithm'));
728+
assert.equal(consoleSpy.called, true);
729+
done();
730+
});
731+
});
732+
733+
it('should not allow aes256-cbc when disallowEncryptionWithInsecureAlgorithm is true', function (done) {
734+
var options = {
735+
cert: fs.readFileSync(__dirname + '/test-auth0.pem'),
736+
key: fs.readFileSync(__dirname + '/test-auth0.key'),
737+
encryptionPublicKey: fs.readFileSync(__dirname + '/test-auth0_rsa.pub'),
738+
encryptionCert: fs.readFileSync(__dirname + '/test-auth0.pem'),
739+
encryptionAlgorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
740+
disallowEncryptionWithInsecureAlgorithm: true
741+
};
742+
743+
saml[createAssertion](options, function (err, encrypted) {
744+
assert.ok(err);
745+
done();
746+
});
747+
});
748+
685749
});
686750
});
687751
}

0 commit comments

Comments
 (0)