openssl self signed certificate node.js - node.js

I have installed openSSl with cygwin and generated self singed certifikate like this
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out csr.pem
openssl x509 -req -in csr.pem -signkey server.key -out cert.pem
i tried to test if i was succesfull so i created a basic tls connection with node
var tls=require("tls");
var fs=require("fs");
var serverOptions={
key:fs.readFileSync('C:/cygwin64/home/Matej/csr.pem'),
cert:fs.readFileSync('C:/cygwin64/home/Matej/cert.pem')
}
var server=tls.createServer(serverOptions);
server.listen(4001)
but it threw error
c.context.setKey(options.key);
^
Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
i quite dont understand what does the erron mean. Did i generated the key/certifikate wrong?
I tried looking here but my pem files does not contain ^M .My cert looks like
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
and csr
-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----

Related

mosquitto mqtt broker tls problem. IP doesn not match certificate's altnames

I have provided the broker and the client with certificates. The broker is avaible at 172.27.224.1.
When I try to connect with the client, I get following error message:
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: IP: 172.27.224.1 is not in the cert's list:
at new NodeError (node:internal/errors:371:5)
at Object.checkServerIdentity (node:tls:297:12)
at TLSSocket.onConnectSecure (node:_tls_wrap:1540:27)
at TLSSocket.emit (node:events:390:28)
at TLSSocket._finishInit (node:_tls_wrap:944:8)
at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:725:12) {
reason: "IP: 172.27.224.1 is not in the cert's list: ",
host: '172.27.224.1',
cert: {
subject: [Object: null prototype] {
C: 'AU',
ST: 'Some-State',
O: '',
OU: '',
CN: '172.27.224.1'
},
issuer: [Object: null prototype] {
C: 'DE',
ST: 'Some-State',
O: '',
OU: '',
CN: '172.27.224.1'
},
[...]
What's the error here? The ca.crt is a self signed cert with issued for 172.27.224.1 and issued from 172.27.224.1. The client.crt is issed from 172.27.224.1 and issued for "username".
should't this work?
Steps I used to generate the certificate:
openssl genrsa -des3 -out ca.key 2048
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
openssl genrsa -out client.key 2048
openssl req -new -out client.csr -key client.key
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360
I use for the client node.js v16.13 and the mqtt library.
Assuming you are using OpenSSL to create the CA cert then you can do it as follows:
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 -sha256 \
-keyout ca.key -out ca.crt -reqexts SAN -extensions SAN \
-subj '/CN=Broker Cert' \
-config <(cat /etc/pki/tls/openssl.cnf; printf "[SAN]\nsubjectAltName=IP:172.27.224.1")
This makes an assumption that you are using a openss.cnf file stored at /etc/pki/tls/openssl.cnf
But as a rule it's better to create a CA cert and then sign server certs with that as it makes changing things easier and you don't need to update all the clients when you want to change something. It also makes issuing client certificates a lot easier.
Please do still update the question with details of the programming language and client library you are using that is now enforcing the SAN rules.

So i have made a ssl certificate for my localhost, but the connection is refused,what should be done?

THIS PART OF THE CODE IS HOW I MADE AN SSL CERTIFICATE ===================
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RS -pkeyopt rsa_keygen_bits:2048 -out ca.key
Algorithm RS not found
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out ca.key
................................................+++
.....+++
C:\Users\avivo\Documents\https_app\server\ssl>openssl req -new -x509 -days 360 -key ca.key -subj "/CN=Test CA/O=AAAA Teat Organization" -out ca.crt
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out server.key
......................................................................................................................................................+++
................................................+++
C:\Users\avivo\Documents\https_app\server\ssl>openssl req -new -key server.key -subj "/CN=localhost/O=AAAA Test Organization" -out server.csr
C:\Users\avivo\Documents\https_app\server\ssl>openssl x509 -days 360 -req -in server.csr -CAcreateserial -CA ca.crt -CAkey cs.key -out server.crt
Signature ok
subject=/CN=localhost/O=AAAA Test Organization
Getting CA Private Key
Error opening CA Private Key cs.key
14360:error:02001002:system library:fopen:No such file or directory:bss_file.c:406:fopen('cs.key','rb')
14360:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:408:
unable to load CA Private Key
unable to write 'random state'
//this the part of ssl ca and server certificate
erial -CA ca.crt -CAkey ca.key -out server.crt
Signature ok
subject=/CN=localhost/O=AAAA Test Organization
Getting CA Private Key
unable to write 'random state'
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out client.key
.......+++
...................................+++
C:\Users\avivo\Documents\https_app\server\ssl>openssl req -new -key client.key -subj "/CN=Test User/O=AAAA Test Organization/UID=testuser1" -out client.csr
C:\Users\avivo\Documents\https_app\server\ssl>openssl x509 -days 360 -req -in client.csr -CAcreateserial -CA ca.crt -CAkey ca.key -out client.crt
Signature ok
subject=/CN=Test User/O=AAAA Test Organization/UID=testuser1
Getting CA Private Key
unable to write 'random state'
//this is the client side
MAIN CODE IN INDEX.JS====================================================
var express=require('express'),
fs=require('fs'),
https=require('https'),
path =require('path');
var app=express();
var directoryToServe='client';
var port=3443;
app.use('/',express.static(path.join(__dirname,"..",directoryToServe)))
var httpsOptions={
cert:fs.readFileSync(path.join(__dirname,'ssl','server.crt')),
key:fs.readFileSync(path.join(__dirname,'ssl','server.key'))
}
https.createServer(httpsOptions,app)
.listen(port,function(){
console.log('serving the'+directoryToServe+'/directory at https://localhost:3443')
})
ERROR=======================
C:\Users\avivo\Documents\https_app\server>node index .js
serving theclient/directory at https://localhost:3443
^C
C:\Users\avivo\Documents\https_app\server>node index .js
serving theclient/directory at https://localhost:3443
^C
C:\Users\avivo\Documents\https_app\server>curl -k https://localhost:3443
curl: (7) Failed to connect to localhost port 3443: Connection refused
C:\Users\avivo\Documents\https_app\server>node index .js
serving theclient/directory at https://localhost:3443
^C
//i have no idea as to why my isn't the server running,can anyone please help??
Your Node application quits as soon as you hit ctrl-c to run the curl command.
You either have to open a second terminal instance for curl or run the Node application as a process, by using something like PM2.

Is openssl '-batch' command line option deprecated or hidden?

I have figured out a set of SSL commands (using openssl tool) to create the private key, CSR and ultimately, the certificate.
Root key and certificate:
openssl genrsa -aes256 -out private/ca.key.pem 4096
openssl req -config openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem
Client SSL key and certificate:
openssl genrsa -aes256 -out private/client.key.pem 2048
openssl req -config openssl.cnf -key private/client.key.pem -new -sha256 -out csr/client.csr.pem
openssl ca -config openssl.cnf -extensions usr_cert -days 375 -notext -md sha256 -in csr/client.csr.pem -out certs/client.cert.pem
However, at the third step of client SSL certificate creation, the tool asks couple of further (interactive) questions as follows:
openssl ca -config openssl.cnf -extensions server_cert -days 375 -notext -md sha256 -in csr/www.example.com.csr.pem -out certs/www.example.com.cert.pem
Using configuration from openssl.cnf
Enter pass phrase for /Users/myssl/private/ca.key.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 4096 (0x1000)
Validity
Not Before: Oct 31 18:43:27 2017 GMT
Not After : Nov 10 18:43:27 2018 GMT
Subject:
countryName = IN
stateOrProvinceName = KAR
organizationName = ABC
commonName = www.example.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
OpenSSL Generated Server Certificate
X509v3 Subject Key Identifier:
D7:12:DB:DE:D1:92:52:15:E5:AD:83:84:B6:7F:9F:CF:97:06:91:8E
X509v3 Authority Key Identifier:
keyid:1C:5F:64:BB:8B:E5:8E:A7:DE:00:E2:D7:1A:D5:1D:52:53:5E:59:32
DirName:/C=IN/ST=KAR/L=BLR/O=ABC/CN=www.example.com
serial:C3:D6:EE:B0:FE:28:76:14
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
Certificate is to be certified until Nov 10 18:43:27 2018 GMT (375 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
The above two prompts goes off only after adding the '-batch' option to the command line. However, I did not find any mention or help on the 'man openssl' page.
I am using openssl version 1.0.2k. Is this option deprecated or it is hidden? It still works and makes the above command non-interactive.

NodeJS & SSL - "bad password read"

Node is failing to create a secure context for SSL communications.
Specifically, I'm trying to get remote notifications to work on iOS. I use a module, called node-apn which throws this error:
Error: error:0906A068:PEM routines:PEM_do_header:bad password read
at Error (native)
at Object.createSecureContext (_tls_common.js:108:19)
at Object.exports.connect (_tls_wrap.js:852:21)
at apnSocket (/home/Slurp/node_modules/apn/lib/socket.js:56:19)
at Connection.<anonymous> (/home/Slurp/node_modules/apn/lib/connection.js:188:17)
at _fulfilled (/home/Slurp/node_modules/apn/node_modules/q/q.js:834:54)
at self.promiseDispatch.done (/home/Slurp/node_modules/apn/node_modules/q/q.js:863:30)
at Promise.promise.promiseDispatch (/home/Slurp/node_modules/apn/node_modules/q/q.js:796:13)
This seems to be a generic error though, and isn't really related to APN specifically.
This is because you've specified a passphrase when generating the cert. This is a password that must be supplied by anyone wanting to use it.
Adding a passphrase field to the credentials solves the problem.
var credentials = {
key: fs.readFileSync('XXX.key', 'utf8'),
cert: fs.readFileSync('XXX.crt', 'utf8'),
passphrase: 'XXXX'
}
var httpsServer = https.createServer(credentials, app);
The following command will generate an unencrypted key, so you won't need to provide a passphrase:
openssl rsa -in yourKey.key -out newKey.key
This command will prompt you for the passphrase.
Use these to generate pem.
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

curl openssl can't verify IIS 7 self-signed cert even when added to curl-ca-bundle.crt

I used IIS 7 on Windows Server Enterprise 2008 to generate a self-signed cert for use with IIS (basically one-click button).
However, even when I export and add this cert to a windows client's curl-ca-bundle.crt, neither it nor openssl.exe will not verify the cert correctly:
openssl s_client -CAfile curl-ca-bundle.crt -showcerts -connect myserver.ad.pri:443
CONNECTED(00000003)
depth=0 /CN=myserver.ad.pri
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /CN=myserver.ad.pri
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/CN=myserver.ad.pri
i:/CN=myserver.ad.pri
-----BEGIN CERTIFICATE-----
MIIDADCCAeigAwIBAgIQTi9gdBLdo6pJ1h4Zljr/wzANBgkqhkiG9w0BAQUFADAp
....
-----END CERTIFICATE-----
---
Server certificate
subject=/CN=myserver.ad.pri
issuer=/CN=myserver.ad.pri
---
No client certificate CA names sent
---
SSL handshake has read 924 bytes and written 444 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES128-SHA
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
Start Time: 1377728216
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
read:errno=104
I used IE to export the cert to Base-64 Encoded, which is openssl-readable as PEM:
openssl x509 -inform PEM -in myserver.crt -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
4e:2f:60:74:12:dd:a3:aa:49:d6:1e:19:96:3a:ff:c3
Signature Algorithm: sha1WithRSAEncryption
Issuer: CN=myserver.ad.pri
Validity
Not Before: Aug 26 15:38:46 2013 GMT
Not After : Aug 26 00:00:00 2014 GMT
Subject: CN=myserver.ad.pri
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
....
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage:
Key Encipherment, Data Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
Signature Algorithm: sha1WithRSAEncryption
...
-----BEGIN CERTIFICATE-----
....
openssl/curl with the same curl-ca-bundle.crt will verify certs from google.com:443 etc. just fine.
I also ran into this (and I'm very surprised more people haven't.) when I couldn't get a NodeJS HTTP(s) client to connect to an IIS instance with a self-signed-certificate on it (one created through IIS manager) Just got the dreaded' unable to verify the first certificate error!
It seems that this is because the certificates that IISManager creates for this purpose specify some 'Key Usage' extensions; 'Key Encipherment' and 'Data Encipherment'.
It turns out that when openssl encounters a certificate that specifies 'Key Usage' but fails to specify the 'certSign' usage then the openssl code will discount that certificate as a possible CA certificate even if it has been correctly provided to the openssl code (meaning it is unable to verify the certificate against said absent CA!).
(See the logic here https://github.com/openssl/openssl/blob/6f0ac0e2f27d9240516edb9a23b7863e7ad02898/crypto/x509v3/v3_purp.c#L503 )
The solution is as the one already above, which is to create your own certificates with the correct key usages (or no key usage extensions!)
I also thought I should include an alternative way of creating the Self Signed certificate that openssl clients would be happy with if you're in windows land.
First download the powershell script from here
In a powershell console (Administrative) execute the following commands from within a folder that contains the downloaded scripts
New-SelfsignedCertificateEx -StoreLocation "LocalMachine" -KeyUsage "DigitalSignature,KeyEncipherment,KeyCertSign" -Subject "CN=<HOST_NAME_TO_USE>" -FriendlyName "<HOST_NAME_TO_USE>" -SignatureAlgorithm sha256 -SubjectAlternativeName "<HOST_NAME_TO_USE>","anotherhost.org","someotherdomain.com"
Once you've executed the above command your LocalMachine\Personal Certificates store will contain a self-signed certificate that can be used by IIS for its SSL communications. (Please note you may also need to copy this certificate into one of the Trusted Root stores as well to guarantee that the certificate is trusted on that machine)
I solved this by using openssl to create a self-signed CA cert, then created a server cert request (also in OpenSSL, for some reason openssl does not like to sign requests generated by IIS), signed it with the former CA cert, then exported to PKCS12. Then imported into IIS. Once the CA cert is added to curl-ca-bundle.crt, it will verify the chain correctly:
Generate a CA:
openssl req -new -x509 -days 3650 -extensions v3_ca \
-keyout cakey.pem -out cacert.pem -config /etc/ssl/openssl.cnf \
-newkey rsa:2048
Generate a server key and signing request:
openssl req -new -nodes -out server-csr.pem -keyout server-key.pem -newkey rsa:2048
Sign the request with the CA:
openssl ca -config /etc/ssl/openssl.cnf -cert cacert.pem -keyfile cakey.pem \
-out server-cert.pem -in server-csr.pem
Export the server cert to PKCS#12:
openssl pkcs12 -export -out server-key-cert.pfx \
-inkey server-key.pem -in server-cert.pem -certfile cacert.pem
Import server-key-cert.pfx into IIS. (Re)bind the site binding's SSL binding to the cert.
Append cacert.pem to clients' curl-ca-bundle.crt. openssl s_client -showcerts -CAfile curl-ca-bundle.crt -connect server:443 has depth 0 and 1 and will verify return.
Notes: Make sure that keyUsage = nonRepudiation, digitalSignature, keyEncipherment is enabled under section [usr_cert] in openssl.cnf else requests won't contain those keyUsage and IIS will complain on binding.

Resources