We tried to install our Hapis (Nodejs Version 14) Web service on our customer's server. It ran under HTTP for months, but when we went to enable HTTPS with the appropriate paths to the cert and key it fails when the service starts up with:
error:06065064:digital envelope routines:EVP_Decryptfinal_ex:bad decrypt
Their certificate and key are generated using the Venafi online portal. It gave them a crt and key. The crt uses a Signature algorithm: sha256RSA, Signature hash algorithm of sha256, and Thumbprint algorith: sha1.
Also, the private key is a RSA PRIVATE KEY with Proc-Type: 4,ENCRYPTED and DEK-Info: DES-EDE3-CBC.
I am not sure what is going on, because HTTPS works fine on our development servers.
Please help.
The specified error 06065064:digital envelope routines:EVP_Decryptfinal_ex:bad decrypt
occurs in an SSL/TLS connection using OpenSSL (which is what nodejs modules like tls and https actually use) when the privatekey is encrypted (with a passphrase) and the correct passphrase is not provided to decrypt it. The described file format, beginning with a line -----BEGIN RSA PRIVATE KEY-----
followed by lines Proc-Type:
and DEK-Info:
is indeed one of the encrypted formats used by OpenSSL. Specifically this is the encrypted 'traditional' or 'legacy' format; the PKSC8 format added about 2000 but still considered new(!) uses -----BEGIN ENCRYPTED PRIVATE KEY-----
and no 822-style headers, only base64 (of the encrypted structure defined by PKCS8); see ursinely-verbose https://security.stackexchange.com/questions/39279/stronger-encryption-for-ssh-keys/#52564 about OpenSSH's use of OpenSSL, which is basically the same as nodejs's use.
The tls
module and others that build on it including https
ultimately read the key(s) and cert(s) using tls.createSecureContext
which accepts in options
a member passphrase
, or if you need to use multiple keys (and certs) you can provide a passphrase for each key as described in the linked doc.
Alternatively you can avoid the need for a passphrase by converting the key to an unencrypted file, if acceptable under applicable security policies and regulations. (Good policies may prohibit this, but they usually also prohibit getting the privatekey from or providing it to any other system, especially one 'online' somewhere, and your customer is doing the latter.) To retain traditional format do
openssl rsa -in oldfile -out newfile
# and give the passphrase when prompted, or see the man page about -passin
or you can use the 'new' PKCS8 format with
openssl pkey -in oldfile -out newfile
# technically only in release 1.0.0 up, but pretty much everyone is there now
#
# or in all versions back to about 2000
openssl pkcs8 -topk8 -nocrypt -in oldfile -out newfile