New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

node-openssl-cert

Package Overview
Dependencies
Maintainers
1
Versions
155
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-openssl-cert - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

test/config.txt

106

example.js

@@ -24,3 +24,5 @@ const node_openssl = require('./index.js');

organizationName: 'SMH',
organizationalUnitName: 'IT',
organizationalUnitName: [
'IT'
],
commonName: [

@@ -61,3 +63,51 @@ 'certificatetools.com',

openssl.generateRSAPrivateKey(rsakeyoptions, function(err, key, cmd) {
var netcertoptions = {
hostname: 'barracuda1.smhplus.org',
port: 25,
starttls: true,
protocol: 'smtp'
}
var netcertoptions = {
hostname: 'kernelmanic.com',
port: 443,
starttls: false,
protocol: 'https'
}
openssl.getCertFromNetwork(netcertoptions, function(err, cert, cmd) {
//console.log(cert);
//console.log(cmd);
if(err) console.log(err);
//console.log(cert);
openssl.convertCertToCSR(cert, function(err,csroptions,cmd) {
//console.log(csroptions.subject);
openssl.generateRSAPrivateKey(rsakeyoptions, function(err, key, cmd) {
//console.log(key);
openssl.generateCSR(csroptions, key, 'test', function(err, csr, cmd) {
if(err) {
console.log(err);
console.log(cmd.files.config);
} else {
//console.log(cmd.command);
//console.log(csr);
//console.log(cmd.files.config);
openssl.selfSignCSR(csr, csroptions, key, 'test', function(err, crt, cmd) {
if(err) {
console.log(err);
console.log(cmd.files.config);
} else {
console.log(cmd.command);
console.log(crt);
console.log(cmd.files.config);
}
});
}
});
});
});
});
/*openssl.generateRSAPrivateKey(rsakeyoptions, function(err, key, cmd) {
console.log(cmd);

@@ -75,3 +125,3 @@ console.log(key);

});
});
});*/

@@ -91,4 +141,54 @@ /*fs.readFile('./test/rsa.key', function(err, contents) {

/*openssl.getCertFromURL('yahoo.com',function(err, cert) {
if(err) console.log(err);
console.log(cert.pemEncoded);
openssl.convertCertToCSR(cert.pemEncoded, function(err,csroptions,cmd) {
//console.log(csroptions.subject);
openssl.generateRSAPrivateKey(rsakeyoptions, function(err, key, cmd) {
openssl.generateCSR(csroptions, key, 'test', function(err, csr, cmd) {
if(err) {
console.log(err);
console.log(cmd.files.config);
} else {
//console.log(cmd.command);
console.log(csr);
//console.log(cmd.files.config);
}
});
});
});
});*/
/*openssl.getCertFromURL('yahoo.com',function(err, cert) {
openssl.convertCertToCSR(cert.pemEncoded, function(err,csroptions,cmd) {
openssl.generateRSAPrivateKey(rsakeyoptions, function(err, key, cmd) {
openssl.generateCSR(csroptions, key, 'test', function(err, csr, cmd) {
console.log(csr);
});
});
});
});*/
/*fs.readFile('./test/test.crt', function(err, contents) {
//console.log(contents.toString());
openssl.convertCertToCSR(contents.toString(), function(err,csroptions,cmd) {
console.log(csroptions);
openssl.generateRSAPrivateKey(rsakeyoptions, function(err, key, cmd) {
openssl.generateCSR(csroptions, key, 'test', function(err, csr, cmd) {
if(err) {
console.log(err);
} else {
//console.log(cmd.command);
console.log(csr);
//console.log(cmd.files.config);
}
});
});
});
});*/
//ca only keyusage keyCertSign, cRLSign
//all explanations https://superuser.com/questions/738612/openssl-ca-keyusage-extension
'use strict';
const { spawn } = require( 'child_process' )
const { spawn } = require( 'child_process' );
const https = require('https');
var tmp = require('tmp');

@@ -12,3 +13,8 @@ var fs = require('fs');

const stderrbuff = [];
var terminate = false;
if(cmd.indexOf('s_client') >= 0) {
terminate = true;
}
const openssl = spawn( opensslbinpath, cmd.split(' ') );

@@ -18,2 +24,12 @@

stdoutbuff.push(data.toString());
/*//openssl.stdin.setEncoding('utf-8');
setTimeout(function() {
//openssl.stdin.write("QUIT\r");
//console.log('QUIT\r\n');
//openssl.stdin.end();
openssl.kill();
}, 1000);*/
if(terminate) {
openssl.kill();
}
});

@@ -30,2 +46,5 @@

openssl.on('exit', function(code) {
if(terminate && code==null) {
code = 0;
}
var out = {

@@ -45,2 +64,331 @@ command: 'openssl ' + cmd,

var pemEncode = function(str, n) {
var ret = []
for (var i = 1; i <= str.length; i++) {
ret.push(str[i - 1])
var mod = i % n
if (mod === 0) {
ret.push('\n')
}
}
var returnString = '-----BEGIN CERTIFICATE-----\n' + ret.join('') + '\n-----END CERTIFICATE-----'
return returnString;
}
var isEmpty = function (object) {
for (var prop in object) {
if (object.hasOwnProperty(prop)) return false;
}
return true;
}
var getSubjectAlternativeNames = function(sans) {
var names = {}
var sanarr = sans.content[0].split(', ');
for(var i = 0; i <= sanarr.length - 1; i++) {
var san = sanarr[i].split(':');
var type = san[0];
var value = san[1];
//console.log(type + ' - ' + value);
if(names[type]) {
names[type].push(value);
} else {
names[type] = [value];
}
}
return names;
}
var getKeyUsage = function(ku) {
var keyusage = {}
var index = {
'Digital Signature': 'digitalSignature',
'Key Encipherment': 'keyEncipherment',
'Non Repudiation': 'nonRepudiation',
'Data Encipherment': 'dataEncipherment',
'Key Agreement': 'keyAgreement',
'Certificate Sign': 'keyCertSign',
'CRL Sign': 'cRLSign',
'Encipher Only': 'encipherOnly',
'Decipher Only': 'decipherOnly'
}
var keyusages = ku.content[0].split(', ');
if(ku.critical) keyusage.critical = true;
keyusage['usages'] = [];
for(var i = 0; i <= keyusages.length - 1; i++) {
keyusage['usages'].push(index[keyusages[i]]);
}
return keyusage;
}
var getExtendedKeyUsage = function(eku) {
var extendedkeyusage = {}
var index = {
'TLS Web Server Authentication': 'serverAuth',
'TLS Web Client Authentication': 'clientAuth',
'Code Signing': 'codeSigning',
'E-mail Protection': 'emailProtection',
'Time Stamping': 'timeStamping',
'OCSP Signing': 'OCSPSigning',
'Microsoft Individual Code Signing': 'msCodeInd',
'Microsoft Commercial Code Signing': 'msCodeCom',
'Microsoft Trust List Signing': 'msCTLSign',
'Microsoft Encrypted File System': 'msEFS'
}
var extendedkeyusages = eku.content[0].split(', ');
if(eku.critical) extendedkeyusage.critical = true;
extendedkeyusage['usages'] = [];
for(var i = 0; i <= extendedkeyusages.length - 1; i++) {
extendedkeyusage['usages'].push(index[extendedkeyusages[i]]);
}
return extendedkeyusage;
}
var getBasicConstraints = function(bc) {
//console.log(bc);
var basicConstraints = {};
var constraints = bc.content[0].split(', ');
if(bc.critical) basicConstraints.critical = true;
for(var i = 0; i <= constraints.length - 1; i++) {
var value;
var constraint = constraints[i].split(':');
if(constraint[1]=='TRUE') {
value = true;
} else if(constraint[1]=='FALSE') {
value = false
} else if(!isNaN(constraint[1])) {
value = parseInt(constraint[1]);
} else {
value = constraint[1]
}
basicConstraints[constraint[0]] = value;
}
return basicConstraints;
}
//this won't work for organization names with a ', '
/*var getSubject = function(certificate) {
var subject = {};
var index = {
'C': 'countryName',
'ST': 'stateOrProvinceName',
'L': 'localityName',
'postalCode': 'postalCode',
'street': 'streetAddress',
'O': 'organizationName',
'OU': 'organizationalUnitName',
'CN': 'commonName',
'emailAddress': 'emailAddress'
}
var subjectstr = 'Subject: '
var findsubject = certificate.split('\n');
for(var i = 0; i <= findsubject.length - 1; i++) {
if(findsubject[i].indexOf(subjectstr) >= 0) {
var subjectline = findsubject[i].substr(findsubject[i].indexOf(subjectstr) + subjectstr.length);
//console.log(subjectline);
var subjectarr = subjectline.split(', ');
for(var j = 0; j <= subjectarr.length - 1; j++) {
var subsubject = subjectarr[j].split('/');
for(var k = 0; k <= subsubject.length - 1; k++) {
var sub = subsubject[k].split('=');
console.log(sub);
if(sub[0]=='CN' || sub[0]=='OU') {
if(subject[index[sub[0]]]) {
subject[index[sub[0]]].push(sub[1]);
} else {
subject[index[sub[0]]] = [sub[1]];
}
} else {
subject[index[sub[0]]] = sub[1];
}
}
}
}
}
console.log(subject);
}*/
var getSubject = function(certificate) {
var normalizesubject = {};
var subject = {};
var index = {
'C': 'countryName',
'ST': 'stateOrProvinceName',
'L': 'localityName',
'postalCode': 'postalCode',
'street': 'streetAddress',
'O': 'organizationName',
'OU': 'organizationalUnitName',
'CN': 'commonName',
'emailAddress': 'emailAddress'
}
var subjectstr = 'Subject: '
var findsubject = certificate.split('\n');
for(var i = 0; i <= findsubject.length - 1; i++) {
if(findsubject[i].indexOf(subjectstr) >= 0) {
var subjectline = findsubject[i].substr(findsubject[i].indexOf(subjectstr) + subjectstr.length);
//console.log(subjectline.replace(/\//g, ', '));
//console.log(subjectline.split('='));
var subjectarr = subjectline.replace(/\//g, ', ')
var splitsubject = subjectarr.split('=');
if(splitsubject[0].split(', ').length > 2) {
//console.log(splitsubject[j].split(', '));
value = splitsubject[1].split(', ').slice(0, -1).join(', ');
type = splitsubject[0]
} else {
value = splitsubject[1].split(', ')[0];
type = splitsubject[0]
}
normalizesubject[index[type]] = [value];
for(var j = 1; j <= splitsubject.length - 2; j++) {
var type;
var value;
if(splitsubject[j + 1].split(', ').length > 2) {
//console.log(splitsubject[j]);
//console.log(splitsubject[j].split(', '));
value = splitsubject[j + 1].split(', ').slice(0, -1).join(', ');
type = splitsubject[j].split(', ').pop();
//console.log(type);
//console.log(value);
} else {
value = splitsubject[j + 1].split(', ')[0];
type = splitsubject[j].split(', ')[splitsubject[j].split(', ').length - 1];
//console.log(type);
}
//console.log(type);
if(normalizesubject[index[type]]) {
normalizesubject[index[type]].push(value);
} else {
normalizesubject[index[type]] = [value];
}
}
}
}
for(var key in normalizesubject) {
if(normalizesubject[key].length==1) {
subject[key] = normalizesubject[key][0];
} else {
subject[key] = normalizesubject[key];
}
}
return subject;
}
var getx509v3Attributes = function(certificate) {
var extensions = {}
var parsedextensions = {};
//console.log(certificate);
var x509v3 = certificate.split('\n');
for(var i = 0; i <= x509v3.length - 1; i++) {
if(x509v3[i].indexOf('X509v3') >= 0 || x509v3[i].indexOf('CT Precertificate SCTs') >= 0 || x509v3[i].indexOf('Authority Information Access') >= 0 ) {
var ext = x509v3[i].split(':');
var extname = ext[0].replace('X509v3','').trim();
var critical = false;
if(ext[1]==' critical') critical = true;
//console.log(i + ' - ' + extname + ' - ' + critical);
parsedextensions[extname] = { "critical": critical, "content": []};
} else {
if(parsedextensions[extname]) {
parsedextensions[extname].content.push(x509v3[i].trim());
}
}
}
for(var key in parsedextensions) {
if(key=='Subject Alternative Name') {
extensions['SANs'] = getSubjectAlternativeNames(parsedextensions[key]);
} else if(key=='Key Usage') {
extensions['keyUsage'] = getKeyUsage(parsedextensions[key]);
} else if(key=='Extended Key Usage') {
extensions['extendedKeyUsage'] = getExtendedKeyUsage(parsedextensions[key]);
} else if(key=='Basic Constraints') {
extensions['basicConstraints'] = getBasicConstraints(parsedextensions[key]);
}
}
return extensions;
}
this.getCertFromURL = function(url, callback) {
if (url.length <= 0 || typeof url !== 'string') {
callback('Invalid URL','Invalid URL');
}
var options = {
hostname: url,
agent: false,
rejectUnauthorized: false,
ciphers: 'ALL'
}
var req = https.get(options, function(res) {
var certificate = res.socket.getPeerCertificate()
if (isEmpty(certificate) || certificate === null) {
reject({ message: 'The website did not provide a certificate' })
} else {
if (certificate.raw) {
certificate.pemEncoded = pemEncode(certificate.raw.toString('base64'), 64)
}
callback(false,certificate);
return true;
}
});
req.on('error', function(e) {
callback(e,false);
});
req.end();
}
this.getCertFromNetwork = function(options, callback) {
const end = '-----END CERTIFICATE-----';
options.port = typeof options.port !== 'undefined' ? options.port : 443;
options.starttls = typeof options.starttls !== 'undefined' ? options.starttls : false;
options.protocol = typeof options.protocol !== 'undefined' ? options.protocol : 'https';
var command;
var param;
if(options.protocol=='https') {
param = ' -servername ' + options.hostname;
} else {
param = ' -starttls ' + options.protocol;
}
command = 's_client -connect ' + options.hostname + ':' + options.port + param;
runOpenSSLCommand(command, function(err, out) {
if(err) {
callback(err,false,command);
}
callback(false, out.stdout.split('Server certificate\n')[1].split(end)[0] + end, command);
});
//console.log(options);
}
this.convertCertToCSR = function(cert, callback) {
var cmd = [];
tmp.file(function _tempFileCreated(err, path, fd, cleanupCallback) {
if (err) throw err;
fs.writeFile(path, cert, function() {
cmd.push('x509 -in ' + path + ' -text -noout');
runOpenSSLCommand(cmd.join(), function(err, out) {
if(err) {
callback(true,out.stderr,cmd.join());
} else {
var extensions = getx509v3Attributes(out.stdout);
var subject = getSubject(out.stdout);
var csroptions = {
extensions: extensions,
subject: subject
}
//callback(false,out.stdout,cmd.join());
callback(false,csroptions,cmd.join());
}
});
});
});
}
var importRSAPrivateKey = function(key, password, callback) {

@@ -139,3 +487,4 @@ tmp.file(function _tempFileCreated(err, path, fd, cleanupCallback) {

this.generateCSR = function(options, key, password, callback) {
var generateConfig = function(options, callback) {
options.hash = typeof options.hash !== 'undefined' ? options.hash : 'sha256';
const validopts = [

@@ -166,3 +515,3 @@ 'hash',

'msCodeCom',
'mcCTLSign',
'msCTLSign',
'msEFS',

@@ -202,4 +551,6 @@ 'ipsecIKE'

for (var prop in options.subject) {
//console.log(prop + typeof(options.subject[prop]));
if(validsubject.indexOf(prop) >=0 ) {
if(prop=='commonName') {
//if(prop=='commonName' || prop=='organizationalUnitName') {
if(typeof(options.subject[prop]) != 'string') {
for(var i = 0; i <= options.subject[prop].length - 1; i++) {

@@ -212,6 +563,3 @@ req.push(i + '.' + prop + ' = ' + options.subject[prop][i]);

} else {
callback('Invalid subject: ' + prop,{
command: null,
data: null
});
callback('Invalid subject: ' + prop, false);
return false;

@@ -225,14 +573,12 @@ }

if(ext == 'SANs') {
req.push('subjectAltName = @alt_names');
req.push('[ alt_names ]');
var sansatend = [];
sansatend.push('subjectAltName = @alt_names');
sansatend.push('[ alt_names ]');
for(var type in options.extensions[ext]) {
if(validsantypes.indexOf(type) >= 0) {
for(var i = 0; i <= options.extensions[ext][type].length - 1; i++) {
req.push(type + '.' + i + ' = ' + options.extensions[ext][type][i]);
sansatend.push(type + '.' + i + ' = ' + options.extensions[ext][type][i]);
}
} else {
callback('Invalid ' + ext + ': ' + options.extensions[ext].usages[i],{
command: null,
data: null
});
callback('Invalid ' + ext + ': ' + options.extensions[ext].usages[i], false);
return false;

@@ -246,6 +592,3 @@ }

if(validextkeyusage.indexOf(options.extensions[ext].usages[i]) < 0) {
callback('Invalid ' + ext + ': ' + options.extensions[ext].usages[i],{
command: null,
data: null
});
callback('Invalid ' + ext + ': ' + options.extensions[ext].usages[i], false);
return false;

@@ -266,6 +609,3 @@ } else {

if(validkeyusage.indexOf(options.extensions[ext].usages[i]) < 0) {
callback('Invalid ' + ext + ': ' + options.extensions[ext].usages[i],{
command: null,
data: null
});
callback('Invalid ' + ext + ': ' + options.extensions[ext].usages[i], false);
return false;

@@ -294,6 +634,3 @@ } else {

} else {
callback('Provided ' + ext + ' parameter \'' + type + '\' is type ' + typeof(options.extensions[ext][type]) + ', ' + reqtype + ' required',{
command: null,
data: null
});
callback('Provided ' + ext + ' parameter \'' + type + '\' is type ' + typeof(options.extensions[ext][type]) + ', ' + reqtype + ' required', false);
return false;

@@ -312,6 +649,3 @@ }

} else {
callback('Provided ' + ext + ' parameter \'' + type + '\' is type ' + typeof(options.extensions[ext][type]) + ', ' + reqtype + ' required',{
command: null,
data: null
});
callback('Provided ' + ext + ' parameter \'' + type + '\' is type ' + typeof(options.extensions[ext][type]) + ', ' + reqtype + ' required', false);
return false;

@@ -329,13 +663,7 @@ }

} else {
callback('Provided ' + ext + ' parameter \'' + type + '\' is type ' + typeof(options.extensions[ext][type]) + ', ' + reqtype + ' required',{
command: null,
data: null
});
callback('Provided ' + ext + ' parameter \'' + type + '\' is type ' + typeof(options.extensions[ext][type]) + ', ' + reqtype + ' required', false);
return false;
}
} else {
callback('Invalid ' + ext + ': ' + type,{
command: null,
data: null
});
callback('Invalid ' + ext + ': ' + type, false);
return false;

@@ -348,52 +676,115 @@ }

if(valid == 1 && bccmd[0]=='critical') {
callback('Basic constraints cannot contain only \'critical\'', {
command: null,
data: null
});
callback('Basic constraints cannot contain only \'critical\'', false);
return false;
}
} else {
callback('Invalid extension: ' + ext,{
command: null,
data: null
});
callback('Invalid extension: ' + ext, false);
return false;
}
}
for(var i = 0; i <= sansatend.length - 1; i++) {
req.push(sansatend[i]);
}
}
callback(false, req);
//console.log(req);
tmp.file(function _tempFileCreated(err, keypath, fd, cleanupCallback) {
if (err) throw err;
fs.writeFile(keypath, key, function() {
}
this.selfSignCSR = function(csr, options, key, password, callback) {
console.log(csr);
generateConfig(options, function(err, req) {
if(err) {
callback(err,{
command: null,
data: null
});
return false;
} else {
tmp.file(function _tempFileCreated(err, csrpath, fd, cleanupCallback) {
if (err) throw err;
fs.writeFile(csrpath, req.join('\r\n'), function() {
var cmd = ['req -new -new -nodes -key ' + keypath + ' -config ' + csrpath];
if(password) {
cmd.push('-passin pass:' + password);
}
//console.log(cmd);
runOpenSSLCommand(cmd.join(' '), function(err, out) {
if(err) {
callback(err, out.stdout, {
command: [out.command.replace(keypath, 'rsa.key')],
files: {
config: req.join('\r\n')
}
fs.writeFile(csrpath, csr, function() {
tmp.file(function _tempFileCreated(err, keypath, fd, cleanupCallback) {
if (err) throw err;
fs.writeFile(keypath, key, function() {
tmp.file(function _tempFileCreated(err, csrconfig, fd, cleanupCallback) {
if (err) throw err;
fs.writeFile(csrconfig, req.join('\r\n'), function() {
var cmd = ['req -x509 -nodes -in ' + csrpath + ' -days 3650 -key ' + keypath + ' -config ' + csrconfig];
if(password) {
cmd.push('-passin pass:' + password);
}
//console.log(cmd);
runOpenSSLCommand(cmd.join(' '), function(err, out) {
if(err) {
callback(err, out.stdout, {
command: [out.command.replace(keypath, 'rsa.key')],
files: {
config: req.join('\r\n')
}
});
} else {
callback(false, out.stdout, {
command: [out.command.replace(keypath, 'rsa.key').replace(csrpath, 'config.txt'),],
files: {
config: req.join('\r\n')
}
});
}
});
});
});
} else {
callback(false, out.stdout, {
command: [out.command.replace(keypath, 'rsa.key').replace(csrpath, 'config.txt'),],
files: {
config: req.join('\r\n')
});
});
});
});
}
});
}
this.generateCSR = function(options, key, password, callback) {
generateConfig(options, function(err, req) {
if(err) {
callback(err,{
command: null,
data: null
});
return false;
} else {
tmp.file(function _tempFileCreated(err, keypath, fd, cleanupCallback) {
if (err) throw err;
fs.writeFile(keypath, key, function() {
tmp.file(function _tempFileCreated(err, csrpath, fd, cleanupCallback) {
if (err) throw err;
fs.writeFile(csrpath, req.join('\r\n'), function() {
var cmd = ['req -new -nodes -key ' + keypath + ' -config ' + csrpath];
if(password) {
cmd.push('-passin pass:' + password);
}
//console.log(cmd);
runOpenSSLCommand(cmd.join(' '), function(err, out) {
if(err) {
callback(err, out.stdout, {
command: [out.command.replace(keypath, 'rsa.key')],
files: {
config: req.join('\r\n')
}
});
} else {
callback(false, out.stdout, {
command: [out.command.replace(keypath, 'rsa.key').replace(csrpath, 'config.txt'),],
files: {
config: req.join('\r\n')
}
});
}
});
}
});
});
});
});
});
}
});

@@ -400,0 +791,0 @@ }

2

package.json
{
"name": "node-openssl-cert",
"version": "0.0.3",
"version": "0.0.4",
"description": "Node.JS OpenSSL wrapper",

@@ -5,0 +5,0 @@ "main": "index.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc