'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
*/
'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
-
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..afb85235 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')
+'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') || !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
+
+/**
+ * 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[0] !== 'genpkey' ? 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/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 66c103e3..5f5ca40e 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')
@@ -55,6 +55,88 @@ var ENCRYPTED_KEY_END = '-----END ENCRYPTED PRIVATE KEY-----'
var CERT_START = '-----BEGIN CERTIFICATE-----'
var CERT_END = '-----END CERTIFICATE-----'
+function convertKeyToTraditional(key, algorithm, searchString, options, callback) {
+ if (!callback && typeof options === 'function') {
+ callback = options
+ options = {}
+ }
+
+ if (!callback) {
+ return new Promise(function (resolve, reject) {
+ convertKeyToTraditional(key, algorithm, 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']
+ 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', {
+ 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
*
@@ -89,11 +171,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 +188,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'))
@@ -131,7 +210,12 @@ function createPrivateKey(keyBitsize, options, callback) {
key: key,
keyLength: key && key.length
})
- done(sslErr || fsErr)
+ convertKeyToTraditional(key, 'rsa', '(RSA |ENCRYPTED |)PRIVATE KEY', options, function (convertErr, keyData) {
+ if (!convertErr) {
+ key = keyData.key
+ }
+ done(sslErr || fsErr || convertErr)
+ })
})
})
}
@@ -140,7 +224,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,12 +245,16 @@ function createDhparam(keyBitsize, callback) {
})
}
- keyBitsize = Number(keyBitsize) || 512
+ 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) {
@@ -182,7 +270,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,31 +299,60 @@ function createEcparam(keyName, paramEnc, noOut, callback) {
})
}
- keyName = keyName || 'secp256k1'
+ keyName = keyName || (getFips() ? 'prime256v1' : 'secp256k1')
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, 'ec', 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, 'ec', searchString, function (error, keyData) {
+ if (error) {
+ return callback(error)
+ }
+ return callback(null, {
+ ecparam: ecparam + '\n' + keyData.key
+ })
+ })
+ })
+ }
})
}
@@ -356,6 +473,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 +756,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,18 +868,27 @@ 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/)) {
- type = 'rsa'
+ } else if (certificate.match(/BEGIN RSA PRIVATE KEY/) || certificate.match(/BEGIN PRIVATE KEY/) || certificate.match(/BEGIN ENCRYPTED PRIVATE KEY/)) {
+ 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)
@@ -766,8 +899,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])
@@ -811,7 +953,7 @@ function getDhparamInfo(dh, callback) {
dh = (Buffer.isBuffer(dh) && dh.toString()) || dh
var params = [
- 'dhparam',
+ 'pkeyparam',
'-text',
'-in',
'--TMPFILE--'
@@ -831,22 +973,37 @@ 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--'
+ ]
+
+ openssl.spawnWrapper(params, dh, function (err, code, stdout, stderr) {
+ if (err) {
+ return callback(err)
+ } else if (stderr) {
+ return callback(stderr)
+ }
+
+ match = stdout.match(/INTEGER\s+:([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)
+ return callback(null, result)
+ })
})
}
@@ -972,6 +1129,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 +1190,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,20 +1225,15 @@ 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) {
- 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', '(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
+ else if (key && key.key) {
+ keybundle.key = key.key
+ }
return callback(err, keybundle)
})
@@ -1145,8 +1306,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 = [(openssl.get('Vendor') === "OPENSSL") ? 'pkey' : 'rsa', '-noout', '-check', '-in', '--TMPFILE--']
} else {
params = ['x509', '-text', '-noout', '-in', '--TMPFILE--']
}
@@ -1160,6 +1321,9 @@ function checkCertificate(certificate, passphrase, callback) {
stdout = stdout && stdout.trim()
var result
switch (params[0]) {
+ case 'pkey':
+ result = /^Key is valid$/i.test(stdout)
+ break
case 'rsa':
result = /^Rsa key ok$/i.test(stdout)
break
@@ -1222,7 +1386,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');
}
@@ -1545,7 +1709,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 = {}
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 0247dea0..795e9783 100644
Binary files a/test/fixtures/idsrv3test.pfx and b/test/fixtures/idsrv3test.pfx differ
diff --git a/test/fixtures/idsrv3test_legacy.pfx b/test/fixtures/idsrv3test_legacy.pfx
new file mode 100644
index 00000000..0247dea0
Binary files /dev/null and b/test/fixtures/idsrv3test_legacy.pfx differ
diff --git a/test/fixtures/rsa_pkcs12_5_keyStore.p12 b/test/fixtures/rsa_pkcs12_5_keyStore.p12
index 5c0c512f..8304b9ad 100644
Binary files a/test/fixtures/rsa_pkcs12_5_keyStore.p12 and b/test/fixtures/rsa_pkcs12_5_keyStore.p12 differ
diff --git a/test/fixtures/rsa_pkcs12_5_keyStore2.p12 b/test/fixtures/rsa_pkcs12_5_keyStore2.p12
index 85566ad7..432072d1 100644
Binary files a/test/fixtures/rsa_pkcs12_5_keyStore2.p12 and b/test/fixtures/rsa_pkcs12_5_keyStore2.p12 differ
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 00000000..85566ad7
Binary files /dev/null and b/test/fixtures/rsa_pkcs12_5_keyStore2_legacy.p12 differ
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 00000000..5c0c512f
Binary files /dev/null and b/test/fixtures/rsa_pkcs12_5_keyStore_legacy.p12 differ
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-----
+MIIJJwIBAAKCAgEA3D7OhXzz4Hza172Fi8EWhoe4kymsniyE87ZyCCLrQOomzP8r
+KNIeGpRJgPwXWqR/s6IqXf9xHNfko5WJma3pMVSt1FFmSEp+w1F83+sLhijbJoPj
+RxzdTO/ryCGf0NvmwXIagqBMdTthW3nvTmT26zm+i88zm0tIQx+JrZMKZxgkv6Q9
+4xlba36HaA1c8EWvXYF+yzagv+Aq7Xta4hN0zMgexQSW7AihV0CbCYFknYs6HvkX
+QqYKLTN5JJyIpLKTreAZhUfh2C+vO0jzxBaZuFVqRt9Xferzt+Up4Ms0Kdk04Rai
+YRgay7Led3fV5soN39RQP3+nrUMozSSYc4p1PTrCGzaGnvum4pCmo5G+oqcvgVbg
+VdMnujwH5nWZvpXbScfxZICrObyKhiHblFmyaNybTHeRIWcqSPv6JlGJEbGN2usr
+d5OXNHJberYRaAxZ2OrkRwKEfRJAdujiVi/8meFGRiIelvjsvVpX8aNEkM3bh2GB
+2UNYVTG9PeZdnfA4YSSTf0p9IzVYVi2m4kh0cpT9k+cpRdVTYF/bEd9lDtejfIOc
+dmOZXLwL0uZmnVapJsg1WuklKElloK/zKEPyOTNlt0ncnnIfiVl/L03SGpWBLQmI
+eB1CoX/dt2ea820UfSjU9ynNffEiOYKKrDyu8u7qNujKAC47Mho2XqvPbysCAwEA
+AQKCAgBNEpWG1SEqz8ZtdN8E9v8A+QG4Tf8gIwgrmQ7ylfWpc8c8OZdK46yxNG88
+eftaNvKRVBBrcHaO12YlcLEEXH2cS7vA7vNSHO+bPirq2P/hZO673a9tNUakI9lo
+4YthtXJdA6cPSzU2WR9KubLqxh46Vqy9lDbFA2U4SBMP8MLVLPe/MKSPklIRneeY
+nASH+HrTx/ss9eLvAm1DScWWE6Tt/KH35BFEbAi51dvrSaKCFzSxng1rv1sUUkz0
+aOrQZ8WSNTf5EhyQYK97mZ3kYtxMS2ezgXjGka/UDJfJGJMaie4dTqRoQd0up1t+
+hysNZmvQhiXG8s8krLncgA/xbuRzcH843e+vVKH4vXLatLO9KxWVXJoIQrd9FgVY
+pmshPF5iXglScRfH6Bwe6niG2OzXnbTih+0AhrDSL3Q6enyU44q8mvfbmEzWRKGh
+z5mj/m4oWBzlOT6QcU0vJXeckX0som9LLjyjjyzcvTM65bbstePxtTlo+hHDuCrJ
+ugaBJ6m0ZIHBq6UlUMegCAgODwBwDr2uy9AeUJOhQ/O8DhT48qMtjO6FWmSbG5Ry
+5jG47IUwjpK03hVyYzrnKAtijGluoaNhivq9y7ASDyN+f6CoP/SwE3lrB1gVahTT
+mMkJShZPG3TccNRsHe3lV9P67LkvgRyIOzWenXgZo+04OdLMoQKCAQEA+FbxRy+g
+skC3RWU7wTzc5ui4uQS/Elz9qw6dwb12dfdPld1Mnv12ymXeEHYXepMqlqViPdof
+USUnz+krNyWJoCoOjAw8xJ2tx/Jn2sc5I3mSTLGoj1M7mZvzLyC+iCU473tjXIa8
+fn1bi1tjuELGSg65ljDv3d5mhpkC3fi7UgaeebXpnjlGqS1ZOQfVI6MZLJxlrxra
+vDSs4eClkoTNORjAJbBAxDdKIVbG0z/gA6Mug0bJZqLqoQuLvLFJFp6AtolK3rLI
+80Eib9hsnCawsAHE2XWgbgC+ScAsr8LSyWE54TElshZwA5jTjNePTkHCasqsM1f+
+zGQZf4ChGxHHeQKCAQEA4woDRwxehqTov/PTHPFJdYB9Ft2cXuCpcHa+HK2xhrN6
+ty7mcxQcM8GAAqsPVElotPRfMvSkaf3MFrgVcELPZQuoaM5LqXyABM4iOYeJZE8W
+kloHpLvaOE5ss4qbDx6MmBd8qbBkC+wF6x3F1Ncflgg8wiZ9+YEwtNjimDslkYyC
+ufpWUklXvMJAty6fOfQ1fv9nCqMfkKupm1i+7UqfhbcX5dvAuBMuk0zfqdC7PtFn
+pqgHIYxN26PiPV67Nr+VRPWSDe5rLfE/QAgUNk+5/dJG2te4cYnxp135p7I9ws2o
+7YlualUxk63AW0NpuKT/0nYDfVJ2VJI7z3n5leLuwwKCAQAtvKV3PNhVvAGE8F4O
++sycYmQS/0LJeQLnDCwV0HUOyNuJeFZyObA1GonJclZkptIDKLZtOczmvvcUHZdt
+8qXkL5q6RE60z22AE6745hQp6mv9YALxUpz5b3VcSqWMoX5Y7Nqh4da5XRENG2nE
+N9gZL5kShjTHIfyz8V5Lz1GAi+OH+u7pyxaudcGm9UBV7eXnB27azxFV9EWa3Cri
+Tz8UsvBAgLOM77nhZf/8TBlP0i/w0YqqMnsP6fZ0bBpP5iVCeQqm9Tp5Qpe7DZsD
+L0T/RXQhsL45RD3Hi3Mvc6wqlpN4W/rbT7KVlwHvQIwOF6Jc1LLeSeiNcCoaB3Ck
+caPRAoIBABMHgtDQq5eTeOKl2BsD6klL9LAW8QVOxUTk3vheYpPMtUtnRe99TwPT
+gxw2JDnHUVxhYx1NPf6YRCPfWASpxOJOQNZP/C1/fudoM5wozQ44RscLfrqC+D5h
+7GB8DJUO1W/mAA/k9e294Z0cSLmXMlGL7TPEsChaeK+fwhZKVtLFOSvHXLbW6OCs
+U2pHIRdlbZpwY72TgJDKopOfs5kF+Srm9rzQV23WRcAY4GJGWXthZ9OjH73jGZ+A
+M/U63GwxUJyQDKbYRel63/dI9hC7S/aHSmMLU61Ih5Wknck9ekm6nR8Ttsp4y4f6
+NzYvB0xvn/WO6Kn3YG2kOBkiuxWiCKsCggEAJutX8x8HxSqTf/LbPLBZgVXcuEPd
+spnNfiJl278eqIQBYFeeKuEYWWLQeLp0PeEFx3qg5d+lwu2Rw6YLVictMOChNcWn
+SOWZmOYVRFK6bYnx+vIwYv+Vaxt/ymdq6U1H+Ks1/xjbodWXCtOWM1IjjPafU6Ok
+sQhYF0Yyv/duti9WTTE90P9w/iL7Mfz+ZUYLTBcDuqL9rkV9mtoAC7oIbLGBZEMk
+LZiLcwRukS6w+y4Oyb2cSfammRJ8Y7+T5KCUGyfX3mG44eUXskLcp2PcaYIas5+h
+/P3zPOCp/vTK0xjr83Oo0JRdrmPcDtfs6UQo5430nXfLixM3jM/7BjiDLQ==
+-----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..82bec5ca 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_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_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,13 +1296,13 @@ 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()
hlp.checkTmpEmpty()
@@ -1296,7 +1325,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()