Browse Source

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>
canary-base
Yury Popov 7 years ago
committed by Ruben Bridgewater
parent
commit
372dc86af5
No known key found for this signature in database GPG Key ID: F07496B3EB3C1762
  1. 12
      doc/api/tls.md
  2. 26
      lib/_tls_common.js
  3. 8
      test/fixtures/keys/Makefile
  4. BIN
      test/fixtures/keys/ec-pfx.pem
  5. 50
      test/parallel/test-tls-multi-pfx.js

12
doc/api/tls.md

@ -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

26
lib/_tls_common.js

@ -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;
const buf = crypto._toBuf(raw);
const passphrase = pfx.passphrase || options.passphrase;
if (passphrase) {
c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
} else {
c.context.loadPKCS12(buf);
}
}
} else {
const buf = crypto._toBuf(options.pfx);
const passphrase = options.passphrase;
if (passphrase) { if (passphrase) {
c.context.loadPKCS12(pfx, passphrase); c.context.loadPKCS12(buf, crypto._toBuf(passphrase));
} else { } else {
c.context.loadPKCS12(pfx); c.context.loadPKCS12(buf);
}
} }
} }

8
test/fixtures/keys/Makefile

@ -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

Binary file not shown.

50
test/parallel/test-tls-multi-pfx.js

@ -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'
}]);
});
Loading…
Cancel
Save