NodeJS 14: Using a SSL CA Bundle - node.js

I'm currently trying to use a CA Bundle with NodeJS 14.0. I've been using Namecheap's article as a guide the implement this feature. I'm currently stuck on a few things:
For the ca parameter for https.createServer(), what file formats are allowed to be passed in?
How do I check that a CA bundle is actually being used?

For the ca parameter for https.createServer(), what file formats are allowed to be passed in?
From NodeJS tls.createSecureContext:
Any string or Buffer can contain multiple PEM CAs concatenated together
Though, in general NodeJS uses PEM format.
How do I check that a CA bundle is actually being used?
You can use a certificate not signed by your CA, e.g. a self-signed certificate.

One point, possibly more subtle than you wanted: nodejs tls.createSecureContext internally calls OpenSSL PEM_read_bio_X509_AUX which actually accepts three PEM formats (or any sequence of those three formats, since nodejs loops). For two of them the base64/64cpl blob contains (exactly) an X.509 certificate, as respecified in rfc7468 sec 5, with either preferred label "CERTIFICATE" or deprecated label "X509 CERTIFICATE". In addition OpenSSL accepts a format of its own with label "TRUSTED CERTIFICATE" where the blob contains an X.509 certificate plus additional (ASN.1) data defined by OpenSSL; see e.g. the man page for d2i_X509_AUX online here. OpenSSL doesn't use this additional data for much, and of course nothing else uses it at all, so it's rare.
And to avoid confusion it might be worth noting that all OpenSSL PEM_read_ routines, including this one, skip any 'comment' data while searching for the PEM data, so actually a file/buffer that contains garbage, then a PEM cert, then more garbage, then another PEM cert, etc. will work the same as if it contained only the PEM certs.

Related

X.509 certificate difference between S/MIME and HTTPS (LetsEncrypt)

Looking at LetsEncrypt FAQ page, they have clearly stated that email encryption and code signing require a different type of certificate and therefore they are not supported by LetsEncrypt.
My understanding is that https and S/MIME both require X.509 certificates. What is the difference between certificates these two technologies require?
Among other things (like the encryption key), an X.509 certificate also specifies what it may be used for. X.509 certificates for HTTPS and S/MIME usage basically have different usages.
The structure of an X.509 certificate is fairly complex. Its possible usage depends on attributes and extensions within the certificate, and require that specific combinations of them with specific values must be present.
For example, an S/MIME certificate, requires a Key Usage attribute with something like Encrypt, Verify, Wrap, Derive, a Key Usage extension that must have the Critical attribute set to Yes and include a Usage attribute with Key Encipherment plus in the Extended Key Usage extension (sic!) it should list the Purpose attribute value Email Protection.
Note that Key Usage extension Data Encipherment is not required, because in S/MIME, the data contents are encrypted by a random symmetric key which then is encrypted with the private key from the certificate. This is called hybrid encryption and it is done for performance and scalability reasons.
The certificate requirements even extend into the certificate chain, meaning that the certificate must be signed by another certificate that has been issued to sign certificates for that usage.
Note that the above example may not be 100% correct, because the subject is so complex, and I don't fully understand every aspect of it myself. I found this quote which I think describes the situation fairly well:
I think a lot of purists would rather have PKI be useless to anyone in
any practical terms than to have it made simple enough to use, but
potentially "flawed". — Chris Zimman
Resources that helped me:
X.509 Style Guide by Peter Gutmann: an attempt to shed light on the relations of attributes and extensions and their interpretations
RFC 4262 - X.509 Certificate Extension for Secure/Multipurpose Internet Mail Extensions (S/MIME) Capabilities

Method to verify a signed archive's X.509 CoT

I am trying to understand the key high level details behind verifying trust when downloading an archive.
This is my understanding of how it could be done:
On the Software Developer side:
Obtain a certificate from a public CA like verisign
Generate a hash of your archive and then encrypt this string using the private key from your certificate, this is the "signature"
Host the archive for download, along with a separate file which contains the public key from your certificate + the signature generated in step 2.
On the (user) client side:
Download and unpack the archive, download the signature + public key file
Decrypt the downloaded signature using the downloaded public key, save this value
Iterate through the public root certificates embedded within your operating system. For each root certificate, decrypt the signature value and compare the result to the result in step 5.
Once a match is found in 6, you have verified that the author's private key descends from the chain of trust of the CA which you found matched in step 6.
This all assumes that the software developer used a CA for which we have an embedded root certificate in our clients OS.
Questions:
Is the above method sound, or am I overlooking key details?
Given a blank slate client that you control, if I wanted to combine the public key + signature + archive into a single file that I could make the client understand and parse, are there any widely supported formats to leverage for organizing this data?
Aside from being a little too specific on Developer (2) (that describes how RSA signatures work, but ECDSA is perfectly well suited to this task) that sounds rather like Authenticode minus some EKU restrictions. This leads me to ask "why not use Authenticode signing?".
The structure I'd consider is the PKCS#7/CMS SignedData format. It can describe multiple signatures from multiple certificates (sign it ECDSA-brainpoolP320t1-SHA-3-512 for anyone who can read it as well as RSA-2048-SHA-2-256 for most of us, and DSA-1024-SHA-1 for anyone whose computer was built in 2001).
For data file you can just use SignedData normally, for executables it's harder since there are semantic portions (so you have to squirrel it away somewhere and use indirect signing).
If you do your signing with .NET, PKCS#7/CMS SignedData is available for both signing and verifying via System.Security.Cryptography.Pkcs.SignedCms (though you probably have to define your own chain trust rules outside of that class).

Why do i have a wrong (sha1) immediate startcom certificate in my chain on azure website?

My immediate certificate on https://paper-shape.com got a weak signature algorithm SHA1: https://www.ssllabs.com/ssltest/analyze.html?d=paper-shape.com
I followed theses instructions. I created my pfx file both per OpenSSL and per certificate export wizard.
The CRT and pem (immediate certificate from startcom) seem to be ok, because the following command shows "Signature Algorithm: sha256WithRSAEncryption" on both (CRT and PEM):
$ openssl x509 -text -in paper-shape.com.crt
Either something went wrong during my pfx creation process or azure website overrules my immediate certificate.
Has anybody an idea?
Check your locally-installed certificates (on Windows, 'certmgr.msc'). You may have an old SHA-1-signed copy of the StartCom intermediate certificate which is still valid (say, to 2017) and being used in preference to that provided by the server.
You can find (and chain) the SHA-256 intermediate certificate for Class-1 in PEM format, here: https://www.startssl.com/certs/class1/sha2/pem/sub.class1.server.sha2.ca.pem
I have been facing this same problem, I was about to pull my hair out when the certificate seemed to be right in some browsers and OS and in others it claimed I was using SHA-1 and even https://shaaaaaaaaaaaaa.com was telling me that I had a SHA-2 signed crt.
So! Here is a huge thread in StartCom forum about this issue: https://forum.startcom.org/viewtopic.php?f=15&t=15929&st=0&sk=t&sd=a
The thing is that the browser is using an Intermediate crt that is SHA-1 signed.
The solution: you need to configurate the Intermadiate crt in your server!
You can see more details here:
https://sslmate.com/blog/post/chrome_cached_sha1_chains

What is the main purpose of openssl's SSL_CTX_use_certificate_file?

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

Inter-convertability of asymmetric key containers (eg: X.509, PGP, OpenSSH)

Are asymmetrical cryptographic keys fundamentally inter-convertible between the major key container formats? For example, can I convert an X.509 key file into a PGP or OpenGPG key file?
And--assuming the answer is yes--is it "security neutral" to keep one key pair in whatever format and convert into whichever container file format is needed for the occasion?
I'm getting a little tired of maintaining so many key pairs for X.509, OpenGPG, and SSH, when they're all RSA at the heart.
Yes and no: yes, the RSA keys embedded into certificates and privkeys are just numbers. You can extract them from the certificate and use them to build keys in other formats. This is commonly done to convert between different certificate formats.
PGP has some support for X.509 for S/MIME, but no ability to use X.509 privkeys verbatim.
SSH has some beta support for directly using X.509 keys and certificates.
You will found how to convert kes between these containers there:
http://sysmic.org/dotclear/index.php?post/2010/03/24/Convert-keys-betweens-GnuPG,-OpenSsh-and-OpenSSL
I'd also have a look at OpenSSL. It has so many different -in and -out functions that will likely be able to convert certs. from one type to the other.
Have a look at http://marc.info/?l=openssl-users&m=105162569405053&w=2

Resources