Load certificate and private key for SSL in Node.js - node.js

Sorry but I have no experience with certificates and SSL, especially in Node.js. I need to configure options for express:
var https = require('https');
var options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('csr.pem')
};
https.createServer(options, my_app).listen(3000);
and if I try with self generated certificates (by openssl) all works like a charm.
Now, I need to change the self generated certificates with the true certificates for my domain. In Plesk I have 3 certificates: a CSR, a Private key (.key) and a Certificate (.crt) in text format, and this certificates are already working on the Plesk configuration of my server, so they are ok.
So, what I need to do now? Which of these is the key.pem and which is the csr.pem?
Sorry but I don't know, can anyone explain me?

It should be this:
key: fs.readFileSync('FILENAME.key'),
cert: fs.readFileSync('FILENAME.crt')
CSR is the request you send to the trusted third party to get a signed certificate. You will receive a certificate back from the trusted third party, and that's what you use with the private key in NodeJS.

Related

What key should I use to sign an intermediate SSL certificate for a reversed proxied HTTPS connection?

I have an Apache server hosting a couple webpages, and an express server running on another machine that connects via a reverse proxy to the apache server, providing an endpoint to the webpage. The webpage is already running on HTTPS with valid certificates, but now I have to configure the express server to do the same with the intermediate certificates, I believe Which private key should I use to setup this service? Or are the intermediate certs signed by the apache head? I don't think that is the case since the configuration dones't work without a key, but I still cannot get my head around how this works if the certificates are issued at the same time the private key of the server is generated. How is it possible to cofigure intermediate connections with intermediate certs if the intermediate servers didn't exist when the certificates where issued?
This is the express server configuration so far:
const options = {
// The same certificate apache uses. Is this right?
cert: fs.readFileSync(config.ssl.dir + config.ssl.cert)
// The three sections of the bundle the issuer provided
ca: [],
// The private key I don't have (its in the other server)
key: fs.readFileSync(config.ssl.dir + config.ssl.key),
};
config.ssl.ca.forEach((value) => {
if (value) options.ca.push(fs.readFileSync(config.ssl.dir + value));
});
server = https.createServer(options, app);
Some more information, I have three files:
certificate.csr, the one the apache server uses and works, so I think it is the root certificate
certificate.pem, with the exact same contents as certificate.csr
a_bundle.csr, with three sections. I believe those are the intermediate certs.
These files were provided by GoDaddy.com when buying the ssl certificates, but with meaningless names.

MTLS - generate certificate to nodejs client side

We need to communicate between our ec2 server and our customer server via Mutual TLS.
The requests are sent from our server to our customer server - so we are the client here.
I read this post, talking about how to generate the files.
The first step is to create a certificate authority (CA) that both the
client and server trust. The CA is just a public and private key with
the public key wrapped up in a self-signed X.509 certificate.
Our cert and their cert - should be signed from the same root CA? who should provide it?
The code in my side should be like:
const req = https.request(
{
hostname: 'myserver.internal.net',
port: 443,
path: '/',
method: 'GET',
cert: fs.readFileSync('client.crt'),
key: fs.readFileSync('client.key'),
ca: fs.readFileSync('ca.crt')
},
res => {
res.on('data', function(data) {
// do something with response
});
}
);
So what should we provide each other? We don't exactly understand and they are not providing more details, just asked us to give them a certificate...
Our cert and their cert - should be signed from the same root CA? who should provide it?
Since the control of the client certificate is done at the TLS server side (i.e. at the customer) it depends fully on what they expect. They might require a publicly signed certificate, they might require a certificate signed by their own CA. Or they might simply check that a specific certificate gets used and will also accept self-signed certificates for this.

How to connect with client side certificates using https module on Node.js

In production my website uses a Let's Encrypt certificate, so that the user can see in the browser the valid certificate lock.
If the user navigates to route example.com/dashboard, I would like the login using client side certificate (and not username/password).
I have generated on a server using openssl private & public key. The public key stays on server and the private key is sent to the client.
Using this tutorial, I have created in server.js
const express = require('express')
const https = require('https')
const fs = require('fs')
const masterapp = express()
var options = {
key: fs.readFileSync('/etc/ssl/certs/sslforfree/private.key'),
cert: fs.readFileSync('/etc/ssl/certs/sslforfree/certificate.crt'),
requestCert: true,
rejectUnauthorized: false,
}
And then in the middleware
const cert = req.connection.getPeerCertificate()
if (req.client.authorized) {
if (cert.subject.CN === "Client123" && cert.fingerprint256 === "AA:BB:CC:DD:00..
On Mac OS it shows correctly the prompt in the browser where I select the key (key is stored in Keychain).
Problems:
req.client.authorized is always false
How can I securely check with Node.js that the private key corresponds to public key?
Is it safer to have dashboard.example.com subdomain or route example.com/dashboard (express router)?
According to the medium article you referenced, you need to supply a ca property in the options object. This should be a list of client CAs that you trust:
Finally, we supply a list of CA certificates that we consider valid. For now, we sign client certificates with our own server key, so it will be the same as our server certificate.
, ca: [ fs.readFileSync('server_cert.pem') ]
}
You should use the CA to sign the public key of the client's generated key. To do this, you'll have to generate a CSR with the private key, then sign the CSR with the CA you have in the list. Once you do this, you can send the private key and the resulting certificate to the client in a bundle, and they will be able to authenticate against your system.
This is because you left off the ca property.
This happens between the browser and your server automatically, once you have a trusted ca.
To create a CA, you can use openssl to generate a self-signed certificate and private key.
This depends, and is out of scope for stackoverflow. You might consider asking on serverfault.com or security.stackexchange.com.

Socket.IO TLS requiring key/cert

I have a CA from an authorized server. I have set up my HTTPS and WebSocket setup as follows:
var httpsOptions = {
cert: fs.readFileSync(config.ssl.server_cert),
key: fs.readFileSync(config.ssl.server_key),
requestCert: true,
rejectUnauthorized: true,
passphrase: config.ssl.server_password
};
httpsServer.listen(config.https_port, function () {
console.info("HTTPS server running on %d", config.https_port);
});
io = io.listen(server);
io.sockets.on('connection', function (socket) {
console.log("connected: " + socket.id);
})
Now, my clients will have to sign up for an account. When they do, I want to create a private/public key for them, and sign it with the CA that I have. They then have to use them for any web socket connection. If these are not provided, I don't want to even allow a connection.
My client at the moment is then:
io.connect(url, {secure: true, 'force new connection': true});
But I cannot figure out how to A) pass the key to the server, and B) If this is even possible?
If you're talking about browsers, then the client certificate and private key has to be installed in the browser or OS certificate store (depending on which browser is being used). Once installed, the browser will automatically send the certificate.
Unfortunately, client certificate installation is not a user-friendly process.
If your client is a node process, a client cert option was (finally) added in socket.io 1.3.
Don't forget to validate that the presented certificate matches a user account in your system. rejectUnauthorized only validates that the client presented a certificate issued by any trusted CA.
Do you mean you have a SSL certificate for your server? You can't sign new certificates with that. No trusted root CA gives out certs that allow third parties to sign certs without a very long process and lots of money.
You can run your own CA that signs client certificates. You have to configure your server to trust your client certificate-issuing CA (via the ca option in createServer) since it will be untrusted by default.

Socket.io/Node.js and SSL

I recently bought a SSL certificate from Comodo. They sent me these files:
AddTrustExternalCARoot.crt
PositiveSSLCA2.crt
mydomain.crt
I then created my private key and ca-bundle like so,
openssl genrsa -des3 -out mydomain.key 1024
cat PositiveSSLCA2.crt AddTrustExternalCARoot.crt > mydomain.ca-bundle
This is the code I'm using to put it all together. I get an SSL connection error in Chrome.
var privateKey = fs.readFileSync('./mydomain.key').toString();
var certificate = fs.readFileSync('./mydomain.crt').toString();
var ca = fs.readFileSync('./mydomain.ca-bundle').toString();
var io = require('socket.io').listen(1200, { key:privateKey,cert:certificate,ca:ca });
You generate your private key before you are issued a certificate.
A certificate is created when a CA signs the public key that goes with a particular private key. You generate a private key, then you create a CSR which includes the public key. The CA sends you back a certificate.
You must have generated a private key at some point before you got a certificate – you have to use that. If you try to use a private key that you generate after the certificate is issued, it will obviously not match the public key in your certificate.
Also, node's tls module cannot parse certificate bundles. You have to pass each certificate separately in an array.
{
key: fs.readFileSync('mydomain.key'),
cert: fs.readFileSync('mydomain.crt'),
ca: [ fs.readFileSync('AddTrustExternalCARoot.crt'), fs.readFileSync('PositiveSSLCA2.crt') ]
}
The docs have more detail.

Resources