Read X509-Certificate to process it - c++

I need to read a X509 certificate in C++. I couldn't find a way to do that with the GnuTLS library. The certificate has to be read in PEM or DER format, so that I can process it twith functions of the GnuTLS library. Is there a pendant to the bio files provided in openssl, which allow me to read the certificate and concert it into processable format?

Actually it is important to generate a variable which contains a tuple of the certificate and the length of the certificate. The certificate can be read using fopen() and fread(). The tuple can be processed with gnutls_x509_crt_import(). That solves the problem for me.

Related

Parse DER x509 in C or C++

I am writting a program in C/C++ on a linux plattofrm to parse X509. Most importantly right now is the public key but I might need other info as well.
I have used the code (in Open SSL) from this post http://www.zedwood.com/article/c-openssl-parse-x509-certificate-pem and it works fine, but my certifcates are in DER format and I therefore need to convert them prior to this (which I can do in the command prompt).
What I need is to do this conversion in code, or other code that does the same on DER certificate directly.
I have tried to replace som components in the code to make it DER instad of PEM but no luck (have been trying to use some id2 commands but I am not even sure if that is correct).
Any help would be apprectiated.
simply use d2i_X509_bio instead of PEM_read_bio_X509 to read the certificate. See how to convert the Certificate String into X509 structure.? and http://www.openssl.org/docs/crypto/d2i_X509.html

cryptoapi and openssl

I'm trying to encrypt and sign a file with cryptoapi with some X.509 certificates. I want to verify and decrypt this file with openssl.
On windows I think I need to use the CryptSignAndEncryptMessage function to encrypt and sign data. I used this example from MSDN to create a signed and encrypted message.
How can I decrypt/verify this file using openssl? I removed the first 4 bytes from the message since it contained the length of the message (from the windows blob).
When I call openssl -asn1parse I get some output that indicates it to be parsable by openssl.
When trying to verify the signature with openssl I recieve an error:
openssl rsautl -verify -inkey AlonsoCert.pem -keyform pem -certin -in sandvout-without-4byte.txt
RSA operation error
3073579208:error:0406706C:rsa routines:RSA_EAY_PUBLIC_DECRYPT:data greater than mod len:rsa_eay.c:680:
CryptSignAndEncrypt message seems to use RC4 cipher with empty ASN.1 parameters field and, looking at OpenSSL sources, openssl chokes on try to generate IV (which is not needed for RC4).
Try to use other cipher (AES for example) in CryptAndSignMessage.
Anyway, RC4 is very old, insecure, and obsolete.
Your ASN.1 dump information shows you've created a PKCS#7 CMS output from your CryptoAPI code. As a result you cannot use the basic OpenSSL decryption and verification methods.
Instead, use the cms mode:
openssl cms -decrypt -inform DER -in sandvout-without-4byte.txt
-out decrypted.bin -recip testkey.pfx
(Note: I've not used this mode before, so I think the syntax I've suggested is correct. Either way, this should hopefully be the step in the right direction that solves this.)
Try using openssl smime to verify and/or decrypt. The syntax is fairly straight-forward but you can find the information here: http://www.openssl.org/docs/apps/smime.html

Is a X509 certificate in DER format ASN1 encoded?

I'm using OpenSSl to encrypt and decrypt files based on CMS/SMIME. Normally I load certificates with rcert = PEM_read_bio_X509(tbio, NULL, 0, NULL); but this is only for PEM formatted files I guess. I haven't found any der.h header or something similar.
So is there a way in OpenSSL to load DER formatted certificates? I've found the load function for ASN1 format which uses OpenSSL intern.
if (format == FORMAT_ASN1)
x=d2i_X509_bio(cert,NULL);
But can that be used for DER which is binary?
DER is indeed encoded using ASN.1, and the d2i_*() family of functions is the way to load a DER file.

Converting between Windows CryptoAPI and OpenSSL x509 formats

I have a CERT_CONTEXT structure which I've extracted from a smart card on Windows via the CryptoAPI. I need to convert this structure into a DER encoded byte array which is consistent with OpenSSL. The closest match I've got so far is via CryptEncodeObject using X509_ASN_ENCODING and the X509_CERT_TO_BE_SIGNED modifier which takes the CERT_INFO structure as input.
The problem is that it doesn't match with the output produced by the OpenSSL i2d_X509 function. Using a 2048 bit x509 certificate as input, OpenSSL produces 1789 bytes of encoded output whilst the Windows CryptoAPI produces 1638 bytes of encoded output.
The only option left that I can see is to create an X509 cert on the fly using the values from the CERT_CONTEXT structure and the encode the resulting object directly with the i2d_X509 function. The only problem with this is that I can't extract the private key from the smart card, so this may cause problems with the x509 cert creation routines.
If anyone can provide any insight/advice/tips into these matters, I'd be much obliged.
DER encoded certificate can be obtained from (ctx->pbCertEncoded, ctx->cbCertEncoded) buffer where ctx is a PCCERT_CONTEXT object. Still you won't be able to recover the private key.

CertCreateCertificateContext returns ASN1 bad tag value met

I'm loading a .p7b certificate file into memory and then calling CertCreateCertificateContext on it, but it fails with the error "ASN1 bad tag value met.".
The call look like this:
m_hContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pbCertEncoded, dwCertEncodedLen);
This returns NULL and GetLastError() returns the error mentioned above.
I created the certificate file by dragging a certificate out of the settings in IE, which then does an automatic export to a file.
What am I doing wrong?
Thanks!
Try to open your certificate by some asn.1 editor.
Probably your certificate has been exported incorrectly or size of the certificate you pass to the api is wrong... Rather the second one option (incorrect cert construction or passing).
I found here the info that the encoding you try to use is not fully supported (see possible error values).
You have to use CertOpenStore() instead:
HCERTSTORE hCertStore = CertOpenStore(
CERT_STORE_PROV_FILENAME,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
NULL,
CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG,
pszFilePath));
CertCreateCertificateContext() supports one certificate only, whereas PKCS #7 file can contain many.
Quote from MSDN:
CERT_STORE_PROV_FILENAME
Initializes the store with certificates, CRLs, and CTLs from a file. The provider opens the file and first attempts to read the file as a serialized store, then as a PKCS #7 signed message, and finally as a single encoded certificate.
After the certificate store is open, you can use CertEnumCertificatesInStore() to retrieve certificate context of individual certificates from store.
Make sure the certificate is in binary format.
I had similar issue when the certificate was in "Base-64 encoded X.509".
It was fixed when i used the same certificate in "DER encoded binary X.509"
You can do this easily on windows by manually importing into cert store and then exporting using the desired format.
Certificate can then be used to be installed on other machines using winapi functions.