We are using EJBCA web service pkcs12req to generate PKCS#12 keystore in an C# application, which is afterwards saved as a p12 file.
After that we need to import p12 file to a smart card providing pin and password programmatically.
Problem is, when we try to load p12 file using an external library, we are getting some errors.
Also, when we try to verify p12 file using OpenSSL command:
pkcs12 -info -nodes -in <path-to-p12-file>
we get the following error:
39512:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:.\crypto\asn1\tasn_dec.c:1316:
39512:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:380:Type=PKCS12
Are we doing the right thing?
Can the generated PKCS#12 keystore be stored as p12 file without any further actions?
Related
I have a TLS certificate received from a public CA that is in pem format without the intermediate certs included. I need the certificate in PFX format with intermediate certs in Azure KeyVault to use with an Application Gateway.
I am able to successfully add the intermediate certs and convert to PFX format with the following:
$apiCertSecret | openssl pkcs12 -export -nodes -out /tmp/cert.pfx -CAfile /tmp/certchain.pem -chain `
-macalg sha256 -certpbe aes-256-cbc -keypbe aes-256-cbc
Where $apiCertSecret is the raw text of the original cert and /tmp/certchain.pem is the root and intermediate cert in PEM format.
The resulting PFX cert checks out AFAICT as valid with both certutil and openssl. Both certutil cert.pfx, run on Windows, and openssl pkcs12 -info -nokeys -in /tmp/cert.pfx, run in WSL, run without error and show all the intermediate certs.
When I take the cert.pfx file and upload it to Azure KeyVault via the portal or via Import-AzKeyVaultCertificate, I end up with an unusable cert. If I reference it from KeyVault in the Application Gateway configuration, I get an unrecognized name error when connecting to that listener. This is the full error from using openssl s_client -connect to test:
error:0A000458:SSL routines:ssl3_read_bytes:tlsv1 unrecognized name:../ssl/record/rec_layer_s3.c:1584:SSL alert number 112
If I retrieve the secret from KeyVault with Get-AzKeyVaultSecret -AsPlainText and pipe it to | openssl pkcs12 -info -nokeys I get the following error:
140606285837632:error:0D0680A8:asn1 encoding routines:asn1_check_tlen:wrong tag:../crypto/asn1/tasn_dec.c:1149:
140606285837632:error:0D07803A:asn1 encoding routines:asn1_item_embed_d2i:nested asn1 error:../crypto/asn1/tasn_dec.c:309:Type=PKCS12
Importing this same cert directly into the Application Gateway works without issue. It also imports into the Windows cert store without issue although I haven't attempted to use it on a site there. I am looking to complete the automation of a cert upgrade, but I'm at a loss for what else to try. I would prefer to reference the cert from Azure KeyVault so the Application Gateway will automatically pick up changes, but right now that appears to be the issue.
My questions.
Are there any other commands I should use to inspect the certificate I have that might shed a little more light on the issue?
Is there another way I should attempt to upload the certificate to Azure KeyVault that would avoid the "corruption"?
Any chance someone has seen this as a known issue in Azure KeyVault?
In case it matters, the version of openssl in use is OpenSSL 1.1.1f 31 Mar 2020
I have openssl installed, and my goal is to convert my CER file to .CRT for an SSL update requirement. I keep running into the error (pasted below)
The code I am using in the console is:
openssl x509 -inform PEM -in Downloads\certificate.cer -out certificate.crt
Error:
C220000:error:80000002:system library:file_open:No such file or directory:providers\implementations\storemgmt\file_store.c:269:calling stat( Downloads\certificate.cer)
AC220000:error:16000069:STORE routines:ossl_store_get0_loader_int:unregistered scheme:crypto\store\store_register.c:237:scheme= C
AC220000:error:1608010C:STORE routines:inner_loader_fetch:unsupported:crypto\store\store_meth.c:359:No store loader found. For standard store loaders you need at least one of the default or base providers available. Did you forget to load them? Info: Global default library context, Scheme ( C : 0), Properties ()
Unable to load certificate
I have all the required files to import to my apache tomcat, that is:
the Certificate Request file (CSR file)
the RSA PRIVATE KEY file
the certificates (root, intermediates and Entity/Domain) that was sent to me by the Certificate Authority.
Now i need to import them to my apache tomcat server.
My question is, given that i havent created any key store to my server (the CSR and private key were sent to me, i didnt created them with e.g. keytool), what should be the next steps? Should i have to create a new keystore through keytool -genkey command (which alias?) ?
And if so, which of the files above should i import? As far as i can see the keytool command doesnt support to import an existing CSR.
The extension .crt is often but not always used for certificates in PEM format. First, set aside the CSR; you won't use it. Look at the contents of the privatekey file and each certificate file; do they each have (usually begin with) a line in the format -----BEGIN {one or more words}----- then several lines of base64 and then a similar END line? If so those are PEM files and the content you need is one privatekey and several certs, exactly as you listed. See also (cross) https://crypto.stackexchange.com/questions/43697/what-is-the-difference-between-pem-csr-key-and-crt and https://security.stackexchange.com/questions/183072/pem-cer-crt-p12-what-is-it-all-about .
As noted in the Q Piotr linked, modern Tomcat (8.5 and up) can directly use PEM files for privatekey and cert(s). Older Tomcats with the 'native' SSL option (aka APR, Apache Portable Runtime, which wraps OpenSSL) also do this.
To use PEM data in older Tomcat using Java SSL (JSSE), or other Java applications, see
Convert a CERT/PEM certificate to a PFX certificate
Importing the private-key/public-certificate pair in the Java KeyStore
How can I set up a letsencrypt SSL certificate and use it in a Spring Boot application?
Converting pem with multiple certificates to java keystore
Converting PEM Certificate for use in JAVA Spring Framework
Converting PEM to PKCS12 and import to Java Keystore
Note PFX is the same thing as PKCS12, and while in olden days it was often necessary to convert to PKCS12 using openssl pkcs12 -export and then to JKS using keytool -importkeystore, Java versions since 2017 should accept PKCS12 as a keystore and in fact j9 up make it the default for newly created keystores.
I've been using a certificate that's stored on the server in a myserver.pfx file.
However, behavior is not the same in all browsers and some complain on account of, I think, a missing 'intermediate' certificate.
I've downloaded the intermediate certificate from Gandi: GandiStandardSSLCA.pem
Now, my question is, how can I add that intermediate certificate into the pfx file?
Although the server is windows, I'm trying to use openssl on a linux machine to manipulate the certificates, just because that's where I have openssl available. I'm assuming this doesn't matter.
One thing I've tried, is to use openssl to export myserver.pfx to myserver.pem, a text file. Then, with a text editor, I've added the text of GandiStandardSSLCA.pem to myserver.pem in hopes of then converting back to pfx format. However, I couldn't get openssl to do that conversion back to pfx.
Is this possible? If so, at the text editing stage, does it matter if the intermediate certificate text goes at the beginning or the end? Also, would I need to manufacture 'Bag Attributes' somehow?
Or, is the whole operation done in one line with openssl?
The .pfx file can be prepared by exporting the intermediate certificate .pem file with the below command example.
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile more.crt
Reference:
https://www.ssl.com/how-to/create-a-pfx-p12-certificate-file-using-openssl/
I’m using the below snipped for setting the certificate and key for client authentication.
curl_easy_setopt(curl,CURLOPT_SSLCERT,"clientCert.pem");
curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD,"changeit");
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
curl_easy_setopt(curl,CURLOPT_SSLKEY,"privateKey.pem");
curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD,"changeit");
curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,"PEM");
The certificate doesn’t have a password, I don’t know why on earth the option SSLCERTPASSWD exists, I just provided a dummy value.
When I run the program on Linux I get an error code of 58 and an error message
unable to set private key file: 'privateKey.pem' type PEM
On Windows however I get
unable to use client certificate (no key found or wrong pass phrase?)
It seems to suggest the certificate and the key don’t match but I don’t know how. I have extracted both the cert and the key from a p12 file using openssl commands.
The command I used to extract the key is
openssl.exe pkcs12 -in client.p12 -nocerts -out privateKey.pem
and the command used to extract the cert is
openssl.exe pkcs12 -in client.p12 -nokeys -out clientCert.pem
The p12 file has been successfully used in a browser to access the client authentication url.
Please help before I shoot myself.
Edit:
Here is proof that the private key and the certificate correspond to each other:
[debugbld#nagara ~/curlm]$ openssl x509 -noout -modulus -in clientCert.pem | openssl md5
d7207cf82b771251471672dd54c59927
[debugbld#nagara ~/curlm]$ openssl rsa -noout -modulus -in privateKey.pem | openssl md5
Enter pass phrase for privateKey.pem:
d7207cf82b771251471672dd54c59927
So why can’t it work?
Using the command line curl, I've got the same error using a .pem file that was also obtained with openssl from a p12 file, The p12 was also able to working properly doing client authentication when imported in a browser. Just like you described, I think.
My problem was caused because the .pem file was not listing the certificates in the proper order: seems that each certificate in the file has to be followed by its issuer certificate. I edited the file and changed the order of the sections and curl was happy.
For the record, my original .p12 file was obtained by backing up a certificate from Firefox.
Also note that in my case, I was not getting prompted for the password and was getting the
curl: (58) unable to set private key file: 'alice.pem' type PEM
before the password prompt
I was facing similar issues, I found out the problem was related to file permissions of the certificate and private key files. The process running PHP did not have read access to those files.
One thing you can try (and that helped me figuring this out) is to run the following code:
$result=openssl_get_privatekey('file://path/to/private/key.pem','password');
and check if the returned value is not false and there are no errors. I was getting:
file_get_contents(/path/to/private/key.pem): failed to open stream: Permission denied
Thanks Hugh for the thread and raugfer for the openssl hint. The later: both helpful and misleading. ;-)
Actually, I solved the problem by making sure that the path of the key file is correct. And here is why the openssl hint was misleading, dispite helping me to check if my PEM file was ok:
cURL needs the complete path, but without 'file://' prefix. While fopen is happy with a relative path, cURL is not. So, all my tests to open the key file had been successful, while cURL was not.
Btw.:
curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD,"changeit");
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,"PEM");
are not needed, as the password is only used to decrypt the private key and PEM is the default.