I am trying to create an https/express server with a server certificate signed by a custom CA.
Here is my code:
var express = require('express');
var https = require('https');
var fs = require('fs');
var app = express();
var config = {
key: fs.readFileSync('cert/server.key'),
cert: fs.readFileSync('cert/server.crt'),
ca: fs.readFileSync('cert/ca.crt')
};
app.get('/', function(req, res) {
res.send('Hello world');
});
https.createServer(config,app).listen(443);
Here is how i create my CA and my server cert :
### CA self signed
openssl genrsa -des3 -out ca.key 1024
openssl req -new -key ca.key -out ca.csr
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt
### server cert signed by CA
openssl genrsa -des3 -out server_pass.key 1024
openssl rsa -in server_pass.key -out server.key
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey ca.key -out server.crt
I don’t think I’m doing it wrong on the openssl part, I create my CA, by definition auto-signed, then I create my server key and csr and then sign it with my CA cert.
I have tried this same nodeJS code with à directly self-signed certificate and in that case it works well.
I assume the problem is that my server cert is neither auto signed nor signed by a public CA as if express didn’t used my custom ca in the config object.
Can someone confirm or invalidate my supposition?
Cheers,
Paul
OK I found out I was using the wrong parameter when signing my key.
I was using: -signkey ca.key
but I should use, when the signing element is a CA file: -CA ca.crt -CAkey ca.key -CAcreateserial
Now it works
Related
I created this certificate:
openssl req -x509 -out localhost.crt -keyout localhost.key
-newkey rsa:2048 -nodes -sha256
-subj '/CN=localhost' -extensions EXT -config <(printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
and have tried installing it in both the Personal and 'Trusted Root Certificate Authorities' but when I try and bind to it in IIS for https it doesn't show up in the 'SSL certificates:' drop down. The certs 'Intended Purposes' is 'Server Authentication'.
Here the machine is laptop.mylocaldomain.net, while dev is a CNAME record aliasing the laptop host from the local DNS server. Both respond to pings and give the same IP address as expected.
Whether it's Firefox, Chrome, or Edge though, if I navigate to https://dev:8080/ running on IIS from a laptop with a self-signed certificate I get a Did Not Connect: Potential Security Issue error and cannot connect to the site, but if I use https://dev.mylocaldomain.net:8080/ which is the same IP address say I get a Warning: Potential Security Risk Ahead warning and I can proceed to the website.
Also https://laptop:8080/ gives the same Warning: Potential Security Risk Ahead warning and I can proceed to the website. Only the CNAME https://dev:8080/ doesn't work.
Cert creation script:
#/bin/sh
sudo openssl genrsa -out LocalDevelopmentCert.key 2048
sudo openssl req -new -key LocalDevelopmentCert.key -sha256 -days 3650 -out LocalDevelopmentCert.csr -config openssl.cnf
sudo openssl x509 -req -days 3650 -in LocalDevelopmentCert.csr -signkey LocalDevelopmentCert.key -out LocalDevelopmentCert.crt -extensions v3_req -extfile openssl.cnf
sudo openssl pkcs12 -name "Local Development IIS Cert" -export -out LocalDevelopmentCert.pfx -inkey LocalDevelopmentCert.key -in LocalDevelopmentCert.crt
Alt Names section of openssl.cnf:
[alt_names]
DNS.1 = *.mylocaldomain.net
DNS.2 = dev
IP.1 = 192.168.XXX.XXX # <- IP address of dev laptop
I've tried setting the CN to various permutations of addresses like dev, dev.mylocaldomain.net, etc. None of them seem to work in the browsers.
How can I get https://dev:8080/ working?
UPDATE 1:
Jesux Manager SSL diagnostic report section:
BINDING: https *:8080:
SSLCertHash: b10671ac592ea5363db0a189fa72180d49ff1956
SSL Flags: None
Testing EndPoint: 127.0.0.1
Cannot find certificate with thumbprint b10671ac592ea5363db0a189fa72180d49ff1956 in store My.
There isn't a store called "My" on Windows 10. I checked every store in MMC for both the Current User and Local Computer to ensure there are no duplicates.
Update 2:
I used the following method to generate a self-signed cert that does report as working in Jexus Manager and its properties show that the certificate is OK.
#!/bin/sh
echo "
[req]
default_bits = 2048
prompt = no
default_md = sha256
x509_extensions = v3_req
distinguished_name = dn
[dn]
C = MyCountry
ST = MyState
L = MyLocality
O = Local Org
OU = Local Org Unit
emailAddress = admin#mylocaldomain.net
CN = *.mylocaldomain.net
[v3_req]
subjectAltName = #alt_names
[alt_names]
DNS.1 = dev.mylocaldomain.net
DNS.2 = dev
DNS.3 = prod.mylocaldomain.net
DNS.4 = prod
DNS.5 = www
DNS.6 = laptop
DNS.7 = desktop
DNS.8 = localhost
">openssl.current.cnf
sudo openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout localcert.key -days 3650 -out localcert.crt -config openssl.current.cnf
sudo openssl pkcs12 -export -out localcert.pfx -inkey localcert.key -in localcert.crt -name "Local Dev Certificate"
It works fine as a self-signed cert Edge and Chrome, but not in Firefox. Does Firefox require you to be your own CA for local development?
I have seen other similar questions but non addresses my problem. I have generated my TLS (openSSL) Self-Signed certificate, but seems not working on my NodeJS server.
Instructions to generate SSL
openssl req -newkey rsa:2048 -keyout key.pem -x509 -days 365 -out certificate.pem
openssl x509 -text -noout -in certificate.pem
openssl pkcs12 -inkey key.pem -in certificate.pem -export -out certificate.p12
openssl pkcs12 -in certificate.p12 -noout -info // verify certificate
So at the end I have .p12 also known as PFX type certificate. Below is my Node.js code:
// ------- Start HTTPS configuration ----------------
const options = {
pfs: fs.readFileSync('./server/security-certificate/certificate.p12'),
passphrase: 'secrete2'
};
https.createServer(options, app).listen(8443);
// -------- End HTTPS configuration -----------------
// Also listen for HTTP
var port = 8000;
app.listen(port, function(){
console.log('running at localhost: '+port);
});
Here is the output when I run curl command, the HTTP request is served correctly, only HTTPS has problem:
Moreover, if I do this:
export CURL_CA_BUNDLE=/var/www/html/node_app/server/security-certificate/cert.p12
Then I get following error:
curl: (77) Problem with the SSL CA cert (path? access rights?)
If I try to access in browser with HTTPS and port, browser says it could not load the page.
Reference links I followed:
Node.js HTTPS:
https://nodejs.org/dist/latest-v8.x/docs/api/https.html#https_https_createserver_options_requestlistener
I'm using AWS RedHat Linux
So far don't know the solution to the above posted problem related to my .p12 bundle certificate (used in my Node.js configuration).
However I have noticed that when I changed the code and tried to use the .pem certificate, it worked correctly with curl -k <MY-URL> command.
const options = {
cert: fs.readFileSync('./server/security-certificate/cert.pem'),
key: fs.readFileSync('./server/security-certificate/key.pem'),
//pfs: fs.readFileSync('./server/security-certificate/cert.p12'), // didn't work
passphrase: 'secrete'
};
https.createServer(options, app).listen(8443);
If any one knows better solution/answer please post that. So far, I'm not sure why .p12 certificate does not work. Should I rename it to .pfx (what is the different and effect)?
I get this error when i tried to set webhook url for facebook messenger bot:
The URL couldn't be validated. Callback verification failed with the following errors: curl_errno = 60; curl_error = SSL certificate problem: self signed certificate in certificate chain; HTTP Status Code = 200; HTTP Message = Connection established
First i created certificate.
1) I used this config file and created certificete authority:
openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-crt.pem
2) I generated a private key
openssl genrsa -out server-key.pem 4096
Then i generated certificate signing request using this configuration file
openssl req -new -config server.cnf -key server-key.pem -out server-csr.pem
After that i executed command:
openssl x509 -req -extfile server.cnf -days 999 -passin "pass:password" -in server-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out server-crt.pem
I didn't chnage any property in configuration files.
Then installed my certificate on windows server by this way
On my Node.js app i created https server using this options:
var server = https.createServer({
ca: fs.readFileSync('sslcert/ca-crt.pem', 'utf8'),
key: fs.readFileSync('sslcert/server-key.pem', 'utf8'),
cert: fs.readFileSync('sslcert/server-crt.pem', 'utf8')
}, app); server.listen(port);
And when i tried to set webhook i got above error. If i open my webhook url on browser i am getting
NET::ERR_CERT_AUTHORITY_INVALID
if ignore this error application console shows status 200
That's right, the URL couldn't be validated because your self signed certificate is in the certificate chain. This is expected behavior.
Self signed certificates are fine for just encrypting the connection, but they don't convey the other important part of proving third party validation that the provider is who they say they are, which is what validation is.
You'll need to get a cert that carries this validation to validate your callback URL. You can purchase one from a reputable vendor, or you can use a service like StartSSL to get one for free (I'm not associated with them in any way, I've just had good experience with them).
You follow THIS and use letsencrypt after that you will get these four files
1.cert.pem 2.chain.pem 3.fullchain.pem 3.privkey.pem
chain.pem is CA file.
Here I also have written a small code snippet to use these.
So I want to have a non-CA certificate as root certificate in an TLS connection in node.js. However the certificate always seems to be considered a CA.
I am generating the root certificate with
openssl req -new -nodes -subj "/CN=ClientName1" -keyout client-key.pem -out client-csr.pem
openssl x509 -req -signkey client-key.pem -in client-csr.pem -out client-cert.pem -extfile v3.ext
(analogous for the server)
and a test-certificate like this
openssl req -new -nodes -subj "/CN=ClientName2" -keyout client-key2.pem -out client-csr2.pem
openssl x509 -req -in client-csr2.pem -out client-cert2.pem -extfile v3.ext -CA client-cert.pem -CAkey client-key.pem -CAcreateserial
with v3.ext being
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
Now the server accepts client-cert as well as client-cert2, however if I generate a third (client-cert3) signed by client-cert2, the server does not accept it. So the root certificate appears to be considered a CA no matter what. Is there a way around it without purposely generating a throwaway dummy root certificate which is only used to sign that one single client-cert?
I am using it like this:
var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
requestCert: true,
rejectUnauthorized: true,
ca: [fs.readFileSync('client-cert.pem')],
port: 15151
};
var server = tls.createServer(options, function (socket) {});
P.S. Also when testing to use client-cert2.pem as root, the server does not accept clients using client-cert2, nor client-cert3, nor client-cert.
Anything which is used to sign another certificate must have the appropriate key usage restrictions. If the the usage restrictions do not allow a certificate to work as a CA you cannot work around it because validation of the certificate chain is done by the client and not by the server.