Skip to content

Commit

Permalink
Singleline private keys (node-saml#423)
Browse files Browse the repository at this point in the history
* feat: single line private keys allowed

* docs: document single line private keys option

* docs: document hashing algs selection with opinionated comments
  • Loading branch information
big kahuna burger authored Feb 19, 2020
1 parent a224a31 commit fb1bda0
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 7 deletions.
42 changes: 38 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,47 @@ The `generateServiceProviderMetadata` method is also available on the `MultiSaml
Passport-SAML uses the HTTP Redirect Binding for its `AuthnRequest`s (unless overridden with the `authnRequestBinding` parameter), and expects to receive the messages back via the HTTP POST binding.
Authentication requests sent by Passport-SAML can be signed using RSA-SHA1. To sign them you need to provide a private key in the PEM format via the `privateCert` configuration key. The certificate
should start with `-----BEGIN PRIVATE KEY-----` on its own line and end with `-----END PRIVATE KEY-----` on its own line.
Authentication requests sent by Passport-SAML can be signed using RSA signature with SHA1, SHA256 or SHA512 hashing algorithms.
For example:
To select hashing algorithm, use:
```js
...
signatureAlgorithm: 'sha1' // (default, but not recommended anymore these days)
signatureAlgorithm: 'sha256', // (preffered - your IDP should support it, otherwise think about upgrading it)
signatureAlgorithm: 'sha512' // (most secure - check if your IDP supports it)
...
```
To sign them you need to provide a private key in the PEM format via the `privateCert` configuration key.
Formats supported for `privateCert` field are,
1. Well formatted PEM:
```
-----BEGIN PRIVATE KEY-----
<private key contents here delimited at 64 characters per row>
-----END PRIVATE KEY-----

```
```
-----BEGIN RSA PRIVATE KEY-----
<private key contents here delimited at 64 characters per row>
-----END RSA PRIVATE KEY-----

```
(both versions work)
See example from tests of the first version of [well formatted private key](test/static/acme_tools_com.key).
2. Alternativelly a single line private key without start/end lines where all rows are joined into single line:
See example from tests of [singleline private key](test/static/singleline_acme_tools_com.key).
Add it to strategy options like this:
```javascript
privateCert: fs.readFileSync('./cert.pem', 'utf-8')
privateCert: fs.readFileSync('./privateCert.pem', 'utf-8')
```
Expand Down
17 changes: 16 additions & 1 deletion lib/passport-saml/saml.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ SAML.prototype.signRequest = function (samlMessage) {
samlMessageToSign.SigAlg = samlMessage.SigAlg;
}
signer.update(querystring.stringify(samlMessageToSign));
samlMessage.Signature = signer.sign(this.options.privateCert, 'base64');
samlMessage.Signature = signer.sign(this.keyToPEM(this.options.privateCert), 'base64');
};

SAML.prototype.generateAuthorizeRequest = function (req, isPassive, isHttpPostBinding, callback) {
Expand Down Expand Up @@ -1290,4 +1290,19 @@ SAML.prototype.generateServiceProviderMetadata = function( decryptionCert, signi
return xmlbuilder.create(metadata).end({ pretty: true, indent: ' ', newline: '\n' });
};

SAML.prototype.keyToPEM = function (key) {
if (!key || typeof key !== 'string') return key;

const lines = key.split('\n');
if (lines.length !== 1) return key;

const wrappedKey = [
'-----BEGIN PRIVATE KEY-----',
...key.match(/.{1,64}/g),
'-----END PRIVATE KEY-----',
''
].join('\n');
return wrappedKey;
};

exports.SAML = SAML;
40 changes: 38 additions & 2 deletions test/samlTests.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use strict';
var fs = require('fs');
var url = require('url');
var should = require('should');

var SAML = require('../lib/passport-saml/saml.js').SAML;
var should = require('should');
var url = require('url');

describe('SAML.js', function () {
describe('get Urls', function () {
Expand Down Expand Up @@ -232,5 +233,40 @@ describe('SAML.js', function () {
});
});
});

describe('keyToPEM', function () {
var [regular, singleline] = [
'acme_tools_com.key',
'singleline_acme_tools_com.key'
].map(keyFromFile);

it('formats singleline keys properly', function (done) {
var result = saml.keyToPEM(singleline);
result.should.equal(regular);
done();
});

it('passes all other multiline keys', function (done) {
var result = saml.keyToPEM(regular);
result.should.equal(regular);
done();
});

it('does nothing to falsy', function (done) {
var result = saml.keyToPEM(null);
should.equal(result, null);
done();
});

it('does nothing to non strings', function (done) {
var result = saml.keyToPEM(1);
should.equal(result, 1);
done();
});
});
});
});

function keyFromFile (file) {
return fs.readFileSync(`./test/static/${file}`).toString();
}
1 change: 1 addition & 0 deletions test/static/singleline_acme_tools_com.key
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJP47MTKaFpkU1/Hj4cXFlsE/d6C9xSA+8ZrvBYJXu/K4Jq4sGrA7UVCrNpEPGQSKGQeqZTPrcPbm/ZCLEvFfKpoVDxPEMUrBgBO1IvvHkbYbDDnofQvVcaBh01bVqQ/H3Q/5RKZWfVZv//sDBT5NX67iMiApnJNogVZ0WXAGGWng4EQcLJjCeAWAzJWgIGxKbBviJ/syLlPvjon1kxCkL62z6R/OV7Ln03Pnmlrl9EvC7irEVS/ahF1cB/Zku7EHsM9BtEfzb97Blnw3gFQaJDIDA6weCnSxv0kny4Qz+qHJLV1dfGOj6TGwjkdeHGng/lH1UAO46q5osijym0itAgMBAAECggEAOEGbotp/9BxfJAPwU5pwK0gea4oSOTAK/YKd4UNSrWcWQ3aaM25Hk/yDIwbvXQg5yVDhqol6lrJ4I6fTSgBl+L75lMcE22xhX75VF4GK51AT0ONvFlqcsfhV8rNfyazgY8qjLGth4iVKq+tCOXCVLOVlSWnQ0Mwnjak+TZYQfSQb9a6KZWwkTkoMf38q52iSkc3zbqUG0xYoGfpUNhdULrna8C6m6yGh+odG9kennHKBePf38M1sa3cCyriAm0TrKUG+OIAIJPV+PN2q14Vn/o9YW6uxj4GD/abBJZzFgt6aEGhJxSjwogEBT8U9SjhwBGwetL2A7T6NOoQkyWyKHQKBgQDGj4PMYtxUV9Cd50C5ekh2NQBLEsGd6DGrkJe2OrLuqDOmpxOdtGnAI7s0oiBNB2gYuTd8T+zL+FdN9vKJc9OJ9dZ0zgHKVoajff8ZB6QDkvGXGKZNbYjnsbuJYAuMg7fE0HZ7DZnBmArbRO1RtfbRf31Pfj2bpuaEWLPr3BbDewKBgQDC3g9XKKsaS+Eg3phgRYBfLL7j33vM5nGe1GrogVu3gNvirLoQLq60lSCzaWIwq0d9m+7nM9xgY9BeA6rxFWms0wWAxBW5Dj+UrRNjAa5KFav1IPVNBkzkoUfXc+WskgZBneDJt87Xif0NdnwvZPufvTzYLtgp7uf1tACOB0v39wKBgQCkvhglMPULiZyOFnuOKFYMtWbb4uD/ydHEPgCR8lvZRXctUzwkQbbn8v106vsPzhBhSvMtUgbvKMoO5tBOmOovcegQG4hCv82Pwo8vzjYXvQhzS8FXRoUrbzxg+245lGOZiTh0WlFy3VpMmQCqJeZ15Wgr11r4VN63ef01uPKuFwKBgDFTXlS0oaL1ZBYa4j00Ootc2zD5J/A0wLvwjuMto1au0nntOOfRuT1SpkVjvowNPvpnlzCE6xqnCV5S1VlTDz3E6Jawi8Mc/TEYIlkkWsa795wD7LPDjYEt5e5+krt89wJzASxuT3g1oI1g2YxxplPH5ffe2665n5ONLbrF1A//AoGAUKM5N826wiZqmYCa+eC1TVz12iprlIdW0wOoBL5hcDRDd7u0ninTSiv9mAE5RYJVHEF3PchmQFTs9i3OJXGXYDWU73kHhzgYnEC+vDxDq/6Q8BOhicRyBZ7faQ3oNnGTUzIioiBoQtmJ9axJZVNs3tfYUpxvwr43am35OSeC3aI=

0 comments on commit fb1bda0

Please sign in to comment.