I am working with self signed certificates for the fist time. I understand that node red does not use the default ca store. The solution to this seems to be to provide a key and self signed certificate when preforming an https request. I would like to uses the standard http request node to do this but i cant find documentation on how to a key, cert, and rejectUnauthorized through the message block. Is this even possible?
Thank you
NodeJS bundles the default CA store into the node binary so you can't just add a file to a dir and have it pick up extra CA certs.
Assuming you are using the HTTP-request node you can add certs/keys by ticking the "Enable secure (SSL/TLS) connection" check box.
This should make a drop down box appear that will let you create a new TLS configuration. In here you can add the certs and keys for the connection.
Related
I am using mkcert to generate a self signed certificate for localhost.
mkcert -install
mkcert localhost
This works fine for the browser but if I try and and do a fetch from node, I get this error:
FetchError: request to https://localhost:52882/ failed, reason: unable to verify the first certificate
I think this is because mkcert is not creating the full chain.
I have hacked around this by using the NODE_EXTRA_CA_CERTS environment variable.
NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"
and I know there is the process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; nuclear approach but I am curious to know how this can be fixed without these.
It is working perfectly. You have own certificate authority (CA) and that one issues localhost certificate directly. There is no intermediate certificate authority used, so assumption mkcert is not creating the full chain is not correct.
CA cert must be available on your machine and you need to define, which CA certs are trustworthy. NODE_EXTRA_CA_CERTS is exactly that config, where you can allow particular CA cert file.
Of course you can add this custom CA cert to system CA cert stores. Their locations depend on used OS, e.g.:
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
"/etc/ssl/ca-bundle.pem", // OpenSUSE
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
"/etc/ssl/cert.pem", // Alpine Linux
That should be done by mkcert -install.
My guess is that your node is not using system CA store (env variable NODE_OPTIONS=--use-openssl-ca), so only node's own CA certs (e.g. https://github.com/nodejs/node/blob/v14.0.0/src/node_root_certs.h) are trustworthy for the node.
You have option to use system CA cert store (env variable NODE_OPTIONS=--use-openssl-ca or node CLI parameter --use-openssl-ca) or you can allow your custom CA with env variable NODE_EXTRA_CA_CERTS as you did.
Consider we run the following request:
url="https://secretsub.example.com/secretpath/post.php"
payload = {'secretmessage1' : 'foo','secretmessage2' : 'bar'}
r = requests.post(url,data=payload,verify=True)
The language (python) is just arbitrary but it can be a request on any other language (NodeJs, Java, Php...)
Notice that the url is using https, which means that the connection is secured over SSL. Assuming that I compile this program into binary (.exe), would it be possible for computer to read the payloads through a software in plain text?
I know that packet sniffing software (like WireShark), will only reveal the domain name (example.com) in plain text but not the secrepath nor the payload which will be encrypted.
If I run this code in a web browser however (assuming that it is written in Javascript), I will be able to access the payload and the secretpath in plain text inside the browser console. I assume that the browser only encrypts it only after the request is logged in its console. But if this code is run outside the browser, is there a way a for the computer host to intercept those data in plain text? (some sort of packet sniffing tools)
It is only possible to see the domain name, the payload and path are encrypted and can only be decrypted by the session key as negotiated between the client and webserver. But malware on your computer could be able to access it, for instance by having access to the memory used by the application or by using an insecure programming library with some kind of backdoor.
What the https is doing is initiating a certificate exchange so your client will recieve a certificate from the server that validates the server is who thay say they are and allows the client to encrypt the data through the channell (network).
The first bit - validating the server is who they claim to be - relies on something called a certificate chain. The certificate you recieve will have been signed with an issuers private key. Your client should check this certificate using the issuers public key that you should "already have".
Most operating systems have a list of trusted root certificates. In windows you can see them in the certificate manager.
Without knowing python - #Patrick Mevzek hints that you can ship a root CA (certificate authority) or use the OS one. if your using the OS one - you might need to check its going to be there.
I would expect all this to be automatic - its part of the protocol that you've specified i.e. https. However - you might want to confirm that with a python person.
Most people kind of ignore all this bit - but it is very important. If you do not validate the certificate then you are susceptabe to a "Man in the Middle" attack or DNS spoofing.
Basically I can issue a cert for secretsub.example.com using a couple of tools on my desktop. It will not be signed by a valid CA but if you don't check it then I can either place that cert in a proxy (Man in the Middle) - and when you make your requet my proxy will get the real cert from the real server, establish the HTTP connection but issue my cert to your application. You will then encrypt to my proxy with my cert so I can read your data and then forward it to the real server - and you'll never know! (Many corporate proxies do exactly this to their employees).
Alternatively if I can change your DNS to point the IP to my server I can do pretty much the same - act as a proxy.
Once that's done the data will then be encrypted accross the network.
So - yes HTTPS will encrypt accross the network - but check the cert is valid.
Obviously as someone points out - the data is in the clear on the client computer - just like it is in your browser now.
Stuart
I am New to node.js and express.js. I Created one application with http sever. It's working fine but it is not secure. I want to create https server in that application
var privateKey = fs.readFileSync('privatekey.pem').toString();
var certificate = fs.readFileSync('certificate.pem').toString();
I got a solution: create https server like above syntaxes. How to get privateKey.pem and certificate.pem files?
Please help me!
You will need to generate your key and certificate. For these to work for real users, you will need to get these from a source like LetsEncrypt. However, for development purposes you can create "self signed" certificates and keys for this. With this you will get an "insecure" alert from your browser but since they're yours anyway you can click "proceed anyway".
There are many ways for generating these and many guides around for doing so. You can use this one to get a key and pem file for development purposes, and then follow the LetsEncrypt advice for production certificates.
With those, you will get your key and cert pem files generated and you will be able to read those in with the code you have above.
I've got a client-side cert secured rest endpoint which works when I hit it via curl using a known cert in Linux-land... That is to say, if I console.log(req.connection.getPeerCertificate()), I see a bunch of stuff. Cool.
... however, when one of my teammates tries to hit the same endpoint from a Windows Machine, req.connection.getPeerCertificate() is an empty object, even though they think they're attaching the cert correctly.
What's the best way to tell if they are, indeed, attaching the cert correctly? How should I go about debugging this?
The docs say:
If the peer does not provide a certificate, [getPeerCertificate] returns null or an empty object.
So you already know that the Windows client is not sending a valid certificate because getPeerCertificate() returns an empty object. Check the authorizationError property for additional information about any client certificate errors that may have occurred.
Debug this by finding out why the client isn't sending a certificate. Are you setting requestCert: true in your server options? Is the client properly configured? Is it sending a certificate that can be validated?
The man page did not clearly specify this. But looking at openssl's apps implementations, SSL_CTX_use_PrivateKey* calls are usually made after SSL_CTX_use_certificate_file succeeded. I assume this is mostly used at the server side.
I recently confused the above function with SSL_CTX_load_verify_locations wherein you could specify a CA certificate file and path. It turned out that SSL_CTX_load_verify_locations is the one I needed to verify a server certificate which is signed by a Trusted Authority.
SSL_CTX_use_certificate_file() is used to load the certificates into the CTX object either in PEM or DER format. The certificates can be chained ultimately ending at the root certificates. SSL_CTX_use_certificate_file API loads the first certificate into the CTX context;not the entire chain of certificates. If you prefer that thorough check of certificates is needed then you need to opt for SSL_CTX_use_certificate_chain_file()
http://publib.boulder.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=/com.ibm.ztpf-ztpfdf.doc_put.cur/gtpc2/cpp_ssl_ctx_use_certificate_file.html