How to send crt file in api request using npm request-promise - security

I am new to the certificate file concept.
I have been given a CRT file along with passphrase to send in an API.
As I am using request-promise package from npm. To add certificates we can do this.
(Note: I have been given only one file that is abc.crt).
const options = {
url: 'https://api.some-server.com/',
agentOptions: {
cert: fs.readFileSync(certFile),
key: fs.readFileSync(keyFile),
// Or use `pfx` property replacing `cert` and `key` when using private key, certificate and CA certs in PFX or PKCS12 format:
// pfx: fs.readFileSync(pfxFilePath),
passphrase: 'password',
securityOptions: 'SSL_OP_NO_SSLv3'
}
};
By doing this i am getting this error
Error: RequestError: Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
I have a few questions related to this.
1) What is use of CRT files?
2) How will I get the .key file from the CRT file?

Related

Node.js HTTPS Server Let's Encrypt Certificate Files Location on Windows Server

I have a windows server 2012 and wanted to run a node.js web server over https. I have SSL certificate from let's encrypt.
My server code is here:
const https = require("https"),
fs = require("fs");
const options = {
key: // not have,
cert: "C:\\ProgramData\\win-acme\\acme-v02.api.letsencrypt.org\\Certificates\\ichangedthispart-csr.pem"
};
const express = require('express')
const qs=require('qs')
const app = express()
const port = 3000
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
https.createServer(options, app).listen(8080);
When I runned with just cert option there is
node:_tls_common:155
context.setCert(cert);
^
Error: error:0909006C:PEM routines:get_name:no start line
at setCerts (node:_tls_common:155:13)
at Object.createSecureContext (node:_tls_common:210:7)
at Server.setSecureContext (node:_tls_wrap:1336:27)
at Server (node:_tls_wrap:1191:8)
at new Server (node:https:67:14)
at Object.createServer (node:https:92:10)
at Object.<anonymous> (C:\inetpub\wwwroot\app\server.js:42:7)
at Module._compile (node:internal/modules/cjs/loader:1108:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
at Module.load (node:internal/modules/cjs/loader:973:32) {
library: 'PEM routines',
function: 'get_name',
reason: 'no start line',
code: 'ERR_OSSL_PEM_NO_START_LINE'
}
I don't have the pem file for 'key' inside win-acme directory. In some examples also another pem file for 'ca'; i don't have that file too.
Could these other .pem files be generated with something using this single pem file on windows server? Do I need any other information? There are some examples using with openssl but it seems different.
I intented to have the key.pem file from let's encrypt certification. Now I solved the issue.
First I was using win-acme tool to generate certificate on windows server. To get key.pem file from certificate generation process, you need to change the PrivateKeyExportable to true in settings.json file of win-acme.
Secondly, you need to generate or renew certificate using win-acme with the PEM encoded files (Apache, nginx, etc.) for storing option. Pick the "How would you like to store the certificate?" question as PEM encoded files (Apache, nginx, etc.) option.
Finally you will have both key.pem and crt.pem files at the export directory. Then use them for the https options object as:
const options = {
key: fs.readFileSync('yourhomesite.com-key.pem', 'utf8'),
cert: fs.readFileSync('yourhomesite.com-crt.pem', 'utf8')
};

ERR_SSL_VERSION_OR_CIPHER_MISMATCH in node js

I recently purchased a personal ssl certificate from Positive ssl. After i got everything sorted out with activating it and the validation, I was finally able to download the certificate files.
The files i got were:
www.niknet.ddns.net.ca-bundle
www.niknet.ddns.net.crt
www.niknet.ddns.net.p7b
Before I only used .key and .crt
and it worked great but now i am using the .ca-bundle and the .crt file
this is the code i use to include those files into the ssl library in node js
var httpPort = process.env.PORT || 80;
var httpsPort = process.env.PORT || 443;
var server = http.createServer(app).listen(httpPort);
var server = https.createServer({
secureProtocol : 'TLSv1_2_server_method',
ciphers : "AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH",
honorCipherOrder : true,
ca: fs.readFileSync(__dirname + '/niknet_ddns_net.ca-bundle'),
cert: fs.readFileSync(__dirname + '/niknet_ddns_net.crt')
},app).listen(httpsPort);
var io = require('socket.io').listen(server);
but I can't for the life of me get the certificate to work properly.
I just get this error
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
I've been reading other posts and have tried adding their code but nothing works.
I also read somewhere that the ssl or tls library for node.js is outdated and that my certificate could be too new. If that's true, are there any other third-party ssl libraries I could use?
run this command:
openssl req -nodes -new -x509 -keyout server.key -out server.cert
Just remember to set this to localhost:
Common Name (e.g. server FQDN or YOUR name) []: localhost
then
https.createServer({
key: fs.readFileSync('./ssl/server.key'),
cert: fs.readFileSync('./ssl/server.cert')
},app)
ERR_SSL_VERSION_OR_CIPHER_MISMATCH will appear if the added certificate are not indicated properly in the first argument of createServer().
tested key and crt with openssl using bellow command (try in browser https://hostname:8888).. and found the exact cipher missing.
openssl s_server -cert server.crt -key server.key -CAfile octopz.zende.sk.ca-bundle -accept 8888 -www
Then added to the nodejs code.
var server = https.createServer({
key: privateKey,
cert: certificate,
ca: certificateAuthority,
ciphers: [
"ECDHE-RSA-AES128-SHA256",
"DHE-RSA-AES128-SHA256",
"AES128-GCM-SHA256",
"RC4",
"HIGH",
"!MD5",
"!aNULL"
].join(':'),
}, app);
it worked!!
We have lots of dupes of this for other languages, but the closest I can find for nodejs is How to create an HTTPS server in Node.js? which is not specific or ERR_SSL_VERSION_OR_CIPHER_MISMATCH with node v7.9.0 https which is not answered. So:
SSL/TLS server including an HTTPS server needs a privatekey AND certificate/chain (with rare exceptions not applicable here). You can use a CA-issued cert (and chain) instead of a self-created (and usually self-signed) cert, as long as the CA-issued cert is for the same privatekey, but you must still provide the privatekey. You can use cert and key together, or you can combine the cert (and optionally chain) and key into a PKCS12-also-called-PFX file, and use pfx.
In addition to the Q you asked, and arguably offtopic for SO, don't use RC4. It's considered broken cryptographically, though still on average moderately difficult/costly in practice, and most standards for using SSL/TLS/HTTPS prohibit it for several years now, particularly rfc7465.

https error in nodejs?

I have installed SSL certificated on ubutunu.
this is not self generated certificates.
I have implemented code
var sslOptions = {
key: fs.readFileSync('/etc/ssl/private/private.key'),
cert: fs.readFileSync('/etc/ssl/certs/STAR_certs.crt'),
//ca: fs.readFileSync('/etc/ssl/certs/AddTrustExternalCARoot.crt'),
requestCert: true,
rejectUnauthorized: false
};
and i do confirm all above files are present. and STAR_certs.crt is having root permissions.
And i got following error now
Error: error:0906D06C:PEM routines:PEM_read_bio:no start line
at Object.exports.createCredentials (crypto.js:100:17)
at Server (tls.js:1130:28)
at new Server (https.js:35:14)
at Object.exports.createServer (https.js:54:10)
Any idea. I dnt have any pem file
Thanks
You need to check that your private.key and STAR_certs.crt files are in format, supported by OpenSSL (which is PEM). If they are not, you need to convert those files. You will find conversion instructions in other StackOverflow questions and answers ( I don't know in which format your files are now, so I can't direct you to any particular answer).

Nodejs https request UNABLE_TO_GET_ISSUER_CERT_LOCALLY

OS: debian sid
Nodejs: v0.10.38
I have a request to a private service that use authentication:
var https = require('https');
var options = {
host: 'private.service.com',
path: '/accounts/' + '123323' + '/orders',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': 0,
'Authorization': 'Bearer ' + 'asdsdgcvxcvxcv'
}
};
var request = https.request(options, function (res) {
console.log(res);
});
When i run the script, node throws this error:
events.js:72
throw er; // Unhandled 'error' event
^
Error: UNABLE_TO_GET_ISSUER_CERT_LOCALLY
at SecurePair.<anonymous> (tls.js:1381:32)
at SecurePair.emit (events.js:92:17)
at SecurePair.maybeInitFinished (tls.js:980:10)
at CleartextStream.read [as _read] (tls.js:472:13)
at CleartextStream.Readable.read (_stream_readable.js:341:10)
at EncryptedStream.write [as _write] (tls.js:369:25)
at doWrite (_stream_writable.js:226:10)
at writeOrBuffer (_stream_writable.js:216:5)
at EncryptedStream.Writable.write (_stream_writable.js:183:11)
at write (_stream_readable.js:602:24)
The same exact script worked well for months, and i'm sure the authentication is correct. Today is the first time i have this situation.
Which can be the cause for this error?
After some study i found that this is a problem of the server that i'm trying to make the https request to.
Node https cannot find the ssl ISSUER_CERT on the private.service server and so it throw that exception.
The solution i used, since i'm sure i can trust that server, was to add
rejectUnauthorized: false
to the options of the https request, this way node will not throw an exception in case of certificates problem.
Anyway this solution is valid only if you know you can trust the host of your request, otherwise it's probably not the best solution.
There is a reason for SSL. Besides other features, it authenticates that you are really communicating with the server identified by private.service.com hostname. Otherwise your client software can be cheated by a Man-in-the-Middle attack.
First when anyone encounters this issue, they should update system root SSL certificates. In Debian they are contained in ca-certificates apt-get package.
If it doesn't help, the server probably uses an issuer certificate, which is not trusted by default worldwide PKI infrastructure. In this case the client should compare the certificate public key signature with a preshared value. This is known as "certificate pinning".
Specifically to your error, if it worked before, it is possible that the server certificate has expired. The server should renew it. As a temporary solution, you can turn off PKI validation by rejectUnauthorized option. However you should use it together with the pinning approach. In NodeJS, you can get the server certificate fingerprint from res.socket.getPeerCertificate().fingerprint.
After a reasearch this solved the problem:
npm set strict-ssl=false
Hope it helps.
From this GitHub issue, use the following environment variable:
export NODE_EXTRA_CA_CERTS=/path/to/certfile.crt
After this, you can run any of the npm commands and nodejs will trust your extra certificate file.
The .crt file is a file that contains a prefix line, the base64 encoded cert and a suffix line.
If you don't have your root CA cert handy, you can generate the cert file from your URL, with the openssl command:
openssl s_client \
-showcerts \
-servername <host> \
-connect <host>:443 2>/dev/null </dev/null | \
openssl x509
Where <host> is the hostname of the url. For example, using google.com for the host, the output looks something like this:
-----BEGIN CERTIFICATE-----
MIIIIDCCBwigAwIBAgIQI/1aCHwDN94QFUhXJeIwODANBgkqhkiG9w0BAQsFADBU
(42 more lines)
E+Hv1bJSbOMSNCDzqRM3JUzvM6Y=
-----END CERTIFICATE-----
Save that as your .crt file and add its path to the NODE_EXTRA_CA_CERTS environment variable and you're all set.
when I was trying to install npm on Ubuntu 16 i got the same error.
The following command worked for me.
npm config set registry http://registry.npmjs.org/

Install root certificate to Node.js (HTTPS Client)

I would like to connect to an internal corporate server with Node.js as a client via HTTPS.
How do I install my internal root certificate to Node.js, so the certificate validation is successful?
I don't want to disable certificate validation.
I solved the problem.
Use this, it works as charm: https://github.com/coolaj86/node-ssl-root-cas
Create a certificates folder
Place your root certificate there
Load the certificate with the module metnioned above
If you use Sails.js, put the code to config/bootstrap.js
Add an environment variable:
NODE_EXTRA_CA_CERTS=file
When set, the well known "root" CAs (like VeriSign) will be extended with the extra certificates in file. The file should consist of one or more trusted certificates in PEM format. A message will be emitted (once) with process.emitWarning() if the file is missing or malformed, but any errors are otherwise ignored.
Note that neither the well known nor extra certificates are used when the ca options property is explicitly specified for a TLS or HTTPS client or server.
This environment variable is ignored when node runs as setuid root or has Linux file capabilities set.
Hope this help someone:
var https = require('https');
var fs = require('fs');
var https_options = {
key: fs.readFileSync("/path/to/private.key"),
cert: fs.readFileSync("/path/to/your_domain_name.crt"),
ca: [
fs.readFileSync('path/to/CA_root.crt'),
fs.readFileSync('path/to/ca_bundle_certificate.crt')
]
};
Ref: https://cheapsslsecurity.com/blog/how-to-install-ssl-certificate-on-node-js/
And you can use this link to check your cert:
https://www.digicert.com/help/

Resources