diff --git a/lib/helper.js b/lib/helper.js index 6181bc44..e9a2bf77 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -11,6 +11,45 @@ var tempDir = process.env.PEMJS_TMPDIR || osTmpdir() * @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 diff --git a/lib/openssl.js b/lib/openssl.js index 259166ad..bb48458b 100644 --- a/lib/openssl.js +++ b/lib/openssl.js @@ -153,7 +153,7 @@ function spawn (params, binary, callback) { if (--needed < 1) { finished = true if (code) { - if (code === 2 && stderr === '') { + if (code === 2 && (stderr === '' || /depth lookup: unable to/.test(stderr))) { return callback(null, code, stdout, stderr) } return callback(new Error('Invalid openssl exit code: ' + code + '\n% openssl ' + params.join(' ') + '\n' + stderr), code) diff --git a/lib/pem.js b/lib/pem.js index 7e42cb8b..6237c2f0 100644 --- a/lib/pem.js +++ b/lib/pem.js @@ -273,6 +273,7 @@ function createCSR (options, callback) { * @param {String} [options.serviceKey] Private key for signing the certificate, if not defined a new one is generated * @param {String} [options.serviceKeyPassword] Password of the service key * @param {Boolean} [options.selfSigned] If set to true and serviceKey is not defined, use clientKey for signing + * @param {String|Number} [options.serial] Set a serial max. 20 octets - only together with options.serviceCertificate * @param {String} [options.hash] Hash function to use (either md5 sha1 or sha256, defaults to sha256) * @param {String} [options.csr] CSR for the certificate, if not defined a new one is generated * @param {Number} [options.days] Certificate expire time in days @@ -335,14 +336,25 @@ function createCertificate (options, callback) { params.push('--TMPFILE--') if (options.serial) { params.push('-set_serial') - // set the serial to the max lenth of 20 octets () - // A certificate serial number is not decimal conforming. That is the - // bytes in a serial number do not necessarily map to a printable ASCII - // character. - // eg: 0x00 is a valid serial number and can not be represented in a - // human readable format (atleast one that can be directly mapped to - // the ACSII table). - params.push('0x' + ('0000000000000000000000000000000000000000' + options.serial.toString(16)).slice(-40)) + if (helper.isNumber(options.serial)) { + // set the serial to the max lenth of 20 octets () + // A certificate serial number is not decimal conforming. That is the + // bytes in a serial number do not necessarily map to a printable ASCII + // character. + // eg: 0x00 is a valid serial number and can not be represented in a + // human readable format (atleast one that can be directly mapped to + // the ACSII table). + params.push('0x' + ('0000000000000000000000000000000000000000' + options.serial.toString(16)).slice(-40)) + } else { + if (helper.isHex(options.serial)) { + if (options.serial.startsWith('0x')) { + options.serial = options.serial.substring(2, options.serial.length) + } + params.push('0x' + ('0000000000000000000000000000000000000000' + options.serial).slice(-40)) + } else { + params.push('0x' + ('0000000000000000000000000000000000000000' + helper.toHex(options.serial)).slice(-40)) + } + } } else { params.push('-CAcreateserial') } @@ -855,18 +867,21 @@ function checkPkcs12 (bufferOrPath, passphrase, callback) { /** * Verifies the signing chain of the passed certificate * @static - * @param {String} PEM encoded certificate - * @param {Array} List of CA certificates + * @param {String|Array} PEM encoded certificate include intermediate certificates + * @param {String|Array} List of CA certificates * @param {Function} callback Callback function with an error object and a boolean valid */ function verifySigningChain (certificate, ca, callback) { + if (!Array.isArray(certificate)) { + certificate = [certificate] + } if (!Array.isArray(ca)) { ca = [ca] } var files = [ ca.join('\n'), - certificate + certificate.join('\n') ] var params = ['verify', diff --git a/test/pem.helper.js b/test/pem.helper.js index 1985a300..806e5f3a 100644 --- a/test/pem.helper.js +++ b/test/pem.helper.js @@ -30,10 +30,10 @@ function checkError (error, expectError) { function checkEcparam (data, min, max) { expect(data).to.be.an('object').that.has.property('ecparam') expect(data.ecparam).to.be.a('string') - expect(/^\n*-----BEGIN EC PARAMETERS-----\n/.test(data.ecparam)).to.be.true() - expect(/\n-----END EC PARAMETERS-----\n/.test(data.ecparam)).to.be.true() - expect(/\n-----BEGIN EC PRIVATE KEY-----\n/.test(data.ecparam)).to.be.true() - expect(/\n-----END EC PRIVATE KEY-----\n*$/.test(data.ecparam)).to.be.true() + expect(/^\r?\n*-----BEGIN EC PARAMETERS-----\r?\n/.test(data.ecparam)).to.be.true() + expect(/\r?\n-----END EC PARAMETERS-----\r?\n/.test(data.ecparam)).to.be.true() + expect(/\r?\n-----BEGIN EC PRIVATE KEY-----\r?\n/.test(data.ecparam)).to.be.true() + expect(/\r?\n-----END EC PRIVATE KEY-----\r?\n*$/.test(data.ecparam)).to.be.true() var matchup = /-----BEGIN EC PRIVATE KEY-----[\s\S]+-----END EC PRIVATE KEY-----/.exec(data.ecparam) expect(matchup[0].trim().length).to.be.within(min + 1, max - 1) } @@ -41,17 +41,17 @@ function checkEcparam (data, min, max) { function checkDhparam (data, min, max) { expect(data).to.be.an('object').that.has.property('dhparam') expect(data.dhparam).to.be.a('string') - expect(/^\n*-----BEGIN DH PARAMETERS-----\n/.test(data.dhparam)).to.be.true() - expect(/\n-----END DH PARAMETERS-----\n*$/.test(data.dhparam)).to.be.true() + expect(/^\r?\n*-----BEGIN DH PARAMETERS-----\r?\n/.test(data.dhparam)).to.be.true() + expect(/\r?\n-----END DH PARAMETERS-----\r?\n*$/.test(data.dhparam)).to.be.true() expect(data.dhparam.trim().length).to.be.within(min + 1, max - 1) } function checkPrivateKey (data, min, max, encrypted) { expect(data).to.be.an('object').that.has.property('key') expect(data.key).to.be.a('string') - if (encrypted) { expect(/ENCRYPTED\n/.test(data.key)).to.be.true() } - expect(/^\n*-----BEGIN RSA PRIVATE KEY-----\n/.test(data.key)).to.be.true() - expect(/\n-----END RSA PRIVATE KEY-----\n*$/.test(data.key)).to.be.true() + if (encrypted) { expect(/ENCRYPTED\r?\n/.test(data.key)).to.be.true() } + expect(/^\r?\n*-----BEGIN RSA PRIVATE KEY-----\r?\n/.test(data.key)).to.be.true() + expect(/\r?\n-----END RSA PRIVATE KEY-----\r?\n*$/.test(data.key)).to.be.true() expect(data.key.trim().length).to.be.within(min + 1, max - 1) } @@ -62,8 +62,8 @@ function checkCSR (data, expectClientKey) { expect(data[k]).to.be.a('string') }) if (expectClientKey) { expect(data.clientKey).to.equal(expectClientKey) } - expect(/^\n*-----BEGIN CERTIFICATE REQUEST-----\n/.test(data.csr)).to.be.true() - expect(/\n-----END CERTIFICATE REQUEST-----\n*$/.test(data.csr)).to.be.true() + expect(/^\r?\n*-----BEGIN CERTIFICATE REQUEST-----\r?\n/.test(data.csr)).to.be.true() + expect(/\r?\n-----END CERTIFICATE REQUEST-----\r?\n*$/.test(data.csr)).to.be.true() } function checkCertificate (data, selfsigned) { @@ -72,8 +72,8 @@ function checkCertificate (data, selfsigned) { expect(data).to.have.property(k) expect(data[k]).to.be.a('string') }) - expect(/^\n*-----BEGIN CERTIFICATE-----\n/.test(data.certificate)).to.be.true() - expect(/\n-----END CERTIFICATE-----\n*$/.test(data.certificate)).to.be.true() + expect(/^\r?\n*-----BEGIN CERTIFICATE-----\r?\n/.test(data.certificate)).to.be.true() + expect(/\r?\n-----END CERTIFICATE-----\r?\n*$/.test(data.certificate)).to.be.true() if (selfsigned) { expect(data.clientKey).to.equal(data.serviceKey) } else { expect(data.clientKey).to.not.equal(data.serviceKey) } } @@ -84,8 +84,8 @@ function checkCertificateData (data, info) { function checkPublicKey (data) { expect(data).to.be.an('object').that.has.property('publicKey') expect(data.publicKey).to.be.a('string') - expect(/^\n*-----BEGIN PUBLIC KEY-----\n/.test(data.publicKey)).to.be.true() - expect(/\n-----END PUBLIC KEY-----\n*$/.test(data.publicKey)).to.be.true() + expect(/^\r?\n*-----BEGIN PUBLIC KEY-----\r?\n/.test(data.publicKey)).to.be.true() + expect(/\r?\n-----END PUBLIC KEY-----\r?\n*$/.test(data.publicKey)).to.be.true() } function checkFingerprint (data) { diff --git a/test/pem.spec.js b/test/pem.spec.js index fa7d4420..15beea16 100644 --- a/test/pem.spec.js +++ b/test/pem.spec.js @@ -62,7 +62,7 @@ describe('General Tests', function () { it('Create default ecparam key', function (done) { pem.createEcparam(function (error, data) { hlp.checkError(error) - hlp.checkEcparam(data, 430, 440) + hlp.checkEcparam(data, 430, 470) hlp.checkTmpEmpty() done() }) @@ -70,7 +70,7 @@ describe('General Tests', function () { it('Create secp521k1 ecparam key', function (done) { pem.createEcparam('secp521r1', function (error, data) { hlp.checkError(error) - hlp.checkEcparam(data, 960, 980) + hlp.checkEcparam(data, 960, 1000) hlp.checkTmpEmpty() done() }) @@ -78,7 +78,7 @@ describe('General Tests', function () { it('Create prime256v1 ecparam key', function (done) { pem.createEcparam('prime256v1', function (error, data) { hlp.checkError(error) - hlp.checkEcparam(data, 430, 560) + hlp.checkEcparam(data, 430, 570) hlp.checkTmpEmpty() done() }) @@ -140,7 +140,7 @@ describe('General Tests', function () { it('create private key', function (done) { pem.createPrivateKey(2048, function (error, data) { hlp.checkError(error) - hlp.checkPrivateKey(data, 1650, 1700) + hlp.checkPrivateKey(data, 1650, 1710) hlp.checkTmpEmpty() done() }) @@ -152,7 +152,7 @@ describe('General Tests', function () { password: 'min4chars' }, function (error, data) { hlp.checkError(error) - hlp.checkPrivateKey(data, 1700, 1780, true) + hlp.checkPrivateKey(data, 1700, 1800, true) hlp.checkTmpEmpty() pwkey = data done() @@ -421,288 +421,372 @@ describe('General Tests', function () { it('create ca certificate', function (done) { pem.createCertificate({ commonName: 'CA Certificate' - }, function (error, data) { + }, + function (error, data) { hlp.checkError(error) hlp.checkCertificate(data) hlp.checkTmpEmpty() ca = data done() }) - it('verify signing chain; create and read PKCS12', - function (done) { - pem.createCertificate({ - serviceKey: ca.serviceKey, - serviceCertificate: ca.certificate, - serial: Date.now() - }, function (error, data) { - hlp.checkError(error) - hlp.checkCertificate(data) - hlp.checkTmpEmpty() - - pem.verifySigningChain(data.certificate, - ca.certificate, - function (error, valid) { - hlp.checkError(error) - expect(valid).to.be.true() - - pem.createPkcs12(data.clientKey, - data.certificate, '', { - certFiles: [ca.certificate] - }, - function (error, d) { - hlp.checkError(error) - expect(d).to.be.ok() - hlp.checkTmpEmpty() - - pem.readPkcs12(d.pkcs12, - function (error, keystore) { - hlp.checkError(error) - expect(keystore).to.be.an('object') - expect(keystore).to.have.property('ca') - expect(keystore).to.have.property('cert') - expect(keystore).to.have.property('key') - expect(keystore.ca).to.be.an('array') - expect(keystore.cert).to.be.an('string') - expect(keystore.key).to.be.an('string') - expect(keystore.ca[0]).to.equal(ca.certificate) - expect(keystore.cert).to.equal(data.certificate) - expect(keystore.key).to.equal(data.clientKey) - done() - }) - }) - }) + }) + it('create certificate with text serial "demo-serial"', function (done) { + pem.createCertificate({ + serviceKey: ca.serviceKey, + serviceCertificate: ca.certificate, + serial: 'demo-serial' + }, + function (error, data) { + hlp.checkError(error) + hlp.checkCertificate(data) + hlp.checkTmpEmpty() + pem.readCertificateInfo(data.certificate, function (error, data) { + hlp.checkError(error); + ['validity', 'serial'].forEach(function (k) { + if (data[k]) { + delete data[k] + } }) - }) - it('Fail to verify invalid sigining chain', function ( - done) { - pem.createCertificate({ - serviceKey: ca.serviceKey, - serviceCertificate: ca.certificate, - serial: Date.now() - }, function (error, data) { - hlp.checkError(error) - hlp.checkCertificate(data) - hlp.checkTmpEmpty() - - pem.verifySigningChain(data.certificate, - data.certificate, - function (error, valid) { - hlp.checkError(error) - expect(valid).to.be.false() - done() - }) - }) - }) - it('Verify deep sigining chain', function (done) { - pem.createCertificate({ - commonName: 'Intermediate CA Certificate', - serviceKey: ca.serviceKey, - serviceCertificate: ca.certificate, - serial: Date.now() - }, function (error, intermediate) { - hlp.checkError(error) - hlp.checkCertificate(intermediate) hlp.checkTmpEmpty() - - pem.createCertificate({ - serviceKey: intermediate.clientKey, - serviceCertificate: intermediate.certificate, - serial: Date.now() - // days: 1024 - }, function (error, cert) { - hlp.checkError(error) - hlp.checkCertificate(cert) - hlp.checkTmpEmpty() - - // chain check ok - pem.verifySigningChain(cert.certificate, [ - ca.certificate, intermediate.certificate - ], function (error, valid) { - hlp.checkError(error) - expect(valid).to.be.true() - - // chain check fails -> missing ca cert in chain - pem.verifySigningChain(cert.certificate, [ - intermediate.certificate - ], function (error, valid) { - hlp.checkError(error) - expect(valid).to.be.false() - - // chain check fails -> missing intermediate cert in chain - pem.verifySigningChain( - cert.certificate, [ - ca.certificate - ], - function (error, - valid) { - hlp.checkError(error) - expect(valid).to.be.false() - done() - }) - }) - }) - }) + done() }) }) }) - - it('Create self signed certificate', function (done) { + it('create certificate with hex serial "0x1234567890abcdef"', function (done) { pem.createCertificate({ - selfSigned: true - }, function (error, data) { + serviceKey: ca.serviceKey, + serviceCertificate: ca.certificate, + serial: '0x1234567890abcdef' + }, + function (error, data) { hlp.checkError(error) - hlp.checkCertificate(data, true) + hlp.checkCertificate(data) hlp.checkTmpEmpty() - done() + pem.readCertificateInfo(data.certificate, function (error, data) { + hlp.checkError(error); + ['validity', 'serial'].forEach(function (k) { + if (data[k]) { + delete data[k] + } + }) + hlp.checkTmpEmpty() + done() + }) }) }) - it('Create and verify wildcard certificate', function (done) { - var certInfo = { - commonName: '*.node.ee' - } - pem.createCertificate(Object.create(certInfo), function (error, data) { + it('create certificate with hex serial "1234567890abcdef"', function (done) { + pem.createCertificate({ + serviceKey: ca.serviceKey, + serviceCertificate: ca.certificate, + serial: '1234567890abcdef' + }, + function (error, data) { hlp.checkError(error) hlp.checkCertificate(data) hlp.checkTmpEmpty() - pem.readCertificateInfo(data.certificate, function (error, data) { - hlp.checkError(error) - expect(data).to.be.an('object').that.has.property('commonName') - expect(data.commonName).to.equal(certInfo.commonName) + hlp.checkError(error); + ['validity', 'serial'].forEach(function (k) { + if (data[k]) { + delete data[k] + } + }) hlp.checkTmpEmpty() done() }) }) }) - it('Read edited cert data from certificate', function (done) { - var certInfo = { - issuer: { - country: 'EE', - state: 'Harjumaa', - locality: 'Tallinn', - organization: 'Node.ee', - organizationUnit: 'test', - commonName: 'www.node.ee', - dc: '' - }, - country: 'EE', - state: 'Harjumaa', - locality: 'Tallinn', - organization: 'Node.ee', - organizationUnit: 'test', - commonName: 'www.node.ee', - emailAddress: 'andris@node.ee', - dc: '', - signatureAlgorithm: 'sha256WithRSAEncryption', - publicKeyAlgorithm: 'rsaEncryption', - publicKeySize: '2048 bit' - } - pem.createCertificate(Object.create(certInfo), function (error, data) { + it('create certificate with number serial "1234567890"', function (done) { + pem.createCertificate({ + serviceKey: ca.serviceKey, + serviceCertificate: ca.certificate, + serial: 1234567890 + }, + function (error, data) { hlp.checkError(error) hlp.checkCertificate(data) hlp.checkTmpEmpty() - pem.readCertificateInfo(data.certificate, function (error, data) { hlp.checkError(error); ['validity', 'serial'].forEach(function (k) { - if (data[k]) { delete data[k] } + if (data[k]) { + delete data[k] + } }) - hlp.checkCertificateData(data, certInfo) hlp.checkTmpEmpty() done() }) }) }) - }) + it('verify signing chain; create and read PKCS12', function (done) { + pem.createCertificate({ + serviceKey: ca.serviceKey, + serviceCertificate: ca.certificate, + serial: Date.now() + }, function (error, data) { + hlp.checkError(error) + hlp.checkCertificate(data) + hlp.checkTmpEmpty() - describe('#.checkCertificate tests', function () { - it('Check certificate file @ ./test/fixtures/test.key', - function (done) { - var d = fs.readFileSync('./test/fixtures/test.key').toString() - 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() - pem.checkCertificate(d, function (error, result) { - hlp.checkError(error) - expect(result).to.be.ok() - done() - }) - }) - it('Check certificate file @ ./test/fixtures/test.csr', - function (done) { - var d = fs.readFileSync('./test/fixtures/test.csr').toString() - pem.checkCertificate(d, function (error, result) { - hlp.checkError(error) - expect(result).to.be.ok() - done() - }) + pem.verifySigningChain(data.certificate, + ca.certificate, + function (error, valid) { + hlp.checkError(error) + expect(valid).to.be.true() + + pem.createPkcs12(data.clientKey, + data.certificate, '', { + certFiles: [ca.certificate] + }, + function (error, d) { + hlp.checkError(error) + expect(d).to.be.ok() + hlp.checkTmpEmpty() + + pem.readPkcs12(d.pkcs12, + function (error, keystore) { + hlp.checkError(error) + expect(keystore).to.be.an('object') + expect(keystore).to.have.property('ca') + expect(keystore).to.have.property('cert') + expect(keystore).to.have.property('key') + expect(keystore.ca).to.be.an('array') + expect(keystore.cert).to.be.an('string') + expect(keystore.key).to.be.an('string') + expect(keystore.ca[0]).to.equal(ca.certificate) + expect(keystore.cert).to.equal(data.certificate) + expect(keystore.key).to.equal(data.clientKey) + done() + }) + }) + }) }) - }) + }) + it('Fail to verify invalid sigining chain', function (done) { + pem.createCertificate({ + serviceKey: ca.serviceKey, + serviceCertificate: ca.certificate, + serial: Date.now() + }, function (error, data) { + hlp.checkError(error) + hlp.checkCertificate(data) + hlp.checkTmpEmpty() - describe('#.getModulus tests', function () { - it('Check matching modulus of key and cert file', function (done) { - var f = fs.readFileSync('./test/fixtures/test.crt').toString() - pem.getModulus(f, function (error, data1) { + pem.verifySigningChain(data.certificate, + data.certificate, + function (error, valid) { + hlp.checkError(error) + expect(valid).to.be.false() + done() + }) + }) + }) + it('Verify deep sigining chain', function (done) { + pem.createCertificate({ + commonName: 'Intermediate CA Certificate', + serviceKey: ca.serviceKey, + serviceCertificate: ca.certificate, + serial: Date.now() + }, function (error, intermediate) { hlp.checkError(error) - hlp.checkModulus(data1) + hlp.checkCertificate(intermediate) hlp.checkTmpEmpty() - f = fs.readFileSync('./test/fixtures/test.key').toString() - pem.getModulus(f, 'password', function (error, data2) { + pem.createCertificate({ + serviceKey: intermediate.clientKey, + serviceCertificate: intermediate.certificate, + serial: Date.now() + // days: 1024 + }, function (error, cert) { hlp.checkError(error) - hlp.checkModulus(data2) - expect(data1.modulus).to.equal(data2.modulus) + hlp.checkCertificate(cert) hlp.checkTmpEmpty() - done() + + // chain check ok + pem.verifySigningChain([intermediate.certificate, cert.certificate], [ + ca.certificate, intermediate.certificate + ], function (error, valid) { + hlp.checkError(error) + expect(valid).to.be.true() + + // chain check fails -> missing ca cert in chain + pem.verifySigningChain(cert.certificate, [ + intermediate.certificate + ], function (error, valid) { + hlp.checkError(error) + expect(valid).to.be.false() + + // chain check fails -> missing intermediate cert in chain + pem.verifySigningChain( + cert.certificate, [ + ca.certificate + ], + function (error, + valid) { + hlp.checkError(error) + expect(valid).to.be.false() + done() + }) + }) + }) }) }) }) }) - describe('#.getDhparamInfo tests', function () { - it('Get DH param info', function (done) { - var dh = fs.readFileSync('./test/fixtures/test.dh').toString() - pem.getDhparamInfo(dh, function (error, data) { + it('Create self signed certificate', function (done) { + pem.createCertificate({ + selfSigned: true + }, function (error, data) { + hlp.checkError(error) + hlp.checkCertificate(data, true) + hlp.checkTmpEmpty() + done() + }) + }) + it('Create and verify wildcard certificate', function (done) { + var certInfo = { + commonName: '*.node.ee' + } + pem.createCertificate(Object.create(certInfo), function (error, data) { + hlp.checkError(error) + hlp.checkCertificate(data) + hlp.checkTmpEmpty() + + pem.readCertificateInfo(data.certificate, 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(prime).to.be.a('string') - expect(/([0-9a-f][0-9a-f]:)+[0-9a-f][0-9a-f]$/g.test(prime)).to.be.true() + expect(data).to.be.an('object').that.has.property('commonName') + expect(data.commonName).to.equal(certInfo.commonName) hlp.checkTmpEmpty() done() }) }) }) + it('Read edited cert data from certificate', function (done) { + var certInfo = { + issuer: { + country: 'EE', + state: 'Harjumaa', + locality: 'Tallinn', + organization: 'Node.ee', + organizationUnit: 'test', + commonName: 'www.node.ee', + dc: '' + }, + country: 'EE', + state: 'Harjumaa', + locality: 'Tallinn', + organization: 'Node.ee', + organizationUnit: 'test', + commonName: 'www.node.ee', + emailAddress: 'andris@node.ee', + dc: '', + signatureAlgorithm: 'sha256WithRSAEncryption', + publicKeyAlgorithm: 'rsaEncryption', + publicKeySize: '2048 bit' + } + pem.createCertificate(Object.create(certInfo), function (error, data) { + hlp.checkError(error) + hlp.checkCertificate(data) + hlp.checkTmpEmpty() - describe('#.readPkcs12 tests', function () { - it('Respond with ENOENT for missing PKCS12 file', function ( - done) { - pem.readPkcs12('/i/do/not/exist.p12', function (error) { - hlp.checkError(error, { - code: 'ENOENT' + pem.readCertificateInfo(data.certificate, function (error, data) { + hlp.checkError(error); + ['validity', 'serial'].forEach(function (k) { + if (data[k]) { delete data[k] } }) + hlp.checkCertificateData(data, certInfo) + hlp.checkTmpEmpty() done() }) }) }) + }) - describe('#.checkPkcs12 tests', function () { - it('Check PKCS12 keystore', function (done) { - var pkcs12 = fs.readFileSync('./test/fixtures/idsrv3test.pfx') - pem.checkPkcs12(pkcs12, 'idsrv3test', function (error, result) { + describe('#.checkCertificate tests', function () { + it('Check certificate file @ ./test/fixtures/test.key', function (done) { + var d = fs.readFileSync('./test/fixtures/test.key').toString() + 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() + pem.checkCertificate(d, function (error, result) { + hlp.checkError(error) + expect(result).to.be.ok() + done() + }) + }) + it('Check certificate file @ ./test/fixtures/test.csr', function (done) { + var d = fs.readFileSync('./test/fixtures/test.csr').toString() + pem.checkCertificate(d, function (error, result) { + hlp.checkError(error) + expect(result).to.be.ok() + done() + }) + }) + }) + + describe('#.getModulus tests', function () { + it('Check matching modulus of key and cert file', function (done) { + var f = fs.readFileSync('./test/fixtures/test.crt').toString() + pem.getModulus(f, function (error, data1) { + hlp.checkError(error) + hlp.checkModulus(data1) + hlp.checkTmpEmpty() + + f = fs.readFileSync('./test/fixtures/test.key').toString() + pem.getModulus(f, 'password', function (error, data2) { hlp.checkError(error) - expect(result).to.be.ok() + hlp.checkModulus(data2) + expect(data1.modulus).to.equal(data2.modulus) + hlp.checkTmpEmpty() done() }) }) }) }) + + describe('#.getDhparamInfo tests', function () { + it('Get DH param info', function (done) { + var dh = fs.readFileSync('./test/fixtures/test.dh').toString() + 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(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() + done() + }) + }) + }) + + describe('#.readPkcs12 tests', function () { + it('Respond with ENOENT for missing PKCS12 file', function ( + done) { + pem.readPkcs12('/i/do/not/exist.p12', function (error) { + hlp.checkError(error, { + code: 'ENOENT' + }) + done() + }) + }) + }) + + describe('#.checkPkcs12 tests', function () { + it('Check PKCS12 keystore', function (done) { + var pkcs12 = fs.readFileSync('./test/fixtures/idsrv3test.pfx') + pem.checkPkcs12(pkcs12, 'idsrv3test', function (error, result) { + hlp.checkError(error) + expect(result).to.be.ok() + done() + }) + }) + }) })