From 7c55860fd99973e434519acaeb6978aa33b63f5b Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Wed, 8 Apr 2026 14:38:49 +0530 Subject: [PATCH 01/10] Added FIPS support --- lib/convert.js | 10 ++ lib/helper.js | 8 +- lib/pem.js | 117 +++++++++++++----- test/ca.spec.js | 3 +- test/convert.spec.js | 32 ++--- test/fixtures/idsrv3test.pfx | Bin 3395 -> 3440 bytes test/fixtures/idsrv3test_legacy.pfx | Bin 0 -> 3395 bytes test/fixtures/rsa_pkcs12_5_keyStore.p12 | Bin 7157 -> 7392 bytes test/fixtures/rsa_pkcs12_5_keyStore2.p12 | Bin 7157 -> 7392 bytes .../rsa_pkcs12_5_keyStore2_legacy.p12 | Bin 0 -> 7157 bytes .../fixtures/rsa_pkcs12_5_keyStore_legacy.p12 | Bin 0 -> 7157 bytes test/fixtures/rsa_pkcs12_5_key_RSA.pem | 103 +++++++-------- .../rsa_pkcs12_5_key_RSA_traditional.pem | 51 ++++++++ test/fixtures/test.crt | 37 +++--- test/fixtures/test.csr | 25 ++-- test/fixtures/test.dh | 9 +- test/fixtures/test.key | 48 ++++--- test/fixtures/test.p7b | 37 +++--- test/fixtures/test_1024_bit.dh | 5 + test/fixtures/test_des.crt | 16 +++ test/fixtures/test_des.csr | 13 ++ test/fixtures/test_des.key | 18 +++ test/fixtures/test_des.p7b | 17 +++ test/fixtures/testnopw.key | 43 ++++--- test/fixtures/testnopw_des.key | 15 +++ test/openssl.spec.js | 8 +- test/pem.spec.js | 77 ++++++++---- 27 files changed, 490 insertions(+), 202 deletions(-) create mode 100644 test/fixtures/idsrv3test_legacy.pfx create mode 100644 test/fixtures/rsa_pkcs12_5_keyStore2_legacy.p12 create mode 100644 test/fixtures/rsa_pkcs12_5_keyStore_legacy.p12 create mode 100644 test/fixtures/rsa_pkcs12_5_key_RSA_traditional.pem create mode 100644 test/fixtures/test_1024_bit.dh create mode 100644 test/fixtures/test_des.crt create mode 100644 test/fixtures/test_des.csr create mode 100644 test/fixtures/test_des.key create mode 100644 test/fixtures/test_des.p7b create mode 100644 test/fixtures/testnopw_des.key diff --git a/lib/convert.js b/lib/convert.js index 92703664..75088ec1 100644 --- a/lib/convert.js +++ b/lib/convert.js @@ -3,6 +3,7 @@ var openssl = require('./openssl.js') var helper = require('./helper.js') var {debug} = require('./debug.js') +const {getFips} = require('node:crypto') // PEM format: .pem, .crt, .cer (!bin), .key // base64 encoded; the cert file might also include the private key; so key file is optional @@ -160,6 +161,9 @@ module.exports.PEM2PFX = function (pathBundleIN, pathOUT, password, callback) { '-in', pathBundleIN.cert ] + if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3 && getFips()) { + params.push('-pbmac1_pbkdf2') + } if (pathBundleIN.ca) { if (!Array.isArray(pathBundleIN.ca)) { pathBundleIN.ca = [pathBundleIN.ca] @@ -202,6 +206,9 @@ module.exports.PFX2PEM = function (pathIN, pathOUT, password, callback) { pathOUT, '-nodes' ] + if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3 && getFips()) { + params.push('-pbmac1_pbkdf2') + } var delTempPWFiles = [] helper.createPasswordFile({ cipher: '', password: password, passType: 'in' }, params, delTempPWFiles) helper.createPasswordFile({ cipher: '', password: password, passType: 'out' }, params, delTempPWFiles) @@ -253,6 +260,9 @@ module.exports.P7B2PFX = function (pathBundleIN, pathOUT, password, callback) { '-out', pathOUT ] + if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3 && getFips()) { + params.push('-pbmac1_pbkdf2') + } if (pathBundleIN.ca) { if (!Array.isArray(pathBundleIN.ca)) { pathBundleIN.ca = [pathBundleIN.ca] diff --git a/lib/helper.js b/lib/helper.js index 2e19d957..d4a7549c 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -3,8 +3,8 @@ var pathlib = require('path') var fs = require('fs') var crypto = require('crypto') -const {tmpdir} = require('os') -var tempDir = process.env.PEMJS_TMPDIR || tmpdir() +const {tmpdir} = require('os') +var tempDir = process.env.PEMJS_TMPDIR || tmpdir() /** * pem helper module @@ -83,7 +83,7 @@ module.exports.createPasswordFile = function (options, params, PasswordFileArray if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) { params.push('-' + options.cipher) } - params.push('-pass' + options.passType) + params.push('-pass' + (params.indexOf('genpkey') === -1 ? options.passType : '')) if (options.mustPass) { params.push('pass:' + options.password) } else { @@ -136,4 +136,4 @@ module.exports.deleteTempFiles = function (files, callback) { * Callback for return an error object. * @callback errorCallback * @param {Error} err - An Error Object or null - */ + */ diff --git a/lib/pem.js b/lib/pem.js index 66c103e3..a1ce5738 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -6,7 +6,7 @@ * @module pem */ const {debug} = require('./debug.js') -const {createHash} = require('node:crypto') +const {createHash, getFips} = require('node:crypto') var net = require('net') var helper = require('./helper.js') var openssl = require('./openssl.js') @@ -89,11 +89,7 @@ function createPrivateKey(keyBitsize, options, callback) { keyBitsize = Number(keyBitsize) || 2048 - var params = ['genrsa'] - - if (openssl.get('Vendor') === 'OPENSSL' && openssl.get('VendorVersionMajor') >= 3) { - params.push('-traditional') - } + var params = ['genpkey', '-algorithm', 'RSA'] var delTempPWFiles = [] @@ -110,7 +106,8 @@ function createPrivateKey(keyBitsize, options, callback) { }, params, delTempPWFiles) } - params.push(keyBitsize) + params.push('-pkeyopt') + params.push(`rsa_keygen_bits:${keyBitsize}`) debug('version', openssl.get('openSslVersion')) @@ -124,15 +121,59 @@ function createPrivateKey(keyBitsize, options, callback) { }) } - helper.deleteTempFiles(delTempPWFiles, function (fsErr) { - debug('createPrivateKey', { - sslErr: sslErr, - fsErr: fsErr, - key: key, - keyLength: key && key.length + if (!sslErr && key && openssl.get('Vendor') === 'OPENSSL' && openssl.get('VendorVersionMajor') >= 3 && !getFips()) { + var traditional_params = ['pkey', '-traditional', '-in', '--TMPFILE--'] + + if (options && options.cipher && (Number(helper.ciphers.indexOf(options.cipher)) !== -1) && options.password) { + debug('helper.createPasswordFile', { + cipher: '', + password: options.password, + passType: 'in' + }) + helper.createPasswordFile({ + cipher: '', + password: options.password, + passType: 'in' + }, traditional_params, delTempPWFiles) + + debug('helper.createPasswordFile', { + cipher: options.cipher, + password: options.password, + passType: 'out' + }) + helper.createPasswordFile({ + cipher: options.cipher, + password: options.password, + passType: 'out' + }, traditional_params, delTempPWFiles) + } + + debug('version', openssl.get('openSslVersion')) + + openssl.exec(traditional_params, '(RSA |ENCRYPTED |)PRIVATE KEY', [key], function (traditional_sslErr, traditional_key) { + + helper.deleteTempFiles(delTempPWFiles, function (traditional_fsErr) { + debug('createPrivateKey', { + sslErr: traditional_sslErr, + fsErr: traditional_fsErr, + key: traditional_key, + keyLength: traditional_key && traditional_key.length + }) + key = traditional_key + done(traditional_sslErr || traditional_fsErr) + }) }) - done(sslErr || fsErr) - }) + } else { + helper.deleteTempFiles(delTempPWFiles, function (fsErr) { + debug('createPrivateKey', { + sslErr: sslErr, + fsErr: fsErr, + key: key, + keyLength: key && key.length + }) + done(sslErr || fsErr) + }) + } }) } @@ -140,7 +181,7 @@ function createPrivateKey(keyBitsize, options, callback) { * Creates a dhparam key * * @static - * @param {Number} [keyBitsize=512] Size of the key, defaults to 512bit + * @param {Number} [keyBitsize=(getFips() ? 2048 : 512)] Size of the key, defaults to 512bit in non-FIPS mode, and to 2048bit in FIPS mode * @param {Function} callback Callback function with an error object and {dhparam} * @returns {Promise<{dhparam: String}>} Resolves with the generated parameters when no callback is provided. */ @@ -161,7 +202,7 @@ function createDhparam(keyBitsize, callback) { }) } - keyBitsize = Number(keyBitsize) || 512 + keyBitsize = Number(keyBitsize) || (getFips() ? 2048 : 512) var params = ['dhparam', '-outform', @@ -182,7 +223,7 @@ function createDhparam(keyBitsize, callback) { /** * Creates a ecparam key * @static - * @param {String} [keyName=secp256k1] Name of the key, defaults to secp256k1 + * @param {String} [keyName=(getFips() ? prime256v1 : secp256k1)] Name of the key, defaults to secp256k1 in non-FIPS mode, and to prime256v1 in FIPS mode * @param {String} [paramEnc=explicit] Encoding of the elliptic curve parameters, defaults to explicit * @param {Boolean} [noOut=false] This option inhibits the output of the encoded version of the parameters. * @param {Function} callback Callback function with an error object and {ecparam} @@ -211,7 +252,7 @@ function createEcparam(keyName, paramEnc, noOut, callback) { }) } - keyName = keyName || 'secp256k1' + keyName = keyName || (getFips() ? 'prime256v1' : 'secp256k1') paramEnc = paramEnc || 'explicit' noOut = noOut || false @@ -356,6 +397,13 @@ function createCSR(options, callback) { ].join('\n')) } else if (options.config) { config = options.config + } else if (typeof options.CA === 'boolean') { + config = [ + '[req]', + 'req_extensions = v3_req', + '[v3_req]', + `basicConstraints = critical,CA:${options.CA}` + ].join('\n') } @@ -632,7 +680,7 @@ function getPublicKey(certificate, callback) { '-noout' ] } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/)) { - params = ['rsa', + params = ['pkey', '-in', '--TMPFILE--', '-pubout' @@ -744,7 +792,7 @@ function getModulus(certificate, password, hash, callback) { let type if (certificate.match(/BEGIN(\sNEW)? CERTIFICATE REQUEST/)) { type = 'req' - } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/)) { + } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/) || certificate.match(/BEGIN ENCRYPTED PRIVATE KEY/)) { type = 'rsa' } else { type = 'x509' @@ -972,6 +1020,10 @@ function createPkcs12(key, certificate, password, options, callback) { params.push('--TMPFILE--') } + if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3 && getFips()) { + params.push('-pbmac1_pbkdf2') + } + openssl.execBinary(params, tmpfiles, function (sslErr, pkcs12) { function done(err) { if (err) { @@ -1029,8 +1081,13 @@ function readPkcs12(bufferOrPath, options, callback) { } if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3) { - args.push('-legacy') - args.push('-traditional') + if (!getFips()) { + args.push('-legacy') + args.push('-traditional') + } + else { + args.push('-pbmac1_pbkdf2') + } } if (options.clientKeyPassword) { @@ -1059,8 +1116,8 @@ function readPkcs12(bufferOrPath, options, callback) { debug("readPkcs12.execBinary - PRIVATE KEY - ?: ", keybundle.key) if (keybundle.key) { - var args = ['rsa']; - if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3) { + var args = ['pkey']; + if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3 && !getFips()) { args.push('-traditional') } args.push('-in'); @@ -1145,8 +1202,8 @@ function checkCertificate(certificate, passphrase, callback) { if (certificate.match(/BEGIN(\sNEW)? CERTIFICATE REQUEST/)) { params = ['req', '-text', '-noout', '-verify', '-in', '--TMPFILE--'] - } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/)) { - params = ['rsa', '-noout', '-check', '-in', '--TMPFILE--'] + } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/) || certificate.match(/BEGIN ENCRYPTED PRIVATE KEY/)) { + params = ['pkey', '-noout', '-check', '-in', '--TMPFILE--'] } else { params = ['x509', '-text', '-noout', '-in', '--TMPFILE--'] } @@ -1160,8 +1217,8 @@ function checkCertificate(certificate, passphrase, callback) { stdout = stdout && stdout.trim() var result switch (params[0]) { - case 'rsa': - result = /^Rsa key ok$/i.test(stdout) + case 'pkey': + result = /^Key is valid$/i.test(stdout) break default: result = /Signature Algorithm/im.test(stdout) @@ -1222,7 +1279,7 @@ function checkPkcs12(bufferOrPath, passphrase, callback) { args[3] = '--TMPFILE--' } - if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3) { + if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3 && !getFips()) { args.splice(2, 0, '-legacy'); } diff --git a/test/ca.spec.js b/test/ca.spec.js index 26258684..d845b2dd 100644 --- a/test/ca.spec.js +++ b/test/ca.spec.js @@ -16,7 +16,8 @@ describe('CertificateAuthority', function () { rootCA = await pem.createCertificate({ commonName: 'Test Root CA', selfSigned: true, - days: 365 + days: 365, + CA: true }) var intermediateConfig = [ diff --git a/test/convert.spec.js b/test/convert.spec.js index 9fd0dec7..a942072e 100644 --- a/test/convert.spec.js +++ b/test/convert.spec.js @@ -10,6 +10,8 @@ const {debug} = require('../lib/debug.js') var expect = chai.expect chai.use(dirtyChai) +const fipsEnabled = require('node:crypto').getFips() + describe('convert.js tests', function () { after(function (done) { var tmpfiles @@ -61,8 +63,8 @@ describe('convert.js tests', function () { }) it('#.PEM2PFX()', function (done) { var pathIN = { - cert: './test/fixtures/test.crt', - key: './test/fixtures/testnopw.key' + cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') +'.crt', + key: './test/fixtures/testnopw' + (fipsEnabled ? '' : '_des') + '.key' } // password is required to encrypt the .pfx file; enforced by openssl pem.convert.PEM2PFX(pathIN, './test/fixtures/tmp.pfx', 'password', function (error, result) { @@ -79,7 +81,7 @@ describe('convert.js tests', function () { }) }) it('#.P7B2PFX() [error in 1st step]', function (done) { - pem.convert.P7B2PFX({ cert: './test/fixtures/test.p7b', key: './test/fixtures/test.key', ca: './test/fixtures/GeoTrust_Primary_CA.pem' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { + pem.convert.P7B2PFX({ cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.p7b', key: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key', ca: './test/fixtures/GeoTrust_Primary_CA.pem' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { debug("TEST pem.convert.PEM2DER",{error, result} ) hlp.checkError(error, true) done() @@ -89,7 +91,7 @@ describe('convert.js tests', function () { pem.config({ pathOpenSSL: process.env.OPENSSL_BIN || 'openssl' }) - pem.convert.P7B2PFX({ cert: './test/fixtures/test.p7b', key: './test/fixtures/test404.key', ca: './test/fixtures/ca404.pem' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { + pem.convert.P7B2PFX({ cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.p7b', key: './test/fixtures/test404.key', ca: './test/fixtures/ca404.pem' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { debug("TEST pem.convert.PEM2DER",{error, result} ) hlp.checkError(error, true) done() @@ -180,8 +182,8 @@ describe('convert.js tests', function () { it('#.PEM2PFX() [no password protected key file]', function (done) { var pathIN = { - cert: './test/fixtures/test.crt', - key: './test/fixtures/testnopw.key' + cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') +'.crt', + key: './test/fixtures/testnopw' + (fipsEnabled ? '' : '_des') + '.key' } // password is required to encrypt the .pfx file; enforced by openssl pem.convert.PEM2PFX(pathIN, './test/fixtures/tmp.pfx', 'password', function (error, result) { @@ -193,8 +195,8 @@ describe('convert.js tests', function () { it('#.PEM2PFX() [password protected key file]', function (done) { var pathIN = { - cert: './test/fixtures/test.crt', - key: './test/fixtures/test.key' + cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') +'.crt', + key: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key' } pem.convert.PEM2PFX(pathIN, './test/fixtures/tmp.pfx', 'password', function (error, result) { hlp.checkError(error) @@ -205,8 +207,8 @@ describe('convert.js tests', function () { it('#.PEM2PFX() [providing CA cert; no array format]', function (done) { var pathIN = { - cert: './test/fixtures/test.crt', - key: './test/fixtures/test.key', + cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') +'.crt', + key: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key', ca: './test/fixtures/GeoTrust_Primary_CA.pem' } pem.convert.PEM2PFX(pathIN, './test/fixtures/tmp.pfx', 'password', function (error, result) { @@ -218,8 +220,8 @@ describe('convert.js tests', function () { it('#.PEM2PFX() [providing CA cert; array format]', function (done) { var pathIN = { - cert: './test/fixtures/test.crt', - key: './test/fixtures/test.key', + cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') +'.crt', + key: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key', ca: ['./test/fixtures/GeoTrust_Primary_CA.pem'] } pem.convert.PEM2PFX(pathIN, './test/fixtures/tmp.pfx', 'password', function (error, result) { @@ -238,7 +240,7 @@ describe('convert.js tests', function () { }) it('#.P7B2PFX() [providing ca cert; no array format]', function (done) { - pem.convert.P7B2PFX({ cert: './test/fixtures/test.p7b', key: './test/fixtures/test.key', ca: './test/fixtures/GeoTrust_Primary_CA.pem' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { + pem.convert.P7B2PFX({ cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.p7b', key: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key', ca: './test/fixtures/GeoTrust_Primary_CA.pem' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { hlp.checkError(error) expect(result).to.be.true() done() @@ -246,7 +248,7 @@ describe('convert.js tests', function () { }) it('#.P7B2PFX() [providing ca cert; array format]', function (done) { - pem.convert.P7B2PFX({ cert: './test/fixtures/test.p7b', key: './test/fixtures/test.key', ca: ['./test/fixtures/GeoTrust_Primary_CA.pem'] }, './test/fixtures/tmp.pfx', 'password', function (error, result) { + pem.convert.P7B2PFX({ cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.p7b', key: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key', ca: ['./test/fixtures/GeoTrust_Primary_CA.pem'] }, './test/fixtures/tmp.pfx', 'password', function (error, result) { hlp.checkError(error) expect(result).to.be.true() done() @@ -254,7 +256,7 @@ describe('convert.js tests', function () { }) it('#.P7B2PFX() [not providing ca cert]', function (done) { - pem.convert.P7B2PFX({ cert: './test/fixtures/test.p7b', key: './test/fixtures/test.key' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { + pem.convert.P7B2PFX({ cert: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.p7b', key: './test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key' }, './test/fixtures/tmp.pfx', 'password', function (error, result) { hlp.checkError(error) expect(result).to.be.true() done() diff --git a/test/fixtures/idsrv3test.pfx b/test/fixtures/idsrv3test.pfx index 0247dea03f0cc23694291f21310f3ae88880e2bb..795e978349141635847fa857e259abe4371ce809 100644 GIT binary patch literal 3440 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 KT!j1o{`Maqr8S!X literal 3395 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 V%$88{h~I%@Xjg7x^oQR@_8&Ry9S;Bi diff --git a/test/fixtures/idsrv3test_legacy.pfx b/test/fixtures/idsrv3test_legacy.pfx new file mode 100644 index 0000000000000000000000000000000000000000..0247dea03f0cc23694291f21310f3ae88880e2bb GIT binary patch literal 3395 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 V%$88{h~I%@Xjg7x^oQR@_8&Ry9S;Bi literal 0 HcmV?d00001 diff --git a/test/fixtures/rsa_pkcs12_5_keyStore.p12 b/test/fixtures/rsa_pkcs12_5_keyStore.p12 index 5c0c512f8fe0d68423a25cc4868ec22246a59f3d..8304b9adc218cb75f4c1817740dde82fc1708608 100644 GIT binary patch literal 7392 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 K*g^j9YySfj8TG9I literal 7157 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 diff --git a/test/fixtures/rsa_pkcs12_5_keyStore2.p12 b/test/fixtures/rsa_pkcs12_5_keyStore2.p12 index 85566ad74011fd397f2ba9c33a0ab1742b82dbf7..432072d14de6272e141545a0b824b4b9b642309c 100644 GIT binary patch literal 7392 zcmai(V{j!-m&WgnZBCMjCgzRpOl&6;TNB&1ZQHhOOl;fcWdB>c^}e-RTeTm$x}N9h z>eFAk>eTNr`r~ha0l^vl@kOCvse{FXpAmu3z+8WPHVA)wrhjaDMt`(#|Bj$?{n6n6 zv7o_#fPXf?zY`#%?!N>iBBLTB=-(27@dpG-{Q$oW%RE#>S^ZFKN&Ivq7#IwI5djM3 zzp8@4LIM~GpkVca#ev4)5I|}O6z+fwZ;cXzB*O0X`@;#aXkUNS*qa!KDEq)iivpt5 z6x&DxlidL}Q_V%YlcljW(O~_w9ZD^v=fw|tb#6U&tdRIe@KqKUIj* z`l8v(nm_2g;C-}0LTViR)@~T`+jclnUp%9fP}pARH^-^sUyl954hg|gi9<)z3Fa3f86wc5 zf^H}`L%c_5Ui1R{i`%hro4<#N)AZ2kp?S>%RX%^q7Fg2LeXABGnSRmxNy$7J7SX(DWayoBA>&j-^?Yn|wk)`)T`` zW1LnKHaDt-G8s55oVIL0{P+;0bh|LJy~-udqyIhAeP!HOYqxm-7OLTe=*5~^o7P!8S0-P;4=n%OHtU+6Pym$v~k82(M|3AX>#~OT1S^H3+B*S@ z;%iTKQ81luTG|&5wZjsqQBHOc@MtAfMI8)oi=D_3g=>Jsn4~hC3TtJ{TTQ}YHU-8oCT^aM7D5c{g~nWL(#?_`w{?X zowm)Us0EoS-a_ROpBbv=@3_b1c$Fr$yA_voF_spT`g2GJI?Y=NUx6RwkjEO)3_3gO zJO{fH?9bQ>{OQkXQbKgyK65#NsA=l~wtrqpb$Xadb(`E*;=jbFg>?Fj`M!}P&Jtl)J`qT^v9f$MVQ!ip)cHd;$s}{MFk8ibfIFN zphK{3=+5cObv1dg;w=Xk?*Oa58~~Wn&uPONb+0l}+A{ zY;gLrgX-(XzICpBmKX}gR-J?mbRIK=$!%=C-0m|wx8j77olp)iJX9Zjqw>?df{lrM z70WV!^o>nK`FwCAjv6^YbK^@tQh^z&0{t&Q3c6LsQMtKOQ20VULv{F1F zX)3xNZ>8!to9-ObCn*Y|=_qkbmx1U__Hv;FI!ZRW7}>6NjIIll-XD>;2Ek0{c@fSn zJdcYN*W+K{TEu?7%^R_#g|dBidp<(gVmbuAO6w2Ve58juGd!`2szJ#c&kHpIwR*V! zUguUFhE<{6$pALCpX`*#WY)yAYTQGM;)o9E>(F)I-u`B>j7oEcHV(LZ&w_?BpT~ZEr7&D3r2D2PquTO2MVTj zH|+Dc2-_D3w$+E@49>98B^6epkiLy`hLEsHMTFw^2J3#u2;5RPl~A0yfM�+vAZ* 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 diff --git a/test/fixtures/rsa_pkcs12_5_keyStore2_legacy.p12 b/test/fixtures/rsa_pkcs12_5_keyStore2_legacy.p12 new file mode 100644 index 0000000000000000000000000000000000000000..85566ad74011fd397f2ba9c33a0ab1742b82dbf7 GIT binary patch literal 7157 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/rsa_pkcs12_5_keyStore_legacy.p12 b/test/fixtures/rsa_pkcs12_5_keyStore_legacy.p12 new file mode 100644 index 0000000000000000000000000000000000000000..5c0c512f8fe0d68423a25cc4868ec22246a59f3d GIT binary patch literal 7157 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 literal 0 HcmV?d00001 diff --git a/test/fixtures/rsa_pkcs12_5_key_RSA.pem b/test/fixtures/rsa_pkcs12_5_key_RSA.pem index b60c0bf3..77f40069 100644 --- a/test/fixtures/rsa_pkcs12_5_key_RSA.pem +++ b/test/fixtures/rsa_pkcs12_5_key_RSA.pem @@ -1,51 +1,52 @@ ------BEGIN RSA PRIVATE KEY----- -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 ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +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 +1+zpRCjnjfSdd8uLEzeMz/sGOIMt +-----END PRIVATE KEY----- diff --git a/test/fixtures/rsa_pkcs12_5_key_RSA_traditional.pem b/test/fixtures/rsa_pkcs12_5_key_RSA_traditional.pem new file mode 100644 index 00000000..b60c0bf3 --- /dev/null +++ b/test/fixtures/rsa_pkcs12_5_key_RSA_traditional.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/test/fixtures/test.crt b/test/fixtures/test.crt index 3c146c56..b629fafd 100644 --- a/test/fixtures/test.crt +++ b/test/fixtures/test.crt @@ -1,16 +1,23 @@ -----BEGIN CERTIFICATE----- -MIIChTCCAe4CCQDbGP0P9s69azANBgkqhkiG9w0BAQsFADCBhjELMAkGA1UEBhMC -WlcxGzAZBgNVBAgMEk1hdGViZWxlbGFuZCBOb3J0aDERMA8GA1UEBwwIQnVsYXdh -eW8xDDAKBgNVBAoMA0J5bzELMAkGA1UECwwCSVQxDzANBgNVBAMMBmJ5by56dzEb -MBkGCSqGSIb3DQEJARYMYWRtaW5AYnlvLnp3MB4XDTE1MDQxMDA5NTM1OVoXDTE2 -MDQwOTA5NTM1OVowgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxh -bmQgTm9ydGgxETAPBgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNV -BAsMAklUMQ8wDQYDVQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5 -by56dzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0q4cDxLRslRKvG2pw5Gx -7fsq7YyiTokoBaDavNold5Vvayi02Mc7dqIanr/ckc0AqgiDd5Kw2bBAYmQpWiDn -pZxp79JIV+gGh7pkiB4wDzvRBXMcew72B9uuYEeUQ8eonE/Yro0ZnD0ZGmBiuk/6 -5xyWNikBhfPLnb2V+Cr/EKsCAwEAATANBgkqhkiG9w0BAQsFAAOBgQAwigr+o+Y+ -5BiL6MuHLTaC+lcv9r2GTHb7wNea674Db3Bi3u6FgmyMsZ8npPSlR0t/YZcFWtRM -y4uXmw5zUutGZTbO/JFxts6kPV+a76mnNm71fF4QINkemmojvJyPZq9N+hV16dba -v1m+dTK7hDZvpd/sM5bMtqWEq4aHkGhujw== ------END CERTIFICATE----- \ No newline at end of file +MIIDyDCCArCgAwIBAgIUMcS1t3keFw5FTPMHhbarirMXxVQwDQYJKoZIhvcNAQEL +BQAwgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxhbmQgTm9ydGgx +ETAPBgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNVBAsMAklUMQ8w +DQYDVQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5by56dzAeFw0y +NjA0MDgwNjIxMjhaFw0yNzA0MDgwNjIxMjhaMIGGMQswCQYDVQQGEwJaVzEbMBkG +A1UECAwSTWF0ZWJlbGVsYW5kIE5vcnRoMREwDwYDVQQHDAhCdWxhd2F5bzEMMAoG +A1UECgwDQnlvMQswCQYDVQQLDAJJVDEPMA0GA1UEAwwGYnlvLnp3MRswGQYJKoZI +hvcNAQkBFgxhZG1pbkBieW8uencwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQC2YDr9Gl+QDoi8iqv6x5JAR/Up1wuSyxrgVK6aVQ6P3hBizKC4PTULM6v1 +w5W3XN4M+46LToSgH2nxypwUFgbu0LFAwzSBbt+riAwU8g1oYebcpDj6g2TrzDbf +E3iCM7eAZCVu1AgYAEk6Z+6b2yrpk8o23OkbwS5OxnTcN22g+aMatYFfZIO06BmO +EihxdtY9n9Woj/1aL5uv/p7LpX0VwOnq17XVp00/iO6aajW34iBa8i1uZE17ZF4+ +iHZJn+dGi2kfx2vMFA9OhJz9TiblY2+EVSxfXsLPK9OnaNBsrNjUVYjUVChv1zKE +D88g5OrwkSFIk9kEXF6evXO7w9ExAgMBAAGjLDAqMAkGA1UdEwQCMAAwHQYDVR0O +BBYEFD0Mpvt5JD34jRZMqNlN4YcEhMOoMA0GCSqGSIb3DQEBCwUAA4IBAQAk1D5q +l39QKR3PH1XrssBcvsXb7zL2A4DbEAXWASLPOeLyNTZV1lBJLB4LbmM0g1+zqy5O +5+31qqnfwUk86ooRYHcS0n/6fa0/KqxnipuFZ6qr7tm2OCdqQ3Li6dAdGVxiF4uc +L6mQz8JSUSKMojkKCp8CdFVHwknQwjy1HRCTzv57agdYBlYM2z1rn1Eyk7IPD76F +FFt9iXfSyFb8GRrncTVSMkfqSYBhiR6GdUvjQWLkqFU9NUnUhFhCX3ri+et6NMgF +McSly1RyHch71C2T1jvEqnoSpPC2yZ0dW1y6cIoNWE6WvloRE89bXL72+s+3XlLY +9M5F6mcDw6DUNPUr +-----END CERTIFICATE----- diff --git a/test/fixtures/test.csr b/test/fixtures/test.csr index 7851a725..78d58183 100644 --- a/test/fixtures/test.csr +++ b/test/fixtures/test.csr @@ -1,13 +1,18 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIB3jCCAUcCAQAwgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxh +MIIC6DCCAdACAQAwgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxh bmQgTm9ydGgxETAPBgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNV BAsMAklUMQ8wDQYDVQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5 -by56dzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0q4cDxLRslRKvG2pw5Gx -7fsq7YyiTokoBaDavNold5Vvayi02Mc7dqIanr/ckc0AqgiDd5Kw2bBAYmQpWiDn -pZxp79JIV+gGh7pkiB4wDzvRBXMcew72B9uuYEeUQ8eonE/Yro0ZnD0ZGmBiuk/6 -5xyWNikBhfPLnb2V+Cr/EKsCAwEAAaAXMBUGCSqGSIb3DQEJAjEIDAZCeW8gQ28w -DQYJKoZIhvcNAQELBQADgYEAxP+4Z2POlTlCBYpGhhKpTBbRDeAQakXqGBlB7ZC2 -0K4fSxuAGVArLV5rbPDHlzNCtmF8mvt55F7zVny4YQ8BHE7ujV3SWtiAr0Otq9VV -WG5LmBLAbyrrUZloHJEpX0wPgQDmMdLhkDkbcjcKOT6WKNW5q36MW+Q9nViStGD5 -lJg= ------END CERTIFICATE REQUEST----- \ No newline at end of file +by56dzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALZgOv0aX5AOiLyK +q/rHkkBH9SnXC5LLGuBUrppVDo/eEGLMoLg9NQszq/XDlbdc3gz7jotOhKAfafHK +nBQWBu7QsUDDNIFu36uIDBTyDWhh5tykOPqDZOvMNt8TeIIzt4BkJW7UCBgASTpn +7pvbKumTyjbc6RvBLk7GdNw3baD5oxq1gV9kg7ToGY4SKHF21j2f1aiP/Vovm6/+ +nsulfRXA6erXtdWnTT+I7ppqNbfiIFryLW5kTXtkXj6Idkmf50aLaR/Ha8wUD06E +nP1OJuVjb4RVLF9ews8r06do0Gys2NRViNRUKG/XMoQPzyDk6vCRIUiT2QRcXp69 +c7vD0TECAwEAAaAcMBoGCSqGSIb3DQEJDjENMAswCQYDVR0TBAIwADANBgkqhkiG +9w0BAQsFAAOCAQEAFh+OwOLRXTamt7jwrmMCs8/wJjBrRclmcsYBVosc2HrU3ErU +zkeCdDDEakZfiTxkFYyOB94Hx23CrG4OHWDKsEDr0Q3/wqd61On3VqTusQ7uVK3x +Yh8mA26K/D49VHb1bZbklasWNlxHZoTKdnCw+CHG5bsPvlENb1ReHomx8534tuoj +yt8RCBzuBlrOkn+GE2PSFSUJC8Fry20J76XX5y93cKyX9cnBdybSnGlv3WSWGOdQ +E+tLCzBzwml5EDWVeCNNcfNnFMteMw57T2bs/H0M9IMVK3pQu1QjeSl1FxejmjCm +jZ+Xbn8WZblFqhH2YrfKFEDX0eRFJ55PdTWyvA== +-----END CERTIFICATE REQUEST----- diff --git a/test/fixtures/test.dh b/test/fixtures/test.dh index b8b18b14..9b182b72 100644 --- a/test/fixtures/test.dh +++ b/test/fixtures/test.dh @@ -1,5 +1,8 @@ -----BEGIN DH PARAMETERS----- -MIGHAoGBAMYXwgiuPY6TqxODWXbRRWx6eWoJuGkjKN8RjhBiLxFJzwgpdfONv5iG -IHHGI8/IfhHI78Mqq+5z3z8L16fuOYnpbaDa2BSUdHZQQmFiCV748lOv9he08UJ5 -qgrFgdgi56V4FdRs2EHJnezvYmviAbIsi8imn+9TVed4DnOmuE1rAgEC +MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz ++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a +87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7 +YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi +7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD +ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg== -----END DH PARAMETERS----- diff --git a/test/fixtures/test.key b/test/fixtures/test.key index ec1c5ece..9c2b2174 100644 --- a/test/fixtures/test.key +++ b/test/fixtures/test.key @@ -1,18 +1,30 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,8D7649F2550A3AD6 - -iD68IbbRZDJuiYBqiEMLSfQQqcbXr4CeHFVkAYxCKN785tg+icShBeYXP2H2Oa7m -dmFBNrtuPclUjk1VFeDcRhd1WwabuSbKJkV26bqIwYKSa1blDcgviSvIc8OgN06G -K7kX+3jQzUMeSj+B1phyysCSoSU059oJvcNknBOEe67ersYZhXWFDOxVOeCnpsVA -xDPRGVWa5g5jj0WqcXey/oC/hUccX8w8RZJLSBurIxfWBGy1QtsnopNRaxs5gqXj -FCucQtYTMwRzA0c65/6yDrYrnv3v0mmCKBKXoTvhcmxkE/Ejrk0+ydxlgWXoMjOD -CzuDy8xQ2KN2/62fb0Eb6LwnI3EHceXAO9GbgpCTXDZt0yoKMBDZFYA1+TuYBXJj -RRcKDcF+gt1VdloSkAWIaDwypnPi0xngsJbzNIHKoSKYPuxWdUXB5rThbSdPki5x -r8La88LBK6/WarJevce8Ggg/KCAx5ng/w9XzQDlMSNVT6Ht+gGe6+69XjBA5IyIo -bymu9PlwRMMYEeEcH53tGXcCgSkzlDs2Cc+1+JUypZpX4oggNV5YhsmLZS5BtPFs -9i3lA7RsxXoV0u1BTgHIqrH58IKaXN9xs0ceie3cLR5tcSiSsU9sh3wpjZ2AZ/Q5 -zjoHuyzQVxY14qlE3uWzI9vJtc/kCkQ4D8wdBRVM8uRzf+YGYKRbI6vvsSICeLuW -n82E2zin77HnIOGVHPJ5aNaTQD91Ubxxv7lVeuxZf2tgejs2DbJraKOtOmHLd9GA -Zb5G9TdFMxVcXq18xUMm/Rbkj8ugALxRy8CGNSrTFTPHaEwYxqhnAQ== ------END RSA PRIVATE KEY----- \ No newline at end of file +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQgTmMmulNENfMd6Mx +IUigdwICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEPnLvMYNwtVd7g3H +3UdBSNwEggTQ/0eRtg2KD9WHWtiRvEYKk6ntxLZYB6a/WXTYfzIn5xyXM7errA0a +i30iHdUG9e3GS0hlMipEscX52KJbS2FEhkFaqcT37DI9uJxwZYcTfctEQroZsMwP +8lPRTNXl7ySTHITyvqrZGhyJernX8J00aPXvfdIG1oSNYGqIdXnBA6CA9TisXeQ3 +iDz7lvA899SA1ugy8fx+yzzbVN0Py2JZwLwziCRXrs+3HkhcI+u6XHkpDIgXv1hE +VDqYMKjp/T5N6A5IzUMVkXDCq/dYQTrYJ4ADiC1btySluwjILbhFsgRv7f63gYVO +d7DgjDrlar7kpqO+qZJFFXOJBcPLSgqho8h8McSxBGug1zGZQBMGHBP/bDFw0WC2 +YGf7ZTkIjeFIKJrAqGuv8Tc7fm7aKixHbdap9QrMltMnw/Yj2U/db0yoQLS/mmTQ +FJxSgeyWB1D2hng/Z+BTleYc3CAJaCqQmVv7mw+kL3618upk+3NtqRiMOWIHBG3D +z+yrz9y/OOf1jYxKxpq8mN4UfuofTyS7HljNdHDUcjwEW/DryaptMqKWkZ8uNQIu +FuS2rCI9fFiImIaBIMBoTx2FahULZ5CPpi0Sj9OxlZ/zIPIvzIaC4kmIt7Y0kDLx +uLdwdCHLbcU90dJvOvbrgh3GoU1B8LnFZP6ABrNIg3z/yWETyXg9/cfIGuSiP0QM +srgSPGPL7rPYd7+/cr98QT66vv9iE0CCWVi6oiVJh3BbCVU1V44HtFIFgbxGGUAj +s/brviZezGZ26s8uLK6Xe5GikQY/AFY9hlDkkW+qecrtXL4PAEZktCSmv8KdWdLG +yuCPh4F4EWCCSTTsI0bCHxhK4ZLcmxAVtKYi2fLEg7rYcNx0QDyhaiJZQAC7eohW +IQILBnAOYRR0FY3A5ZmQTYEPJFBFgxA3LtED/DflMokqkKEQCy99si91CHHkE7m5 +rSYKDJKz5p4sSvEwSjd5JSgTgpRO/rb1hr/76X+e+nnCQGfNby/4GLlUxWSAZPdt +ekcoJ2v3nd0arOVTGMX/L59ns4V41i72A0+IpC50WdI/8Rk22fvp8TE20N2OIfMy +YWW6xSjHeoVt7lsnK28V5ujN7VDtE1Lvw0C/wMcmm7EWcJVqjVpE65YRiLPuWAAd +GXsTNL59PXUaTBRDDm5tYBOok91u0337ZgDqylREsiTkz+x3WqNAPu6TO5TibYcH +WlNg+1kJr9oJeUtGD5MAGj0AUt0EJM49ncb6t39TxI9NQ+QMTiJvSl6GcRmZfLxY +rSiC7qEODe2l7fZjrz/bUWZRPi6fI5zKQYeIqendUFnxEDhLHe6TyezCD7J1RKaH +hlbQ76HFsR6wgWKrwfVgmtEsrYQpg/ujEZ8pUNN/g5kc5eJV+Adna3GJfK4d7mTg +aC1NzehJmEVNrwFhuwrSh2xMrG3y0yvssvRu+MLzGU1FmEtuTqQFPFPNYVFqRjNk +x3c/M659EGEqOA64Ja7PCcjdsCRsyikl8fitMQMq+R8p709ny+PGEsJCZggI31sL +Gq21JRk9AKpZzmSLnHyez+Wzdw4W3jpX2VF9QbVNhbZfIYgEM5sEAHkLNy3qx+uZ +5X7QgNHccDeFOYKG3X24WDal/7Ug/IEmVlXhBYtCVKA91s5+bCiQShE= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/test/fixtures/test.p7b b/test/fixtures/test.p7b index 430c129f..c8b6b00c 100644 --- a/test/fixtures/test.p7b +++ b/test/fixtures/test.p7b @@ -1,17 +1,24 @@ -----BEGIN PKCS7----- -MIICtgYJKoZIhvcNAQcCoIICpzCCAqMCAQExADALBgkqhkiG9w0BBwGgggKJMIIC -hTCCAe4CCQDbGP0P9s69azANBgkqhkiG9w0BAQsFADCBhjELMAkGA1UEBhMCWlcx -GzAZBgNVBAgMEk1hdGViZWxlbGFuZCBOb3J0aDERMA8GA1UEBwwIQnVsYXdheW8x -DDAKBgNVBAoMA0J5bzELMAkGA1UECwwCSVQxDzANBgNVBAMMBmJ5by56dzEbMBkG -CSqGSIb3DQEJARYMYWRtaW5AYnlvLnp3MB4XDTE1MDQxMDA5NTM1OVoXDTE2MDQw -OTA5NTM1OVowgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxhbmQg -Tm9ydGgxETAPBgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNVBAsM -AklUMQ8wDQYDVQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5by56 -dzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0q4cDxLRslRKvG2pw5Gx7fsq -7YyiTokoBaDavNold5Vvayi02Mc7dqIanr/ckc0AqgiDd5Kw2bBAYmQpWiDnpZxp -79JIV+gGh7pkiB4wDzvRBXMcew72B9uuYEeUQ8eonE/Yro0ZnD0ZGmBiuk/65xyW -NikBhfPLnb2V+Cr/EKsCAwEAATANBgkqhkiG9w0BAQsFAAOBgQAwigr+o+Y+5BiL -6MuHLTaC+lcv9r2GTHb7wNea674Db3Bi3u6FgmyMsZ8npPSlR0t/YZcFWtRMy4uX -mw5zUutGZTbO/JFxts6kPV+a76mnNm71fF4QINkemmojvJyPZq9N+hV16dbav1m+ -dTK7hDZvpd/sM5bMtqWEq4aHkGhuj6EAMQA= +MIID9wYJKoZIhvcNAQcCoIID6DCCA+QCAQExADALBgkqhkiG9w0BBwGgggPMMIID +yDCCArCgAwIBAgIUMcS1t3keFw5FTPMHhbarirMXxVQwDQYJKoZIhvcNAQELBQAw +gYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxhbmQgTm9ydGgxETAP +BgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNVBAsMAklUMQ8wDQYD +VQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5by56dzAeFw0yNjA0 +MDgwNjIxMjhaFw0yNzA0MDgwNjIxMjhaMIGGMQswCQYDVQQGEwJaVzEbMBkGA1UE +CAwSTWF0ZWJlbGVsYW5kIE5vcnRoMREwDwYDVQQHDAhCdWxhd2F5bzEMMAoGA1UE +CgwDQnlvMQswCQYDVQQLDAJJVDEPMA0GA1UEAwwGYnlvLnp3MRswGQYJKoZIhvcN +AQkBFgxhZG1pbkBieW8uencwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQC2YDr9Gl+QDoi8iqv6x5JAR/Up1wuSyxrgVK6aVQ6P3hBizKC4PTULM6v1w5W3 +XN4M+46LToSgH2nxypwUFgbu0LFAwzSBbt+riAwU8g1oYebcpDj6g2TrzDbfE3iC +M7eAZCVu1AgYAEk6Z+6b2yrpk8o23OkbwS5OxnTcN22g+aMatYFfZIO06BmOEihx +dtY9n9Woj/1aL5uv/p7LpX0VwOnq17XVp00/iO6aajW34iBa8i1uZE17ZF4+iHZJ +n+dGi2kfx2vMFA9OhJz9TiblY2+EVSxfXsLPK9OnaNBsrNjUVYjUVChv1zKED88g +5OrwkSFIk9kEXF6evXO7w9ExAgMBAAGjLDAqMAkGA1UdEwQCMAAwHQYDVR0OBBYE +FD0Mpvt5JD34jRZMqNlN4YcEhMOoMA0GCSqGSIb3DQEBCwUAA4IBAQAk1D5ql39Q +KR3PH1XrssBcvsXb7zL2A4DbEAXWASLPOeLyNTZV1lBJLB4LbmM0g1+zqy5O5+31 +qqnfwUk86ooRYHcS0n/6fa0/KqxnipuFZ6qr7tm2OCdqQ3Li6dAdGVxiF4ucL6mQ +z8JSUSKMojkKCp8CdFVHwknQwjy1HRCTzv57agdYBlYM2z1rn1Eyk7IPD76FFFt9 +iXfSyFb8GRrncTVSMkfqSYBhiR6GdUvjQWLkqFU9NUnUhFhCX3ri+et6NMgFMcSl +y1RyHch71C2T1jvEqnoSpPC2yZ0dW1y6cIoNWE6WvloRE89bXL72+s+3XlLY9M5F +6mcDw6DUNPUrMQA= -----END PKCS7----- diff --git a/test/fixtures/test_1024_bit.dh b/test/fixtures/test_1024_bit.dh new file mode 100644 index 00000000..b8b18b14 --- /dev/null +++ b/test/fixtures/test_1024_bit.dh @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAMYXwgiuPY6TqxODWXbRRWx6eWoJuGkjKN8RjhBiLxFJzwgpdfONv5iG +IHHGI8/IfhHI78Mqq+5z3z8L16fuOYnpbaDa2BSUdHZQQmFiCV748lOv9he08UJ5 +qgrFgdgi56V4FdRs2EHJnezvYmviAbIsi8imn+9TVed4DnOmuE1rAgEC +-----END DH PARAMETERS----- diff --git a/test/fixtures/test_des.crt b/test/fixtures/test_des.crt new file mode 100644 index 00000000..3c146c56 --- /dev/null +++ b/test/fixtures/test_des.crt @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIIChTCCAe4CCQDbGP0P9s69azANBgkqhkiG9w0BAQsFADCBhjELMAkGA1UEBhMC +WlcxGzAZBgNVBAgMEk1hdGViZWxlbGFuZCBOb3J0aDERMA8GA1UEBwwIQnVsYXdh +eW8xDDAKBgNVBAoMA0J5bzELMAkGA1UECwwCSVQxDzANBgNVBAMMBmJ5by56dzEb +MBkGCSqGSIb3DQEJARYMYWRtaW5AYnlvLnp3MB4XDTE1MDQxMDA5NTM1OVoXDTE2 +MDQwOTA5NTM1OVowgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxh +bmQgTm9ydGgxETAPBgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNV +BAsMAklUMQ8wDQYDVQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5 +by56dzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0q4cDxLRslRKvG2pw5Gx +7fsq7YyiTokoBaDavNold5Vvayi02Mc7dqIanr/ckc0AqgiDd5Kw2bBAYmQpWiDn +pZxp79JIV+gGh7pkiB4wDzvRBXMcew72B9uuYEeUQ8eonE/Yro0ZnD0ZGmBiuk/6 +5xyWNikBhfPLnb2V+Cr/EKsCAwEAATANBgkqhkiG9w0BAQsFAAOBgQAwigr+o+Y+ +5BiL6MuHLTaC+lcv9r2GTHb7wNea674Db3Bi3u6FgmyMsZ8npPSlR0t/YZcFWtRM +y4uXmw5zUutGZTbO/JFxts6kPV+a76mnNm71fF4QINkemmojvJyPZq9N+hV16dba +v1m+dTK7hDZvpd/sM5bMtqWEq4aHkGhujw== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/test/fixtures/test_des.csr b/test/fixtures/test_des.csr new file mode 100644 index 00000000..7851a725 --- /dev/null +++ b/test/fixtures/test_des.csr @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIB3jCCAUcCAQAwgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxh +bmQgTm9ydGgxETAPBgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNV +BAsMAklUMQ8wDQYDVQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5 +by56dzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0q4cDxLRslRKvG2pw5Gx +7fsq7YyiTokoBaDavNold5Vvayi02Mc7dqIanr/ckc0AqgiDd5Kw2bBAYmQpWiDn +pZxp79JIV+gGh7pkiB4wDzvRBXMcew72B9uuYEeUQ8eonE/Yro0ZnD0ZGmBiuk/6 +5xyWNikBhfPLnb2V+Cr/EKsCAwEAAaAXMBUGCSqGSIb3DQEJAjEIDAZCeW8gQ28w +DQYJKoZIhvcNAQELBQADgYEAxP+4Z2POlTlCBYpGhhKpTBbRDeAQakXqGBlB7ZC2 +0K4fSxuAGVArLV5rbPDHlzNCtmF8mvt55F7zVny4YQ8BHE7ujV3SWtiAr0Otq9VV +WG5LmBLAbyrrUZloHJEpX0wPgQDmMdLhkDkbcjcKOT6WKNW5q36MW+Q9nViStGD5 +lJg= +-----END CERTIFICATE REQUEST----- \ No newline at end of file diff --git a/test/fixtures/test_des.key b/test/fixtures/test_des.key new file mode 100644 index 00000000..ec1c5ece --- /dev/null +++ b/test/fixtures/test_des.key @@ -0,0 +1,18 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,8D7649F2550A3AD6 + +iD68IbbRZDJuiYBqiEMLSfQQqcbXr4CeHFVkAYxCKN785tg+icShBeYXP2H2Oa7m +dmFBNrtuPclUjk1VFeDcRhd1WwabuSbKJkV26bqIwYKSa1blDcgviSvIc8OgN06G +K7kX+3jQzUMeSj+B1phyysCSoSU059oJvcNknBOEe67ersYZhXWFDOxVOeCnpsVA +xDPRGVWa5g5jj0WqcXey/oC/hUccX8w8RZJLSBurIxfWBGy1QtsnopNRaxs5gqXj +FCucQtYTMwRzA0c65/6yDrYrnv3v0mmCKBKXoTvhcmxkE/Ejrk0+ydxlgWXoMjOD +CzuDy8xQ2KN2/62fb0Eb6LwnI3EHceXAO9GbgpCTXDZt0yoKMBDZFYA1+TuYBXJj +RRcKDcF+gt1VdloSkAWIaDwypnPi0xngsJbzNIHKoSKYPuxWdUXB5rThbSdPki5x +r8La88LBK6/WarJevce8Ggg/KCAx5ng/w9XzQDlMSNVT6Ht+gGe6+69XjBA5IyIo +bymu9PlwRMMYEeEcH53tGXcCgSkzlDs2Cc+1+JUypZpX4oggNV5YhsmLZS5BtPFs +9i3lA7RsxXoV0u1BTgHIqrH58IKaXN9xs0ceie3cLR5tcSiSsU9sh3wpjZ2AZ/Q5 +zjoHuyzQVxY14qlE3uWzI9vJtc/kCkQ4D8wdBRVM8uRzf+YGYKRbI6vvsSICeLuW +n82E2zin77HnIOGVHPJ5aNaTQD91Ubxxv7lVeuxZf2tgejs2DbJraKOtOmHLd9GA +Zb5G9TdFMxVcXq18xUMm/Rbkj8ugALxRy8CGNSrTFTPHaEwYxqhnAQ== +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/test/fixtures/test_des.p7b b/test/fixtures/test_des.p7b new file mode 100644 index 00000000..430c129f --- /dev/null +++ b/test/fixtures/test_des.p7b @@ -0,0 +1,17 @@ +-----BEGIN PKCS7----- +MIICtgYJKoZIhvcNAQcCoIICpzCCAqMCAQExADALBgkqhkiG9w0BBwGgggKJMIIC +hTCCAe4CCQDbGP0P9s69azANBgkqhkiG9w0BAQsFADCBhjELMAkGA1UEBhMCWlcx +GzAZBgNVBAgMEk1hdGViZWxlbGFuZCBOb3J0aDERMA8GA1UEBwwIQnVsYXdheW8x +DDAKBgNVBAoMA0J5bzELMAkGA1UECwwCSVQxDzANBgNVBAMMBmJ5by56dzEbMBkG +CSqGSIb3DQEJARYMYWRtaW5AYnlvLnp3MB4XDTE1MDQxMDA5NTM1OVoXDTE2MDQw +OTA5NTM1OVowgYYxCzAJBgNVBAYTAlpXMRswGQYDVQQIDBJNYXRlYmVsZWxhbmQg +Tm9ydGgxETAPBgNVBAcMCEJ1bGF3YXlvMQwwCgYDVQQKDANCeW8xCzAJBgNVBAsM +AklUMQ8wDQYDVQQDDAZieW8uencxGzAZBgkqhkiG9w0BCQEWDGFkbWluQGJ5by56 +dzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0q4cDxLRslRKvG2pw5Gx7fsq +7YyiTokoBaDavNold5Vvayi02Mc7dqIanr/ckc0AqgiDd5Kw2bBAYmQpWiDnpZxp +79JIV+gGh7pkiB4wDzvRBXMcew72B9uuYEeUQ8eonE/Yro0ZnD0ZGmBiuk/65xyW +NikBhfPLnb2V+Cr/EKsCAwEAATANBgkqhkiG9w0BAQsFAAOBgQAwigr+o+Y+5BiL +6MuHLTaC+lcv9r2GTHb7wNea674Db3Bi3u6FgmyMsZ8npPSlR0t/YZcFWtRMy4uX +mw5zUutGZTbO/JFxts6kPV+a76mnNm71fF4QINkemmojvJyPZq9N+hV16dbav1m+ +dTK7hDZvpd/sM5bMtqWEq4aHkGhuj6EAMQA= +-----END PKCS7----- diff --git a/test/fixtures/testnopw.key b/test/fixtures/testnopw.key index d507c834..5d1eb34e 100644 --- a/test/fixtures/testnopw.key +++ b/test/fixtures/testnopw.key @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQDSrhwPEtGyVEq8banDkbHt+yrtjKJOiSgFoNq82iV3lW9rKLTY -xzt2ohqev9yRzQCqCIN3krDZsEBiZClaIOelnGnv0khX6AaHumSIHjAPO9EFcxx7 -DvYH265gR5RDx6icT9iujRmcPRkaYGK6T/rnHJY2KQGF88udvZX4Kv8QqwIDAQAB -AoGALuEtPzFp1eupwaoJR4pI9HKaR8euahlc/XugkLtd8PEgnNCvBTm4Aprpn3+D -3jGmvy8rydSrY5UzjnFJPlPqF2kWkQaBFtqBJpQFjCPDbQ3nwVoaEN7X/lz3v91M -BdoMT36CPvzDwtdrA3U16Jd1JOV09DxP/7jAuvrP3zvuoOkCQQD/eXu/UL++xUb8 -BH4hkookSWrRJHIsRw5gktMoo2tGhe0AXVDh+3Eg8KNfvy2T/PqI7z/pn3QTcjn6 -hJlG7ujVAkEA0x0KUstDNB8FEn64xfmmbCWJ/kyYm3dtiR1ByvqNBJ4Dt3IAIwnP -1ww9NWJfZta34nUzI97rDLyvBubaN0rTfwJBAM1kDOIt+EpWbpBUyFcTai5sPA1y -4LvKULvBrzQ/1hI3v+gIHevg6/3QmXhzyh/tRjrrJpYb1QWBUy2eh2Bo2RUCQQCl -hPROG62yFMwORyqpleXkjr4VkopoAgfwY+7srOqZfyZc0tXGou/ApIjs7Rbtc1Wz -CL6y1hkl4F2+JItcpJ8TAkBUGA1T46IMHtQ4D7HaemPup+ve7gwYx2c1EDlLYAc/ -M9y+va/N+2k6DAMHUNIRktmgYsA5inGT/QCftLql4v+5 ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2YDr9Gl+QDoi8 +iqv6x5JAR/Up1wuSyxrgVK6aVQ6P3hBizKC4PTULM6v1w5W3XN4M+46LToSgH2nx +ypwUFgbu0LFAwzSBbt+riAwU8g1oYebcpDj6g2TrzDbfE3iCM7eAZCVu1AgYAEk6 +Z+6b2yrpk8o23OkbwS5OxnTcN22g+aMatYFfZIO06BmOEihxdtY9n9Woj/1aL5uv +/p7LpX0VwOnq17XVp00/iO6aajW34iBa8i1uZE17ZF4+iHZJn+dGi2kfx2vMFA9O +hJz9TiblY2+EVSxfXsLPK9OnaNBsrNjUVYjUVChv1zKED88g5OrwkSFIk9kEXF6e +vXO7w9ExAgMBAAECggEAAUpfiHx4CiUsLwddLa5dWNKZh8UDijOhOk6nGKT68CYu +YACaL4uRVUW1lQzgAZbo5FcgXFh/JEHspj8ciSDZxjVYV8C53aOa9hQFn91Rnng4 +4b1QwOcOnwOILN5upx82EHTE9gqOjxrrabwkClrL7DC1SNuZ064zhW+ukoNa5X1z +q+DwEZ6XaKz3/vh+llTPMP0KSrCKg5z55d1ZgQAfOp41hEIJEyjJjh1htjzuQJvr ++V4cX1FY2DZKDGGiQ/gmHIqRsyYE539xVA0BP/dhaNfHpdxK5mHnP3LOHKVzZ9xc +sERbvbNpCtkvAIDV1cP7LyPnCX2oIW9lDUz91aE2BQKBgQDjfoWCd8YHrbHan6dr +cCg35PLvR60Uwg383B0lQ5o4+zd6z6JJxk/3h9s5GTksEngXOM+XEMOdgQY2asA/ +C9H4RbE+ISBdHSz7xE7qI8u20h3Ce5HcIKjYd7NifKVNqDHsC0LMfsVFb4kBV872 +K3u4ehHMmXi6d6QzDW5DaCPInQKBgQDNOmtd9Xgacux0yW/QAg3hqqkoN9pgtjjM +mGbcSbvsnR/JGqC+nh1kZm2h14EWC3EqgkcqEifX1DRVjQXSt283oJAQYKdN4Vvs +w5L2WaUB9i+89yGQvCDMM0iorApHZCSBnztOCQUF6Wjo5JSRaop78+V+sk+h4U1/ +x+959GBUpQKBgQDWo+c/49YaJI3sIjqKKfYoVoHHta7eKQGdk+iD4ja+kHgWDZWn +Wc7VU39Jbjz9EifwcQ+cDpsiHjxIV4wvb+2Z+9dxMTwh3oc0vFFgpIluYuzlNEW4 +la/5HWdJAyXMEWeYuD88RlfGXae8dqa0qO5AbhwhGKRJ+twXtxJT0wwAGQKBgCay +62gOT5V9MkVbbrAkkwWIrtkcnxs5gUBjRJIpfTxC7Kl5UfJf0l8KSYYJIxhLFA3V +/yFZxxWVuEChlQWE/X3Z0xCjiSjQZAsjXeUCRnE2QQ4686NdNjoLOZpExrNrmM6w +ffhbDw1sVBIGeFVrZ62z8gSQDyARYhHEW839XOTZAoGAfA7qfDBe0orhH4KHEJQm +Gp+fb6pJbBaUoVMEduQ1VYErtfOfEKMZBkHxZRGFQhS5KYNQosQGqQUCDL2C8oxw +SDeWRm+EGSMxAYbDZo2wIVOxHDpCy3JoPud4k3xzZ200XL0XrBgX5q0VyxmEHhvH +pR/RdflkP931QipkmNq8hzQ= +-----END PRIVATE KEY----- diff --git a/test/fixtures/testnopw_des.key b/test/fixtures/testnopw_des.key new file mode 100644 index 00000000..d507c834 --- /dev/null +++ b/test/fixtures/testnopw_des.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDSrhwPEtGyVEq8banDkbHt+yrtjKJOiSgFoNq82iV3lW9rKLTY +xzt2ohqev9yRzQCqCIN3krDZsEBiZClaIOelnGnv0khX6AaHumSIHjAPO9EFcxx7 +DvYH265gR5RDx6icT9iujRmcPRkaYGK6T/rnHJY2KQGF88udvZX4Kv8QqwIDAQAB +AoGALuEtPzFp1eupwaoJR4pI9HKaR8euahlc/XugkLtd8PEgnNCvBTm4Aprpn3+D +3jGmvy8rydSrY5UzjnFJPlPqF2kWkQaBFtqBJpQFjCPDbQ3nwVoaEN7X/lz3v91M +BdoMT36CPvzDwtdrA3U16Jd1JOV09DxP/7jAuvrP3zvuoOkCQQD/eXu/UL++xUb8 +BH4hkookSWrRJHIsRw5gktMoo2tGhe0AXVDh+3Eg8KNfvy2T/PqI7z/pn3QTcjn6 +hJlG7ujVAkEA0x0KUstDNB8FEn64xfmmbCWJ/kyYm3dtiR1ByvqNBJ4Dt3IAIwnP +1ww9NWJfZta34nUzI97rDLyvBubaN0rTfwJBAM1kDOIt+EpWbpBUyFcTai5sPA1y +4LvKULvBrzQ/1hI3v+gIHevg6/3QmXhzyh/tRjrrJpYb1QWBUy2eh2Bo2RUCQQCl +hPROG62yFMwORyqpleXkjr4VkopoAgfwY+7srOqZfyZc0tXGou/ApIjs7Rbtc1Wz +CL6y1hkl4F2+JItcpJ8TAkBUGA1T46IMHtQ4D7HaemPup+ve7gwYx2c1EDlLYAc/ +M9y+va/N+2k6DAMHUNIRktmgYsA5inGT/QCftLql4v+5 +-----END RSA PRIVATE KEY----- diff --git a/test/openssl.spec.js b/test/openssl.spec.js index e0499bb7..e63ec84e 100644 --- a/test/openssl.spec.js +++ b/test/openssl.spec.js @@ -7,6 +7,8 @@ var dirtyChai = require('dirty-chai') var expect = chai.expect chai.use(dirtyChai) +const fipsEnabled = require('node:crypto').getFips() + // NOTE: we cover here only the test cases left in coverage report describe('openssl.js tests', function () { this.timeout(300000)// 5 minutes @@ -18,8 +20,8 @@ describe('openssl.js tests', function () { 'dhparam', '-outform', 'PEM', - 1024 - ], 'DH PARAMETERS 1024', function (error) { + (fipsEnabled ? 2048 : 1024) + ], 'DH PARAMETERS ' + (fipsEnabled ? 2048 : 1024), function (error) { hlp.checkError(error, true) done() }) @@ -43,7 +45,7 @@ describe('openssl.js tests', function () { 'dhparam', '-outform', 'PEM', - 1024 + (fipsEnabled ? 2048 : 1024) ], function (error, result) { hlp.checkError(error) expect(result).to.be.ok() diff --git a/test/pem.spec.js b/test/pem.spec.js index 8c196084..607ba2c2 100644 --- a/test/pem.spec.js +++ b/test/pem.spec.js @@ -4,13 +4,15 @@ var pem = require('../lib/pem') var openssl = require('../lib/openssl.js') var fs = require('fs') var hlp = require('./pem.helper.js') -const {createHash} = require('node:crypto') +const {createHash, getFips} = require('node:crypto') const {debug} = require('../lib/debug.js') var chai = require('chai') var dirtyChai = require('dirty-chai') var expect = chai.expect chai.use(dirtyChai) +const fipsEnabled = getFips() + describe('General Tests', function () { this.timeout(300000)// 5 minutes this.slow(2000)// 2 seconds @@ -62,12 +64,19 @@ describe('General Tests', function () { it('Create default sized dhparam key', function (done) { pem.createDhparam(function (error, data) { hlp.checkError(error) - hlp.checkDhparam(data, 150, 160) + if (!fipsEnabled) { + hlp.checkDhparam(data, 150, 160) + } else { + hlp.checkDhparam(data, 420, 430) + } hlp.checkTmpEmpty() done() }) }) it('Create 1024bit dhparam key', function (done) { + if(fipsEnabled) { + this.skip("1024bit DH parameters are not allowed in FIPS mode") + } this.timeout(600000)// 10 minutes pem.createDhparam(1024, function (error, data) { var maxKeySize = 250; @@ -86,7 +95,11 @@ describe('General Tests', function () { it('Create default ecparam key', function (done) { pem.createEcparam(function (error, data) { hlp.checkError(error) - hlp.checkEcparam(data, 430, 530) + if (!fipsEnabled) { + hlp.checkEcparam(data, 430, 530) // Default is secp256k1 in non-FIPS mode + } else { + hlp.checkEcparam(data, 430, 570) // Default is prime256v1 in FIPS mode + } hlp.checkTmpEmpty() done() }) @@ -100,6 +113,9 @@ describe('General Tests', function () { }) }) it('Create prime256v1 ecparam key', function (done) { + if(fipsEnabled) { + this.skip("prime256v1 is the default curve in FIPS mode, so this test is redundant") + } pem.createEcparam('prime256v1', function (error, data) { hlp.checkError(error) hlp.checkEcparam(data, 430, 570) @@ -476,6 +492,9 @@ describe('General Tests', function () { }) it('get its modulus [md5 hashed]', function (done) { + if(fipsEnabled) { + this.skip("MD5 hashing is not allowed in FIPS mode") + } pem.getModulus(cert.certificate, function (error, rawData) { hlp.checkError(error) hlp.checkModulus(rawData) @@ -560,6 +579,9 @@ describe('General Tests', function () { }) it('get its modulus [md5 hashed]', function (done) { + if(fipsEnabled) { + this.skip("MD5 hashing is not allowed in FIPS mode") + } pem.getModulus(cert.certificate, function (error, rawData) { hlp.checkError(error) hlp.checkModulus(rawData) @@ -623,7 +645,8 @@ describe('General Tests', function () { var ca it('create ca certificate', function (done) { pem.createCertificate({ - commonName: 'CA Certificate' + commonName: 'CA Certificate', + CA: true }, function (error, data) { hlp.checkError(error) @@ -738,7 +761,7 @@ describe('General Tests', function () { expect(valid).to.be.true() pem.createPkcs12(data.clientKey, - data.certificate, '', { + data.certificate, (fipsEnabled ? 'password' : ''), { certFiles: [ca.certificate] }, function (error, d) { @@ -746,7 +769,9 @@ describe('General Tests', function () { expect(d).to.be.ok() hlp.checkTmpEmpty() - pem.readPkcs12(d.pkcs12, + pem.readPkcs12(d.pkcs12, { + p12Password: (fipsEnabled ? 'password' : '') + }, function (error, keystore) { debug("verify signing chain; create and read PKCS12 - pem.readPkcs12", { error: error, @@ -771,12 +796,14 @@ describe('General Tests', function () { }) context('pkcs12 -export -out "$pfx" -inkey "$key" -in "$cert" -certfile "$ca_bundle" -passout "pass:"', function () { it('verify right order of chains; read PKCS12', function (done) { - let pkcs12_5_file_pfx = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_keyStore.p12') - let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + let pkcs12_5_file_pfx = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_keyStore' + (fipsEnabled ? '' : '_legacy') + '.p12') + let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA' + (fipsEnabled ? '' : '_traditional') + '.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_4_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_4_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_5_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let geotrust_primary_ca_cert = fs.readFileSync('./test/fixtures/GeoTrust_Primary_CA.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() - pem.readPkcs12(pkcs12_5_file_pfx, + pem.readPkcs12(pkcs12_5_file_pfx, { + p12Password: (fipsEnabled ? 'password' : '') + }, function (error, keystore) { debug("verify right order of chains; read PKCS12 - pem.readPkcs12", { error: error, @@ -800,12 +827,14 @@ describe('General Tests', function () { }) context('pkcs12 -export -out "pfx" -inkey "$key" -in "$cert + $ca_bundle" -passout "pass:"', function () { it('verify right order of chains; read PKCS12', function (done) { - let pkcs12_5_file_pfx = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_keyStore2.p12') - let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + let pkcs12_5_file_pfx = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_keyStore2' + (fipsEnabled ? '' : '_legacy') + '.p12') + let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA' + (fipsEnabled ? '' : '_traditional') + '.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_4_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_4_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_5_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let geotrust_primary_ca_cert = fs.readFileSync('./test/fixtures/GeoTrust_Primary_CA.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() - pem.readPkcs12(pkcs12_5_file_pfx, + pem.readPkcs12(pkcs12_5_file_pfx, { + p12Password: (fipsEnabled ? 'password' : '') + }, function (error, keystore) { debug("verify right order of chains; read PKCS12 - pem.readPkcs12", { error: error, @@ -1219,16 +1248,16 @@ describe('General Tests', function () { }) describe('#.checkCertificate tests', function () { - it('Check certificate file @ ./test/fixtures/test.key', function (done) { - var d = fs.readFileSync('./test/fixtures/test.key').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + it('Check certificate file @ ./test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key', function (done) { + var d = fs.readFileSync('./test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() pem.checkCertificate(d, 'password', function (error, result) { hlp.checkError(error) expect(result).to.be.ok() done() }) }) - it('Check certificate file @ ./test/fixtures/test.crt', function (done) { - var d = fs.readFileSync('./test/fixtures/test.crt').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + it('Check certificate file @ ./test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.crt', function (done) { + var d = fs.readFileSync('./test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.crt').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() pem.checkCertificate(d, function (error, result) { hlp.checkError(error) expect(result).to.be.ok() @@ -1247,13 +1276,13 @@ describe('General Tests', function () { describe('#.getModulus tests', function () { it('Check matching modulus of key and cert file', function (done) { - var f = fs.readFileSync('./test/fixtures/test.crt').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + var f = fs.readFileSync('./test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.crt').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() pem.getModulus(f, function (error, data1) { hlp.checkError(error) hlp.checkModulus(data1) hlp.checkTmpEmpty() - f = fs.readFileSync('./test/fixtures/test.key').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + f = fs.readFileSync('./test/fixtures/test' + (fipsEnabled ? '' : '_des') + '.key').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() pem.getModulus(f, 'password', function (error, data2) { hlp.checkError(error) hlp.checkModulus(data2) @@ -1267,15 +1296,19 @@ describe('General Tests', function () { describe('#.getDhparamInfo tests', function () { it('Get DH param info', function (done) { - var dh = fs.readFileSync('./test/fixtures/test.dh').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + var dh = fs.readFileSync('./test/fixtures/test' + (fipsEnabled ? '' : '_1024_bit') + '.dh').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() pem.getDhparamInfo(dh, function (error, data) { hlp.checkError(error) var size = (data && data.size) || 0 var prime = ((data && data.prime) || '').toString() expect(size).to.be.a('number') - expect(size).to.equal(1024) + expect(size).to.equal(fipsEnabled ? 2048 : 1024) expect(prime).to.be.a('string') - expect(/([0-9a-f][0-9a-f]:)+[0-9a-f][0-9a-f]$/g.test(prime)).to.be.true() + if (fipsEnabled) { + expect(/([0-9a-f][0-9a-f]:)*$/g.test(prime)).to.be.true() + } else { + expect(/([0-9a-f][0-9a-f]:)+[0-9a-f][0-9a-f]$/g.test(prime)).to.be.true() + } hlp.checkTmpEmpty() done() }) @@ -1296,7 +1329,7 @@ describe('General Tests', function () { describe('#.checkPkcs12 tests', function () { it('Check PKCS12 keystore', function (done) { - var pkcs12 = fs.readFileSync('./test/fixtures/idsrv3test.pfx') + var pkcs12 = fs.readFileSync('./test/fixtures/idsrv3test' + (fipsEnabled ? '' : '_legacy') + '.pfx') pem.checkPkcs12(pkcs12, 'idsrv3test', function (error, result) { hlp.checkError(error) expect(result).to.be.ok() From 998707dd814337d34a83d1e2cbc743fcc010c02d Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Fri, 10 Apr 2026 11:48:33 +0530 Subject: [PATCH 02/10] Add type check for `options.password` --- lib/helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/helper.js b/lib/helper.js index d4a7549c..c53ef8f2 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -71,7 +71,7 @@ var ciphers = module.exports.ciphers * @return {Boolean} result */ module.exports.createPasswordFile = function (options, params, PasswordFileArray) { - if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) { + if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !(typeof options.password === 'string') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) { return false } var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex')) From 5b6a61a0d1b23190173adc50e75fc63d690d74f5 Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Fri, 10 Apr 2026 11:49:09 +0530 Subject: [PATCH 03/10] Change `fileformat` to `unix` --- docs/docco/lib/helper.html | 262 +++++++++++++++++----------------- docs/jsdoc/helper.js.html | 276 ++++++++++++++++++------------------ lib/helper.js | 278 ++++++++++++++++++------------------- 3 files changed, 408 insertions(+), 408 deletions(-) diff --git a/docs/docco/lib/helper.html b/docs/docco/lib/helper.html index 16988f7b..74d2e576 100644 --- a/docs/docco/lib/helper.html +++ b/docs/docco/lib/helper.html @@ -58,57 +58,57 @@

helper.js

-
'use strict'
-
-var pathlib = require('path')
-var fs = require('fs')
-var crypto = require('crypto')
-var osTmpdir = require('os-tmpdir')
-var tempDir = process.env.PEMJS_TMPDIR || osTmpdir()
-
-/**
- * pem helper module
- *
- * @module helper
- */
-
-/**
- * helper function to check is the string a number or not
- * @param {String} str String that should be checked to be a number
- */
-module.exports.isNumber = function (str) {
-  if (Array.isArray(str)) {
-    return false
-  }
-  /*
-  var bstr = str && str.toString()
-  str = str + ''
-
-  return bstr - parseFloat(bstr) + 1 >= 0 &&
-          !/^\s+|\s+$/g.test(str) && /^\d+$/g.test(str) &&
-          !isNaN(str) && !isNaN(parseFloat(str))
-  */
-  return /^\d+$/g.test(str)
-}
-
-/**
- * helper function to check is the string a hexaceximal value
- * @param {String} hex String that should be checked to be a hexaceximal
- */
-module.exports.isHex = function isHex (hex) {
-  return /^(0x){0,1}([0-9A-F]{1,40}|[0-9A-F]{1,40})$/gi.test(hex)
-}
-
-/**
- * helper function to convert a string to a hexaceximal value
- * @param {String} str String that should be converted to a hexaceximal
- */
-module.exports.toHex = function toHex (str) {
-  var hex = ''
-  for (var i = 0; i < str.length; i++) {
-    hex += '' + str.charCodeAt(i).toString(16)
-  }
-  return hex
+            
'use strict'
+
+var pathlib = require('path')
+var fs = require('fs')
+var crypto = require('crypto')
+var osTmpdir = require('os-tmpdir')
+var tempDir = process.env.PEMJS_TMPDIR || osTmpdir()
+
+/**
+ * pem helper module
+ *
+ * @module helper
+ */
+
+/**
+ * helper function to check is the string a number or not
+ * @param {String} str String that should be checked to be a number
+ */
+module.exports.isNumber = function (str) {
+  if (Array.isArray(str)) {
+    return false
+  }
+  /*
+  var bstr = str && str.toString()
+  str = str + ''
+
+  return bstr - parseFloat(bstr) + 1 >= 0 &&
+          !/^\s+|\s+$/g.test(str) && /^\d+$/g.test(str) &&
+          !isNaN(str) && !isNaN(parseFloat(str))
+  */
+  return /^\d+$/g.test(str)
+}
+
+/**
+ * helper function to check is the string a hexaceximal value
+ * @param {String} hex String that should be checked to be a hexaceximal
+ */
+module.exports.isHex = function isHex (hex) {
+  return /^(0x){0,1}([0-9A-F]{1,40}|[0-9A-F]{1,40})$/gi.test(hex)
+}
+
+/**
+ * helper function to convert a string to a hexaceximal value
+ * @param {String} str String that should be converted to a hexaceximal
+ */
+module.exports.toHex = function toHex (str) {
+  var hex = ''
+  for (var i = 0; i < str.length; i++) {
+    hex += '' + str.charCodeAt(i).toString(16)
+  }
+  return hex
 }
@@ -124,65 +124,65 @@

helper.js

-
/**
- * list of supported ciphers
- * @type {Array}
- */
-module.exports.ciphers = ['aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea']
-var ciphers = module.exports.ciphers
-
-/**
- * Creates a PasswordFile to hide the password form process infos via `ps auxf` etc.
- * @param {Object} options object of cipher, password and passType, mustPass, {cipher:'aes128', password:'xxxx', passType:"in/out/word"}, if the object empty we do nothing
- * @param {String} options.cipher cipher like 'aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea'
- * @param {String} options.password password can be empty or at last 4 to 1023 chars
- * @param {String} options.passType passType: can be in/out/word for passIN/passOUT/passWORD
- * @param {Boolean} options.mustPass mustPass is used when you need to set the pass like as "-password pass:" most needed when empty password
- * @param {Object} params params will be extended with the data that need for the openssl command. IS USED AS POINTER!
- * @param {String} PasswordFileArray PasswordFileArray is an array of filePaths that later need to deleted ,after the openssl command. IS USED AS POINTER!
- * @return {Boolean} result
- */
-module.exports.createPasswordFile = function (options, params, PasswordFileArray) {
-  if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) {
-    return false
-  }
-  var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex'))
-  PasswordFileArray.push(PasswordFile)
-  options.password = options.password.trim()
-  if (options.password === '') {
-    options.mustPass = true
-  }
-  if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) {
-    params.push('-' + options.cipher)
-  }
-  params.push('-pass' + options.passType)
-  if (options.mustPass) {
-    params.push('pass:' + options.password)
-  } else {
-    fs.writeFileSync(PasswordFile, options.password)
-    params.push('file:' + PasswordFile)
-  }
-  return true
-}
-
-/**
- * Deletes a file or an array of files
- * @param {Array} files array of files that shoudld be deleted
- * @param {errorCallback} callback Callback function with an error object
- */
-module.exports.deleteTempFiles = function (files, callback) {
-  var rmFiles = []
-  if (typeof files === 'string') {
-    rmFiles.push(files)
-  } else if (Array.isArray(files)) {
-    rmFiles = files
-  } else {
-    return callback(new Error('Unexcepted files parameter type; only string or array supported'))
-  }
-  var deleteSeries = function (list, finalCallback) {
-    if (list.length) {
-      var file = list.shift()
-      var myCallback = function (err) {
+            
/**
+ * list of supported ciphers
+ * @type {Array}
+ */
+module.exports.ciphers = ['aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea']
+var ciphers = module.exports.ciphers
+
+/**
+ * Creates a PasswordFile to hide the password form process infos via `ps auxf` etc.
+ * @param {Object} options object of cipher, password and passType, mustPass, {cipher:'aes128', password:'xxxx', passType:"in/out/word"}, if the object empty we do nothing
+ * @param {String} options.cipher cipher like 'aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea'
+ * @param {String} options.password password can be empty or at last 4 to 1023 chars
+ * @param {String} options.passType passType: can be in/out/word for passIN/passOUT/passWORD
+ * @param {Boolean} options.mustPass mustPass is used when you need to set the pass like as "-password pass:" most needed when empty password
+ * @param {Object} params params will be extended with the data that need for the openssl command. IS USED AS POINTER!
+ * @param {String} PasswordFileArray PasswordFileArray is an array of filePaths that later need to deleted ,after the openssl command. IS USED AS POINTER!
+ * @return {Boolean} result
+ */
+module.exports.createPasswordFile = function (options, params, PasswordFileArray) {
+  if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) {
+    return false
+  }
+  var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex'))
+  PasswordFileArray.push(PasswordFile)
+  options.password = options.password.trim()
+  if (options.password === '') {
+    options.mustPass = true
+  }
+  if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) {
+    params.push('-' + options.cipher)
+  }
+  params.push('-pass' + options.passType)
+  if (options.mustPass) {
+    params.push('pass:' + options.password)
+  } else {
+    fs.writeFileSync(PasswordFile, options.password)
+    params.push('file:' + PasswordFile)
+  }
+  return true
+}
+
+/**
+ * Deletes a file or an array of files
+ * @param {Array} files array of files that shoudld be deleted
+ * @param {errorCallback} callback Callback function with an error object
+ */
+module.exports.deleteTempFiles = function (files, callback) {
+  var rmFiles = []
+  if (typeof files === 'string') {
+    rmFiles.push(files)
+  } else if (Array.isArray(files)) {
+    rmFiles = files
+  } else {
+    return callback(new Error('Unexcepted files parameter type; only string or array supported'))
+  }
+  var deleteSeries = function (list, finalCallback) {
+    if (list.length) {
+      var file = list.shift()
+      var myCallback = function (err) {
         if (err && err.code === 'ENOENT') {
@@ -198,7 +198,7 @@

helper.js

-
          return deleteSeries(list, finalCallback)
+            
          return deleteSeries(list, finalCallback)
         } else if (err) {
@@ -214,26 +214,26 @@

helper.js

-
          return finalCallback(err)
-        } else {
-          return deleteSeries(list, finalCallback)
-        }
-      }
-      if (file && typeof file === 'string') {
-        fs.unlink(file, myCallback)
-      } else {
-        return deleteSeries(list, finalCallback)
-      }
-    } else {
-      return finalCallback(null) // no errors
-    }
-  }
-  deleteSeries(rmFiles, callback)
-}
-/**
- * Callback for return an error object.
- * @callback errorCallback
- * @param {Error} err - An Error Object or null
+            
          return finalCallback(err)
+        } else {
+          return deleteSeries(list, finalCallback)
+        }
+      }
+      if (file && typeof file === 'string') {
+        fs.unlink(file, myCallback)
+      } else {
+        return deleteSeries(list, finalCallback)
+      }
+    } else {
+      return finalCallback(null) // no errors
+    }
+  }
+  deleteSeries(rmFiles, callback)
+}
+/**
+ * Callback for return an error object.
+ * @callback errorCallback
+ * @param {Error} err - An Error Object or null
  */
diff --git a/docs/jsdoc/helper.js.html b/docs/jsdoc/helper.js.html index 20cb12f9..29896085 100644 --- a/docs/jsdoc/helper.js.html +++ b/docs/jsdoc/helper.js.html @@ -38,144 +38,144 @@

helper.js

-
'use strict'
-
-var pathlib = require('path')
-var fs = require('fs')
-var crypto = require('crypto')
-var osTmpdir = require('os-tmpdir')
-var tempDir = process.env.PEMJS_TMPDIR || osTmpdir()
-
-/**
- * pem helper module
- *
- * @module helper
- */
-
-/**
- * helper function to check is the string a number or not
- * @param {String} str String that should be checked to be a number
- */
-module.exports.isNumber = function (str) {
-  if (Array.isArray(str)) {
-    return false
-  }
-  /*
-  var bstr = str && str.toString()
-  str = str + ''
-
-  return bstr - parseFloat(bstr) + 1 >= 0 &&
-          !/^\s+|\s+$/g.test(str) && /^\d+$/g.test(str) &&
-          !isNaN(str) && !isNaN(parseFloat(str))
-  */
-  return /^\d+$/g.test(str)
-}
-
-/**
- * helper function to check is the string a hexaceximal value
- * @param {String} hex String that should be checked to be a hexaceximal
- */
-module.exports.isHex = function isHex (hex) {
-  return /^(0x){0,1}([0-9A-F]{1,40}|[0-9A-F]{1,40})$/gi.test(hex)
-}
-
-/**
- * helper function to convert a string to a hexaceximal value
- * @param {String} str String that should be converted to a hexaceximal
- */
-module.exports.toHex = function toHex (str) {
-  var hex = ''
-  for (var i = 0; i < str.length; i++) {
-    hex += '' + str.charCodeAt(i).toString(16)
-  }
-  return hex
-}
-
-// cipherPassword returns an array of supported ciphers.
-/**
- * list of supported ciphers
- * @type {Array}
- */
-module.exports.ciphers = ['aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea']
-var ciphers = module.exports.ciphers
-
-/**
- * Creates a PasswordFile to hide the password form process infos via `ps auxf` etc.
- * @param {Object} options object of cipher, password and passType, mustPass, {cipher:'aes128', password:'xxxx', passType:"in/out/word"}, if the object empty we do nothing
- * @param {String} options.cipher cipher like 'aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea'
- * @param {String} options.password password can be empty or at last 4 to 1023 chars
- * @param {String} options.passType passType: can be in/out/word for passIN/passOUT/passWORD
- * @param {Boolean} options.mustPass mustPass is used when you need to set the pass like as "-password pass:" most needed when empty password
- * @param {Object} params params will be extended with the data that need for the openssl command. IS USED AS POINTER!
- * @param {String} PasswordFileArray PasswordFileArray is an array of filePaths that later need to deleted ,after the openssl command. IS USED AS POINTER!
- * @return {Boolean} result
- */
-module.exports.createPasswordFile = function (options, params, PasswordFileArray) {
-  if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) {
-    return false
-  }
-  var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex'))
-  PasswordFileArray.push(PasswordFile)
-  options.password = options.password.trim()
-  if (options.password === '') {
-    options.mustPass = true
-  }
-  if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) {
-    params.push('-' + options.cipher)
-  }
-  params.push('-pass' + options.passType)
-  if (options.mustPass) {
-    params.push('pass:' + options.password)
-  } else {
-    fs.writeFileSync(PasswordFile, options.password)
-    params.push('file:' + PasswordFile)
-  }
-  return true
-}
-
-/**
- * Deletes a file or an array of files
- * @param {Array} files array of files that shoudld be deleted
- * @param {errorCallback} callback Callback function with an error object
- */
-module.exports.deleteTempFiles = function (files, callback) {
-  var rmFiles = []
-  if (typeof files === 'string') {
-    rmFiles.push(files)
-  } else if (Array.isArray(files)) {
-    rmFiles = files
-  } else {
-    return callback(new Error('Unexcepted files parameter type; only string or array supported'))
-  }
-  var deleteSeries = function (list, finalCallback) {
-    if (list.length) {
-      var file = list.shift()
-      var myCallback = function (err) {
-        if (err && err.code === 'ENOENT') {
-          // file doens't exist
-          return deleteSeries(list, finalCallback)
-        } else if (err) {
-          // other errors, e.g. maybe we don't have enough permission
-          return finalCallback(err)
-        } else {
-          return deleteSeries(list, finalCallback)
-        }
-      }
-      if (file && typeof file === 'string') {
-        fs.unlink(file, myCallback)
-      } else {
-        return deleteSeries(list, finalCallback)
-      }
-    } else {
-      return finalCallback(null) // no errors
-    }
-  }
-  deleteSeries(rmFiles, callback)
-}
-/**
- * Callback for return an error object.
- * @callback errorCallback
- * @param {Error} err - An Error Object or null
+            
'use strict'
+
+var pathlib = require('path')
+var fs = require('fs')
+var crypto = require('crypto')
+var osTmpdir = require('os-tmpdir')
+var tempDir = process.env.PEMJS_TMPDIR || osTmpdir()
+
+/**
+ * pem helper module
+ *
+ * @module helper
+ */
+
+/**
+ * helper function to check is the string a number or not
+ * @param {String} str String that should be checked to be a number
+ */
+module.exports.isNumber = function (str) {
+  if (Array.isArray(str)) {
+    return false
+  }
+  /*
+  var bstr = str && str.toString()
+  str = str + ''
+
+  return bstr - parseFloat(bstr) + 1 >= 0 &&
+          !/^\s+|\s+$/g.test(str) && /^\d+$/g.test(str) &&
+          !isNaN(str) && !isNaN(parseFloat(str))
+  */
+  return /^\d+$/g.test(str)
+}
+
+/**
+ * helper function to check is the string a hexaceximal value
+ * @param {String} hex String that should be checked to be a hexaceximal
+ */
+module.exports.isHex = function isHex (hex) {
+  return /^(0x){0,1}([0-9A-F]{1,40}|[0-9A-F]{1,40})$/gi.test(hex)
+}
+
+/**
+ * helper function to convert a string to a hexaceximal value
+ * @param {String} str String that should be converted to a hexaceximal
+ */
+module.exports.toHex = function toHex (str) {
+  var hex = ''
+  for (var i = 0; i < str.length; i++) {
+    hex += '' + str.charCodeAt(i).toString(16)
+  }
+  return hex
+}
+
+// cipherPassword returns an array of supported ciphers.
+/**
+ * list of supported ciphers
+ * @type {Array}
+ */
+module.exports.ciphers = ['aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea']
+var ciphers = module.exports.ciphers
+
+/**
+ * Creates a PasswordFile to hide the password form process infos via `ps auxf` etc.
+ * @param {Object} options object of cipher, password and passType, mustPass, {cipher:'aes128', password:'xxxx', passType:"in/out/word"}, if the object empty we do nothing
+ * @param {String} options.cipher cipher like 'aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea'
+ * @param {String} options.password password can be empty or at last 4 to 1023 chars
+ * @param {String} options.passType passType: can be in/out/word for passIN/passOUT/passWORD
+ * @param {Boolean} options.mustPass mustPass is used when you need to set the pass like as "-password pass:" most needed when empty password
+ * @param {Object} params params will be extended with the data that need for the openssl command. IS USED AS POINTER!
+ * @param {String} PasswordFileArray PasswordFileArray is an array of filePaths that later need to deleted ,after the openssl command. IS USED AS POINTER!
+ * @return {Boolean} result
+ */
+module.exports.createPasswordFile = function (options, params, PasswordFileArray) {
+  if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) {
+    return false
+  }
+  var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex'))
+  PasswordFileArray.push(PasswordFile)
+  options.password = options.password.trim()
+  if (options.password === '') {
+    options.mustPass = true
+  }
+  if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) {
+    params.push('-' + options.cipher)
+  }
+  params.push('-pass' + options.passType)
+  if (options.mustPass) {
+    params.push('pass:' + options.password)
+  } else {
+    fs.writeFileSync(PasswordFile, options.password)
+    params.push('file:' + PasswordFile)
+  }
+  return true
+}
+
+/**
+ * Deletes a file or an array of files
+ * @param {Array} files array of files that shoudld be deleted
+ * @param {errorCallback} callback Callback function with an error object
+ */
+module.exports.deleteTempFiles = function (files, callback) {
+  var rmFiles = []
+  if (typeof files === 'string') {
+    rmFiles.push(files)
+  } else if (Array.isArray(files)) {
+    rmFiles = files
+  } else {
+    return callback(new Error('Unexcepted files parameter type; only string or array supported'))
+  }
+  var deleteSeries = function (list, finalCallback) {
+    if (list.length) {
+      var file = list.shift()
+      var myCallback = function (err) {
+        if (err && err.code === 'ENOENT') {
+          // file doens't exist
+          return deleteSeries(list, finalCallback)
+        } else if (err) {
+          // other errors, e.g. maybe we don't have enough permission
+          return finalCallback(err)
+        } else {
+          return deleteSeries(list, finalCallback)
+        }
+      }
+      if (file && typeof file === 'string') {
+        fs.unlink(file, myCallback)
+      } else {
+        return deleteSeries(list, finalCallback)
+      }
+    } else {
+      return finalCallback(null) // no errors
+    }
+  }
+  deleteSeries(rmFiles, callback)
+}
+/**
+ * Callback for return an error object.
+ * @callback errorCallback
+ * @param {Error} err - An Error Object or null
  */
 
diff --git a/lib/helper.js b/lib/helper.js index c53ef8f2..2cd84329 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -1,139 +1,139 @@ -'use strict' - -var pathlib = require('path') -var fs = require('fs') -var crypto = require('crypto') -const {tmpdir} = require('os') -var tempDir = process.env.PEMJS_TMPDIR || tmpdir() - -/** - * pem helper module - * - * @module helper - */ - -/** - * helper function to check is the string a number or not - * @param {String} str String that should be checked to be a number - */ -module.exports.isNumber = function (str) { - if (Array.isArray(str)) { - return false - } - /* - var bstr = str && str.toString() - str = str + '' - - return bstr - parseFloat(bstr) + 1 >= 0 && - !/^\s+|\s+$/g.test(str) && /^\d+$/g.test(str) && - !isNaN(str) && !isNaN(parseFloat(str)) - */ - return /^\d+$/g.test(str) -} - -/** - * helper function to check is the string a hexaceximal value - * @param {String} hex String that should be checked to be a hexaceximal - */ -module.exports.isHex = function isHex (hex) { - return /^(0x){0,1}([0-9A-F]{1,40}|[0-9A-F]{1,40})$/gi.test(hex) -} - -/** - * helper function to convert a string to a hexaceximal value - * @param {String} str String that should be converted to a hexaceximal - */ -module.exports.toHex = function toHex (str) { - var hex = '' - for (var i = 0; i < str.length; i++) { - hex += '' + str.charCodeAt(i).toString(16) - } - return hex -} - -// cipherPassword returns an array of supported ciphers. -/** - * list of supported ciphers - * @type {Array} - */ -module.exports.ciphers = ['aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea'] -var ciphers = module.exports.ciphers - -/** - * Creates a PasswordFile to hide the password form process infos via `ps auxf` etc. - * @param {Object} options object of cipher, password and passType, mustPass, {cipher:'aes128', password:'xxxx', passType:"in/out/word"}, if the object empty we do nothing - * @param {String} options.cipher cipher like 'aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea' - * @param {String} options.password password can be empty or at last 4 to 1023 chars - * @param {String} options.passType passType: can be in/out/word for passIN/passOUT/passWORD - * @param {Boolean} options.mustPass mustPass is used when you need to set the pass like as "-password pass:" most needed when empty password - * @param {Object} params params will be extended with the data that need for the openssl command. IS USED AS POINTER! - * @param {String} PasswordFileArray PasswordFileArray is an array of filePaths that later need to deleted ,after the openssl command. IS USED AS POINTER! - * @return {Boolean} result - */ -module.exports.createPasswordFile = function (options, params, PasswordFileArray) { - if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !(typeof options.password === 'string') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) { - return false - } - var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex')) - PasswordFileArray.push(PasswordFile) - options.password = options.password.trim() - if (options.password === '') { - options.mustPass = true - } - if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) { - params.push('-' + options.cipher) - } - params.push('-pass' + (params.indexOf('genpkey') === -1 ? options.passType : '')) - if (options.mustPass) { - params.push('pass:' + options.password) - } else { - fs.writeFileSync(PasswordFile, options.password) - params.push('file:' + PasswordFile) - } - return true -} - -/** - * Deletes a file or an array of files - * @param {Array} files array of files that shoudld be deleted - * @param {errorCallback} callback Callback function with an error object - */ -module.exports.deleteTempFiles = function (files, callback) { - var rmFiles = [] - if (typeof files === 'string') { - rmFiles.push(files) - } else if (Array.isArray(files)) { - rmFiles = files - } else { - return callback(new Error('Unexcepted files parameter type; only string or array supported')) - } - var deleteSeries = function (list, finalCallback) { - if (list.length) { - var file = list.shift() - var myCallback = function (err) { - if (err && err.code === 'ENOENT') { - // file doens't exist - return deleteSeries(list, finalCallback) - } else if (err) { - // other errors, e.g. maybe we don't have enough permission - return finalCallback(err) - } else { - return deleteSeries(list, finalCallback) - } - } - if (file && typeof file === 'string') { - fs.unlink(file, myCallback) - } else { - return deleteSeries(list, finalCallback) - } - } else { - return finalCallback(null) // no errors - } - } - deleteSeries(rmFiles, callback) -} -/** - * Callback for return an error object. - * @callback errorCallback - * @param {Error} err - An Error Object or null - */ +'use strict' + +var pathlib = require('path') +var fs = require('fs') +var crypto = require('crypto') +const {tmpdir} = require('os') +var tempDir = process.env.PEMJS_TMPDIR || tmpdir() + +/** + * pem helper module + * + * @module helper + */ + +/** + * helper function to check is the string a number or not + * @param {String} str String that should be checked to be a number + */ +module.exports.isNumber = function (str) { + if (Array.isArray(str)) { + return false + } + /* + var bstr = str && str.toString() + str = str + '' + + return bstr - parseFloat(bstr) + 1 >= 0 && + !/^\s+|\s+$/g.test(str) && /^\d+$/g.test(str) && + !isNaN(str) && !isNaN(parseFloat(str)) + */ + return /^\d+$/g.test(str) +} + +/** + * helper function to check is the string a hexaceximal value + * @param {String} hex String that should be checked to be a hexaceximal + */ +module.exports.isHex = function isHex (hex) { + return /^(0x){0,1}([0-9A-F]{1,40}|[0-9A-F]{1,40})$/gi.test(hex) +} + +/** + * helper function to convert a string to a hexaceximal value + * @param {String} str String that should be converted to a hexaceximal + */ +module.exports.toHex = function toHex (str) { + var hex = '' + for (var i = 0; i < str.length; i++) { + hex += '' + str.charCodeAt(i).toString(16) + } + return hex +} + +// cipherPassword returns an array of supported ciphers. +/** + * list of supported ciphers + * @type {Array} + */ +module.exports.ciphers = ['aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea'] +var ciphers = module.exports.ciphers + +/** + * Creates a PasswordFile to hide the password form process infos via `ps auxf` etc. + * @param {Object} options object of cipher, password and passType, mustPass, {cipher:'aes128', password:'xxxx', passType:"in/out/word"}, if the object empty we do nothing + * @param {String} options.cipher cipher like 'aes128', 'aes192', 'aes256', 'camellia128', 'camellia192', 'camellia256', 'des', 'des3', 'idea' + * @param {String} options.password password can be empty or at last 4 to 1023 chars + * @param {String} options.passType passType: can be in/out/word for passIN/passOUT/passWORD + * @param {Boolean} options.mustPass mustPass is used when you need to set the pass like as "-password pass:" most needed when empty password + * @param {Object} params params will be extended with the data that need for the openssl command. IS USED AS POINTER! + * @param {String} PasswordFileArray PasswordFileArray is an array of filePaths that later need to deleted ,after the openssl command. IS USED AS POINTER! + * @return {Boolean} result + */ +module.exports.createPasswordFile = function (options, params, PasswordFileArray) { + if (!options || !Object.prototype.hasOwnProperty.call(options, 'password') || !(typeof options.password === 'string') || !Object.prototype.hasOwnProperty.call(options, 'passType') || !/^(word|in|out)$/.test(options.passType)) { + return false + } + var PasswordFile = pathlib.join(tempDir, crypto.randomBytes(20).toString('hex')) + PasswordFileArray.push(PasswordFile) + options.password = options.password.trim() + if (options.password === '') { + options.mustPass = true + } + if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) { + params.push('-' + options.cipher) + } + params.push('-pass' + (params.indexOf('genpkey') === -1 ? options.passType : '')) + if (options.mustPass) { + params.push('pass:' + options.password) + } else { + fs.writeFileSync(PasswordFile, options.password) + params.push('file:' + PasswordFile) + } + return true +} + +/** + * Deletes a file or an array of files + * @param {Array} files array of files that shoudld be deleted + * @param {errorCallback} callback Callback function with an error object + */ +module.exports.deleteTempFiles = function (files, callback) { + var rmFiles = [] + if (typeof files === 'string') { + rmFiles.push(files) + } else if (Array.isArray(files)) { + rmFiles = files + } else { + return callback(new Error('Unexcepted files parameter type; only string or array supported')) + } + var deleteSeries = function (list, finalCallback) { + if (list.length) { + var file = list.shift() + var myCallback = function (err) { + if (err && err.code === 'ENOENT') { + // file doens't exist + return deleteSeries(list, finalCallback) + } else if (err) { + // other errors, e.g. maybe we don't have enough permission + return finalCallback(err) + } else { + return deleteSeries(list, finalCallback) + } + } + if (file && typeof file === 'string') { + fs.unlink(file, myCallback) + } else { + return deleteSeries(list, finalCallback) + } + } else { + return finalCallback(null) // no errors + } + } + deleteSeries(rmFiles, callback) +} +/** + * Callback for return an error object. + * @callback errorCallback + * @param {Error} err - An Error Object or null + */ From a0d717e7db57fa7114112fc7337bd3779171a502 Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Fri, 10 Apr 2026 15:31:19 +0530 Subject: [PATCH 04/10] Fix matching empty string at the end of any `prime` value --- test/pem.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pem.spec.js b/test/pem.spec.js index 607ba2c2..95b84cc5 100644 --- a/test/pem.spec.js +++ b/test/pem.spec.js @@ -1305,7 +1305,7 @@ describe('General Tests', function () { expect(size).to.equal(fipsEnabled ? 2048 : 1024) expect(prime).to.be.a('string') if (fipsEnabled) { - expect(/([0-9a-f][0-9a-f]:)*$/g.test(prime)).to.be.true() + expect(/([0-9a-f][0-9a-f]:)+$/g.test(prime)).to.be.true() } else { expect(/([0-9a-f][0-9a-f]:)+[0-9a-f][0-9a-f]$/g.test(prime)).to.be.true() } From 69e1919a3e0d7d2f12da86ea6bf3fc051d6efffb Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Fri, 10 Apr 2026 15:47:04 +0530 Subject: [PATCH 05/10] Revert "Fix matching empty string at the end of any `prime` value" This reverts commit a0d717e7db57fa7114112fc7337bd3779171a502. --- test/pem.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/pem.spec.js b/test/pem.spec.js index 95b84cc5..607ba2c2 100644 --- a/test/pem.spec.js +++ b/test/pem.spec.js @@ -1305,7 +1305,7 @@ describe('General Tests', function () { expect(size).to.equal(fipsEnabled ? 2048 : 1024) expect(prime).to.be.a('string') if (fipsEnabled) { - expect(/([0-9a-f][0-9a-f]:)+$/g.test(prime)).to.be.true() + expect(/([0-9a-f][0-9a-f]:)*$/g.test(prime)).to.be.true() } else { expect(/([0-9a-f][0-9a-f]:)+[0-9a-f][0-9a-f]$/g.test(prime)).to.be.true() } From dc7977b73823d8b2a889fb1e7c0103cdb09409ec Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Mon, 13 Apr 2026 17:51:02 +0530 Subject: [PATCH 06/10] Use `openssl asn1parse` to get the prime --- lib/pem.js | 41 +++++++++++++++++++++++++++++------------ test/pem.spec.js | 6 +----- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/lib/pem.js b/lib/pem.js index a1ce5738..b7decf3d 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -879,22 +879,39 @@ function getDhparamInfo(dh, callback) { result.size = Number(match[1]) } - var prime = '' - stdout.split('\n').forEach(function (line) { - if (/\s+([0-9a-f][0-9a-f]:)+[0-9a-f]?[0-9a-f]?/g.test(line)) { - prime += line.trim() - } - }) + match = stdout.match(/GROUP: \((\d+) bit\)/) - if (prime) { - result.prime = prime + if (match) { + result.group = match[1] } - if (!match && !prime) { - return callback(new Error('No DH info found')) - } + params = [ + 'asn1parse', + '-in', + '--TMPFILE--', + '-item', + 'DHparams' + ] - return callback(null, result) + openssl.spawnWrapper(params, dh, function (err, code, stdout, stderr) { + if (err) { + return callback(err) + } else if (stderr) { + return callback(stderr) + } + + match = stdout.match(/p: ([0-9A-F]+)/i) + + if (match) { + result.prime = match[1].trim().toLowerCase().replace(new RegExp(`(.{2})(?!$)`, 'g'), `$&:`) + } + + if (!result.size && !result.prime) { + return callback(new Error('No DH info found')) + } + + return callback(null, result) + }) }) } diff --git a/test/pem.spec.js b/test/pem.spec.js index 607ba2c2..d2f9092c 100644 --- a/test/pem.spec.js +++ b/test/pem.spec.js @@ -1304,11 +1304,7 @@ describe('General Tests', function () { expect(size).to.be.a('number') expect(size).to.equal(fipsEnabled ? 2048 : 1024) expect(prime).to.be.a('string') - if (fipsEnabled) { - expect(/([0-9a-f][0-9a-f]:)*$/g.test(prime)).to.be.true() - } else { - expect(/([0-9a-f][0-9a-f]:)+[0-9a-f][0-9a-f]$/g.test(prime)).to.be.true() - } + expect(/([0-9a-f][0-9a-f]:)+[0-9a-f][0-9a-f]$/g.test(prime)).to.be.true() hlp.checkTmpEmpty() done() }) From 4d8c298d7864e5386c92b759878416b5308d4cb8 Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Mon, 13 Apr 2026 17:58:06 +0530 Subject: [PATCH 07/10] Replace low-level commands with high-level commands --- lib/pem.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/pem.js b/lib/pem.js index b7decf3d..2aecf90b 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -204,10 +204,14 @@ function createDhparam(keyBitsize, callback) { keyBitsize = Number(keyBitsize) || (getFips() ? 2048 : 512) - var params = ['dhparam', + var params = ['genpkey', + '-genparam', + '-algorithm', + 'DH', '-outform', 'PEM', - keyBitsize + '-pkeyopt', + `dh_paramgen_prime_len:${keyBitsize}` ] openssl.exec(params, 'DH PARAMETERS', function (error, dhparam) { @@ -793,17 +797,26 @@ function getModulus(certificate, password, hash, callback) { if (certificate.match(/BEGIN(\sNEW)? CERTIFICATE REQUEST/)) { type = 'req' } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/) || certificate.match(/BEGIN ENCRYPTED PRIVATE KEY/)) { - type = 'rsa' + type = 'pkey' } else { type = 'x509' } let params = [ type, '-noout', - '-modulus', '-in', '--TMPFILE--' ] + + switch (params[0]) { + case 'pkey': + params.push('-text_pub') + break + default: + params.push('-modulus') + break + } + let delTempPWFiles = [] if (password) { helper.createPasswordFile({cipher: '', password: password, passType: 'in'}, params, delTempPWFiles) @@ -814,8 +827,17 @@ function getModulus(certificate, password, hash, callback) { if (err) { return callback(err) } - var match = stdout.match(/Modulus=([0-9a-fA-F]+)$/m) + var match = undefined + switch (params[0]) { + case 'pkey': + match = stdout.match(/Modulus:\s+([\s\S]+?)(?=\n[a-zA-Z0-9]+:|$)/i); + break + default: + match = stdout.match(/Modulus=([0-9a-fA-F]+)$/m) + break + } if (match) { + match[1] = match[1].replace(/[\s:]+/g, '').replace(/^0+/, '').toUpperCase() if (hash === 'md5') { return callback(null, { modulus: hash_md5(match[1]) @@ -859,7 +881,7 @@ function getDhparamInfo(dh, callback) { dh = (Buffer.isBuffer(dh) && dh.toString()) || dh var params = [ - 'dhparam', + 'pkeyparam', '-text', '-in', '--TMPFILE--' From ce96d79a60c879a3ac7b94dfca1fed60d1289955 Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Mon, 13 Apr 2026 22:36:23 +0530 Subject: [PATCH 08/10] Replace `openssl ecparam` with `openssl genpkey` and rework key conversion to traditional format --- lib/openssl.js | 2 +- lib/pem.js | 202 ++++++++++++++++++++++++++++++----------------- test/pem.spec.js | 4 +- 3 files changed, 134 insertions(+), 74 deletions(-) diff --git a/lib/openssl.js b/lib/openssl.js index c819cad3..f6c33153 100644 --- a/lib/openssl.js +++ b/lib/openssl.js @@ -77,7 +77,7 @@ function exec(params, searchStr, tmpfiles, callback) { } // To get the full EC key with parameters and private key - if (searchStr === 'EC PARAMETERS') { + if (searchStr === 'EC PARAMETERS' && params[0] === 'ecparam') { searchStr = 'EC PRIVATE KEY' } diff --git a/lib/pem.js b/lib/pem.js index 2aecf90b..6184bc3b 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -55,6 +55,83 @@ var ENCRYPTED_KEY_END = '-----END ENCRYPTED PRIVATE KEY-----' var CERT_START = '-----BEGIN CERTIFICATE-----' var CERT_END = '-----END CERTIFICATE-----' +function convertKeyToTraditional(key, searchString, options, callback) { + if (!callback && typeof options === 'function') { + callback = options + options = {} + } + + if (!callback) { + return new Promise(function (resolve, reject) { + convertKeyToTraditional(key, searchString, options, function (err, result) { + if (err) { + return reject(err) + } + resolve(result) + }) + }) + } + + function done(err) { + if (err) { + return callback(err) + } + return callback(null, { + key: key + }) + } + if (key && searchString) { + if (!getFips() || !options || !options.cipher || (Number(helper.ciphers.indexOf(options.cipher)) === -1)) { + var params = ['pkey', '-traditional', '-in', '--TMPFILE--'] + + var delTempPWFiles = [] + if (options && options.cipher && (Number(helper.ciphers.indexOf(options.cipher)) !== -1) && options.password) { + debug('helper.createPasswordFile', { + cipher: '', + password: options.password, + passType: 'in' + }) + helper.createPasswordFile({ + cipher: '', + password: options.password, + passType: 'in' + }, params, delTempPWFiles) + + debug('helper.createPasswordFile', { + cipher: options.cipher, + password: options.password, + passType: 'out' + }) + helper.createPasswordFile({ + cipher: options.cipher, + password: options.password, + passType: 'out' + }, params, delTempPWFiles) + } + + debug('version', openssl.get('openSslVersion')) + + openssl.exec(params, searchString, [key], function (sslErr, traditional_key) { + + helper.deleteTempFiles(delTempPWFiles, function (fsErr) { + debug('convertKeyToTraditional', { + sslErr: sslErr, + fsErr: fsErr, + key: traditional_key, + keyLength: traditional_key && traditional_key.length + }) + key = traditional_key + done(sslErr || fsErr) + }) + }) + } else { + done() + } + } else { + done(new Error('No key or search string provided for conversion')) + } +} + /** * Creates a private key * @@ -121,59 +198,20 @@ function createPrivateKey(keyBitsize, options, callback) { }) } - if (!sslErr && key && openssl.get('Vendor') === 'OPENSSL' && openssl.get('VendorVersionMajor') >= 3 && !getFips()) { - var traditional_params = ['pkey', '-traditional', '-in', '--TMPFILE--'] - - if (options && options.cipher && (Number(helper.ciphers.indexOf(options.cipher)) !== -1) && options.password) { - debug('helper.createPasswordFile', { - cipher: '', - password: options.password, - passType: 'in' - }) - helper.createPasswordFile({ - cipher: '', - password: options.password, - passType: 'in' - }, traditional_params, delTempPWFiles) - - debug('helper.createPasswordFile', { - cipher: options.cipher, - password: options.password, - passType: 'out' - }) - helper.createPasswordFile({ - cipher: options.cipher, - password: options.password, - passType: 'out' - }, traditional_params, delTempPWFiles) - } - - debug('version', openssl.get('openSslVersion')) - - openssl.exec(traditional_params, '(RSA |ENCRYPTED |)PRIVATE KEY', [key], function (traditional_sslErr, traditional_key) { - - helper.deleteTempFiles(delTempPWFiles, function (traditional_fsErr) { - debug('createPrivateKey', { - sslErr: traditional_sslErr, - fsErr: traditional_fsErr, - key: traditional_key, - keyLength: traditional_key && traditional_key.length - }) - key = traditional_key - done(traditional_sslErr || traditional_fsErr) - }) + helper.deleteTempFiles(delTempPWFiles, function (fsErr) { + debug('createPrivateKey', { + sslErr: sslErr, + fsErr: fsErr, + key: key, + keyLength: key && key.length }) - } else { - helper.deleteTempFiles(delTempPWFiles, function (fsErr) { - debug('createPrivateKey', { - sslErr: sslErr, - fsErr: fsErr, - key: key, - keyLength: key && key.length - }) - done(sslErr || fsErr) + convertKeyToTraditional(key, '(RSA |ENCRYPTED |)PRIVATE KEY', options, function (convertErr, keyData) { + if (!convertErr) { + key = keyData.key + } + done(sslErr || fsErr || convertErr) }) - } + }) }) } @@ -260,27 +298,56 @@ function createEcparam(keyName, paramEnc, noOut, callback) { paramEnc = paramEnc || 'explicit' noOut = noOut || false - var params = ['ecparam', - '-name', - keyName, - '-genkey', - '-param_enc', - paramEnc + var params = ['genpkey', + '-genparam', + '-algorithm', + 'EC', + '-pkeyopt', + `ec_paramgen_curve:${keyName}`, + '-pkeyopt', + `ec_param_enc:${paramEnc}` ] var searchString = 'EC PARAMETERS' if (noOut) { - params.push('-noout') - searchString = 'EC PRIVATE KEY' + params = params.filter(param => param !== '-genparam'); + searchString = '(EC |)PRIVATE KEY' } openssl.exec(params, searchString, function (error, ecparam) { if (error) { return callback(error) } - return callback(null, { - ecparam: ecparam - }) + if (noOut) { + convertKeyToTraditional(ecparam, searchString, function (error, keyData) { + if (error) { + return callback(error) + } + return callback(null, { + ecparam: keyData.key + }) + }) + } + else { + params = ['genpkey', + '-paramfile', + '--TMPFILE--' + ] + searchString = '(EC |)PRIVATE KEY' + openssl.exec(params, searchString, [ecparam], function (error, eckey) { + if (error) { + return callback(error) + } + convertKeyToTraditional(eckey, searchString, function (error, keyData) { + if (error) { + return callback(error) + } + return callback(null, { + ecparam: ecparam + '\n' + keyData.key + }) + }) + }) + } }) } @@ -1155,20 +1222,13 @@ function readPkcs12(bufferOrPath, options, callback) { debug("readPkcs12.execBinary - PRIVATE KEY - ?: ", keybundle.key) if (keybundle.key) { - var args = ['pkey']; - if (openssl.get('Vendor') === "OPENSSL" && openssl.get('VendorVersionMajor') >= 3 && !getFips()) { - args.push('-traditional') - } - args.push('-in'); - args.push('--TMPFILE--'); - // convert to RSA key - return openssl.exec(args, '(RSA |)PRIVATE KEY', [keybundle.key], function (err, key) { + return convertKeyToTraditional(keybundle.key, '(RSA |)PRIVATE KEY', function (err, key) { if (err) { debug("readPkcs12.execBinary - PRIVATE KEY convert - error: ", err) } //debug("readPkcs12.execBinary - PRIVATE KEY", key) - keybundle.key = key + keybundle.key = key.key return callback(err, keybundle) }) diff --git a/test/pem.spec.js b/test/pem.spec.js index d2f9092c..82bec5ca 100644 --- a/test/pem.spec.js +++ b/test/pem.spec.js @@ -797,7 +797,7 @@ describe('General Tests', function () { context('pkcs12 -export -out "$pfx" -inkey "$key" -in "$cert" -certfile "$ca_bundle" -passout "pass:"', function () { it('verify right order of chains; read PKCS12', function (done) { let pkcs12_5_file_pfx = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_keyStore' + (fipsEnabled ? '' : '_legacy') + '.p12') - let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA' + (fipsEnabled ? '' : '_traditional') + '.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA_traditional.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_4_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_4_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_5_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let geotrust_primary_ca_cert = fs.readFileSync('./test/fixtures/GeoTrust_Primary_CA.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() @@ -828,7 +828,7 @@ describe('General Tests', function () { context('pkcs12 -export -out "pfx" -inkey "$key" -in "$cert + $ca_bundle" -passout "pass:"', function () { it('verify right order of chains; read PKCS12', function (done) { let pkcs12_5_file_pfx = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_keyStore2' + (fipsEnabled ? '' : '_legacy') + '.p12') - let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA' + (fipsEnabled ? '' : '_traditional') + '.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() + let pkcs12_5_file_key_rsa = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_key_RSA_traditional.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_4_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_4_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let pkcs12_5_file_cert = fs.readFileSync('./test/fixtures/rsa_pkcs12_5_cert.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() let geotrust_primary_ca_cert = fs.readFileSync('./test/fixtures/GeoTrust_Primary_CA.pem').toString().replace(/(?:\r\n|\r|\n)/g, "\n").trim() From 7d29f693fb634a3943a021d0bab96c23a21fae9f Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Tue, 14 Apr 2026 09:32:37 +0530 Subject: [PATCH 09/10] Adapt to both OpenSSL and LibreSSL --- lib/pem.js | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/pem.js b/lib/pem.js index 6184bc3b..47d6f114 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -55,7 +55,7 @@ var ENCRYPTED_KEY_END = '-----END ENCRYPTED PRIVATE KEY-----' var CERT_START = '-----BEGIN CERTIFICATE-----' var CERT_END = '-----END CERTIFICATE-----' -function convertKeyToTraditional(key, searchString, options, callback) { +function convertKeyToTraditional(key, algorithm, searchString, options, callback) { if (!callback && typeof options === 'function') { callback = options options = {} @@ -63,7 +63,7 @@ function convertKeyToTraditional(key, searchString, options, callback) { if (!callback) { return new Promise(function (resolve, reject) { - convertKeyToTraditional(key, searchString, options, function (err, result) { + convertKeyToTraditional(key, algorithm, searchString, options, function (err, result) { if (err) { return reject(err) } @@ -81,9 +81,14 @@ function convertKeyToTraditional(key, searchString, options, callback) { }) } if (key && searchString) { - if (!getFips() || !options || !options.cipher || (Number(helper.ciphers.indexOf(options.cipher)) === -1)) { - var params = ['pkey', '-traditional', '-in', '--TMPFILE--'] + if (!(getFips() && options && options.cipher && (Number(helper.ciphers.indexOf(options.cipher)) !== -1))) { + var params = ['pkey', '-traditional'] + if (openssl.get('Vendor') !== "OPENSSL") { + params = [algorithm] + } + params.push('-in') + params.push('--TMPFILE--') var delTempPWFiles = [] if (options && options.cipher && (Number(helper.ciphers.indexOf(options.cipher)) !== -1) && options.password) { debug('helper.createPasswordFile', { @@ -205,7 +210,7 @@ function createPrivateKey(keyBitsize, options, callback) { key: key, keyLength: key && key.length }) - convertKeyToTraditional(key, '(RSA |ENCRYPTED |)PRIVATE KEY', options, function (convertErr, keyData) { + convertKeyToTraditional(key, 'rsa', '(RSA |ENCRYPTED |)PRIVATE KEY', options, function (convertErr, keyData) { if (!convertErr) { key = keyData.key } @@ -319,7 +324,7 @@ function createEcparam(keyName, paramEnc, noOut, callback) { return callback(error) } if (noOut) { - convertKeyToTraditional(ecparam, searchString, function (error, keyData) { + convertKeyToTraditional(ecparam, 'ec', searchString, function (error, keyData) { if (error) { return callback(error) } @@ -338,7 +343,7 @@ function createEcparam(keyName, paramEnc, noOut, callback) { if (error) { return callback(error) } - convertKeyToTraditional(eckey, searchString, function (error, keyData) { + convertKeyToTraditional(eckey, 'ec', searchString, function (error, keyData) { if (error) { return callback(error) } @@ -977,9 +982,7 @@ function getDhparamInfo(dh, callback) { params = [ 'asn1parse', '-in', - '--TMPFILE--', - '-item', - 'DHparams' + '--TMPFILE--' ] openssl.spawnWrapper(params, dh, function (err, code, stdout, stderr) { @@ -989,7 +992,7 @@ function getDhparamInfo(dh, callback) { return callback(stderr) } - match = stdout.match(/p: ([0-9A-F]+)/i) + match = stdout.match(/INTEGER\s+:([0-9A-F]+)/i) if (match) { result.prime = match[1].trim().toLowerCase().replace(new RegExp(`(.{2})(?!$)`, 'g'), `$&:`) @@ -1223,7 +1226,7 @@ function readPkcs12(bufferOrPath, options, callback) { debug("readPkcs12.execBinary - PRIVATE KEY - ?: ", keybundle.key) if (keybundle.key) { // convert to RSA key - return convertKeyToTraditional(keybundle.key, '(RSA |)PRIVATE KEY', function (err, key) { + return convertKeyToTraditional(keybundle.key, 'rsa', '(RSA |)PRIVATE KEY', function (err, key) { if (err) { debug("readPkcs12.execBinary - PRIVATE KEY convert - error: ", err) } @@ -1302,7 +1305,7 @@ function checkCertificate(certificate, passphrase, callback) { if (certificate.match(/BEGIN(\sNEW)? CERTIFICATE REQUEST/)) { params = ['req', '-text', '-noout', '-verify', '-in', '--TMPFILE--'] } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/) || certificate.match(/BEGIN ENCRYPTED PRIVATE KEY/)) { - params = ['pkey', '-noout', '-check', '-in', '--TMPFILE--'] + params = [(openssl.get('Vendor') === "OPENSSL") ? 'pkey' : 'rsa', '-noout', '-check', '-in', '--TMPFILE--'] } else { params = ['x509', '-text', '-noout', '-in', '--TMPFILE--'] } @@ -1319,6 +1322,9 @@ function checkCertificate(certificate, passphrase, callback) { case 'pkey': result = /^Key is valid$/i.test(stdout) break + case 'rsa': + result = /^Rsa key ok$/i.test(stdout) + break default: result = /Signature Algorithm/im.test(stdout) break @@ -1701,7 +1707,7 @@ function fetchCertificateData(certData, callback) { } // SAN - if ((san = certData.match(/X509v3 Subject Alternative Name: \r?\n([^\r\n]*)\r?\n/)) && san.length > 1) { + if ((san = certData.match(/X509v3 Subject Alternative Name:\s*\r?\n([^\r\n]*)\r?\n/)) && san.length > 1) { san = san[1].trim() + '\n' certValues.san = {} From ad90eb75883bdd8c7efb9cc58776e0d8c73d7954 Mon Sep 17 00:00:00 2001 From: Nikhil Sairam Reddy Sannapareddy Date: Fri, 17 Apr 2026 11:09:26 +0530 Subject: [PATCH 10/10] Minor fixes --- lib/helper.js | 2 +- lib/pem.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/helper.js b/lib/helper.js index 2cd84329..afb85235 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -83,7 +83,7 @@ module.exports.createPasswordFile = function (options, params, PasswordFileArray if (options.cipher && (ciphers.indexOf(options.cipher) !== -1)) { params.push('-' + options.cipher) } - params.push('-pass' + (params.indexOf('genpkey') === -1 ? options.passType : '')) + params.push('-pass' + (params[0] !== 'genpkey' ? options.passType : '')) if (options.mustPass) { params.push('pass:' + options.password) } else { diff --git a/lib/pem.js b/lib/pem.js index 47d6f114..5f5ca40e 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -1231,7 +1231,9 @@ function readPkcs12(bufferOrPath, options, callback) { debug("readPkcs12.execBinary - PRIVATE KEY convert - error: ", err) } //debug("readPkcs12.execBinary - PRIVATE KEY", key) - keybundle.key = key.key + else if (key && key.key) { + keybundle.key = key.key + } return callback(err, keybundle) })