41

I'm writing a proxy support HTTPS-HTTPS proxy. Before i use Python as the main programming language, but i'm interested in node.js now, so i prepare to migrate.

The largest problem i'm facing is that i don't know how to generate CA and other server certificates in node.js. In Python, there is pyOpenSSL which is awesome. I don't find something similar in node.js until now.

Maybe i should use openssl-fork method? But how to handle the interactive operation in openssl.

Thank you.

ayanamist
  • 1,035
  • 3
  • 12
  • 20

5 Answers5

38

Use shell for certificate:

openssl genrsa -out server-key.pem 1024
openssl req -new -key server-key.pem -out server-csr.pem
openssl x509 -req -in server-csr.pem -signkey server-key.pem -out server-cert.pem

Then use them in node.js

var https = require('https');
https.createServer({
    key: fs.readFileSync('server-key.pem'),
    cert: fs.readFileSync('server-cert.pem')
},
function (req,res) {
      ... 
})

EDIT:

You can also give a try to this project in NPM : https://npmjs.org/package/openssl-wrapper

I found it searching the NPM repo : https://npmjs.org/search?q=openssl

I did not tried or checked it myself, but it looks like a way to generate the certificate using node, which is the original question.

var openssl = require('openssl-wrapper');
var password = 'github';

return openssl.exec('genrsa', {des3: true, passout: 'pass:' + password, '2048': false}, function(err, buffer) {
    console.log(buffer.toString());
});

I'd be interested by a feedback. ;)

Nicocube
  • 2,962
  • 2
  • 20
  • 28
  • 2
    I see no harm in wrapping those shell scripts in in exec functions and a spawn function, and using that instead of a whole library – Nelson Owalo Oct 03 '18 at 07:22
34

In case somebody does want to programatically create CSRs from node.js, I have created a nodejs module which uses openssl to create a private key and a CSR.

Edit: Use pem instead. It is much more complete and probably more reliable.

Edit2: Actually, pem is also just a simple wrapper over openssh. For a pure js implementation, look into forge

Eric Vicenti
  • 1,928
  • 1
  • 16
  • 16
  • 5
    My module is now totally deprecated. I was only publishing it because I didnt know about pem: https://www.npmjs.org/package/pem – Eric Vicenti Apr 27 '14 at 03:05
  • pem just spawns openssl. – andrewrk Aug 18 '14 at 00:49
  • @andrewrk that's a good thing. High-profile vulnerabilities like heartbleed aside (which never effected node directly), keep security and crypto code as isolated and DRY as possible. – David Souther Sep 16 '14 at 15:35
  • @DavidSouther Node actually links against a fork of the OpenSSL libraries, generally with a more recent version than what is on the hosting system. – Mark Mar 12 '15 at 14:58
  • 1
    `node-forge` is a life saver! As far as I know, it's the only option if you also need Windows support. – Arthur C Nov 06 '17 at 09:43
11

node-forge allow that. Nothing to say more. DOES NOT use openssl shell command internally.

https://github.com/digitalbazaar/forge#x509

socketpair
  • 1,893
  • 17
  • 15
1

there is a pure javascript library called "Jsrsasign" to generate CSR certificates.

const r = require("jsrsasign");
const kp = r.KEYUTIL.generateKeypair("RSA", 2048);
const csr = r.KJUR.asn1.csr.CSRUtil.newCSRPEM({
 subject: {},
 sbjpubkey: kp.pubKeyObj,
 sigalg: "SHA256withRSA",
 sbjprvkey: kp.prvKeyObj,
});
const privateKey = r.KEYUTIL.getPEM(kp.prvKeyObj, "PKCS1PRV");

for more docs visit http://kjur.github.io/jsrsasign/

-1

None of the node libraries seem to support the options I need, so I use the openssl executable.

import { execSync } from 'child_process'
import fs from 'fs'
import tempy from 'tempy'

const extHeader = `authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
`
const shell = cmd => execSync(cmd, { stdio: 'pipe' })

const writeCert = (extFile, outfile) => {
  const cmd = [
    `openssl`,
    `x509`,
    `-req`,
    `-in ssl/my.csr`,
    `-CA ssl/root-ca.pem`,
    `-CAkey ssl/root-ca.key`,
    `-CAserial ssl/root-ca.srl`,
    `-out ssl/${outfile}`,
    `-days 1825`,
    `-sha256`,
    `-extfile ${extFile}`,
    `-passin pass:mypassphrase`
  ]
  shell(cmd.join(' '))
}

const createCert = domains => {
  const sans = domains.map((d, i) => `DNS.${i + 1} = ${d}`)
  const ext = extHeader + sans.join('\n')
  const extFile = tempy.file()
  fs.writeFileSync(extFile, ext, 'utf-8')
  writeCert(extFile, 'out.crt')
}

Dependencies:

  • openssl executable
  • yarn add tempy
Jay
  • 9,314
  • 7
  • 33
  • 40
  • This code seems incomplete... What is `ssl/my.csr`, `ssl/root-ca.pem`, etc.? How to generate them? Why not include the code to generate them in the answer? – Vladimir Panteleev Dec 07 '20 at 00:36