tls: multiple PFX in createSecureContext

Add support for multiple PFX files in tls.createSecureContext.
Also added support for object-style PFX pass.

PR-URL: https://github.com/nodejs/node/pull/14793
Fixes: https://github.com/nodejs/node/issues/14756
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Yury Popov 2017-08-12 19:06:35 +03:00 committed by Ruben Bridgewater
parent 2ffc8ac301
commit 372dc86af5
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
5 changed files with 85 additions and 13 deletions

View File

@ -934,10 +934,14 @@ changes:
--> -->
* `options` {Object} * `options` {Object}
* `pfx` {string|Buffer} Optional PFX or PKCS12 encoded private key and * `pfx` {string|string[]|Buffer|Buffer[]|Object[]} Optional PFX or PKCS12
certificate chain. `pfx` is an alternative to providing `key` and `cert` encoded private key and certificate chain. `pfx` is an alternative to
individually. PFX is usually encrypted, if it is, `passphrase` will be used providing `key` and `cert` individually. PFX is usually encrypted, if it is,
to decrypt it. `passphrase` will be used to decrypt it. Multiple PFX can be provided either
as an array of unencrypted PFX buffers, or an array of objects in the form
`{buf: <string|buffer>[, passphrase: <string>]}`. The object form can only
occur in an array. `object.passphrase` is optional. Encrypted PFX will be
decrypted with `object.passphrase` if provided, or `options.passphrase` if it is not.
* `key` {string|string[]|Buffer|Buffer[]|Object[]} Optional private keys in * `key` {string|string[]|Buffer|Buffer[]|Object[]} Optional private keys in
PEM format. PEM allows the option of private keys being encrypted. Encrypted PEM format. PEM allows the option of private keys being encrypted. Encrypted
keys will be decrypted with `options.passphrase`. Multiple keys using keys will be decrypted with `options.passphrase`. Multiple keys using

View File

@ -161,19 +161,29 @@ exports.createSecureContext = function createSecureContext(options, context) {
} }
if (options.pfx) { if (options.pfx) {
var pfx = options.pfx;
if (!crypto) if (!crypto)
crypto = require('crypto'); crypto = require('crypto');
pfx = crypto._toBuf(pfx); if (Array.isArray(options.pfx)) {
if (passphrase) for (i = 0; i < options.pfx.length; i++) {
passphrase = crypto._toBuf(passphrase); const pfx = options.pfx[i];
const raw = pfx.buf ? pfx.buf : pfx;
if (passphrase) { const buf = crypto._toBuf(raw);
c.context.loadPKCS12(pfx, passphrase); const passphrase = pfx.passphrase || options.passphrase;
if (passphrase) {
c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
}
}
} else { } else {
c.context.loadPKCS12(pfx); const buf = crypto._toBuf(options.pfx);
const passphrase = options.passphrase;
if (passphrase) {
c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
}
} }
} }

View File

@ -335,6 +335,14 @@ ec-cert.pem: ec-csr.pem ec-key.pem
-signkey ec-key.pem \ -signkey ec-key.pem \
-out ec-cert.pem -out ec-cert.pem
ec-pfx.pem: ec-cert.pem ec-key.pem
openssl pkcs12 -export \
-descert \
-in ec-cert.pem \
-inkey ec-key.pem \
-out ec-pfx.pem \
-password pass:
dh512.pem: dh512.pem:
openssl dhparam -out dh512.pem 512 openssl dhparam -out dh512.pem 512

BIN
test/fixtures/keys/ec-pfx.pem vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,50 @@
'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('assert');
const tls = require('tls');
const fixtures = require('../common/fixtures');
const options = {
pfx: [
{
buf: fixtures.readKey('agent1-pfx.pem'),
passphrase: 'sample'
},
fixtures.readKey('ec-pfx.pem')
]
};
const ciphers = [];
const server = tls.createServer(options, function(conn) {
conn.end('ok');
}).listen(0, function() {
const ecdsa = tls.connect(this.address().port, {
ciphers: 'ECDHE-ECDSA-AES256-GCM-SHA384',
rejectUnauthorized: false
}, common.mustCall(function() {
ciphers.push(ecdsa.getCipher());
const rsa = tls.connect(server.address().port, {
ciphers: 'ECDHE-RSA-AES256-GCM-SHA384',
rejectUnauthorized: false
}, common.mustCall(function() {
ciphers.push(rsa.getCipher());
ecdsa.end();
rsa.end();
server.close();
}));
}));
});
process.on('exit', function() {
assert.deepStrictEqual(ciphers, [{
name: 'ECDHE-ECDSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
}, {
name: 'ECDHE-RSA-AES256-GCM-SHA384',
version: 'TLSv1/SSLv3'
}]);
});