Archived Forum Post

Index of archived forum posts

Question:

Decrypt s/mime message with PEM certificate

Feb 06 '13 at 11:26

I'm having some trouble decrypting emails with both an encrypted and unencrypted PEM certificate. I generated the PEM certificates from a PFX certificate with openssl as follows:

openssl pkcs12 -in myCert.pfx -out encrypted.pem
openssl pkcs12 -in myCert.pfx -out unencrypted.pem -nodes

I have an email that decrypts fine when I load the PFX certificate it into the CkCrypt2 object with AddPfxSourceData(), however the two approaches I've tried with the PEM certificates have failed. I tried loading the encrypted PEM certificate with AddPfxSourceData(), and I tried creating a CkCert object with LoadFromFile() and adding it to the CkCrypt2 object with AddEncryptCert().

I believe both approaches failed for different reasons:

  1. In a PFX certificate that is loaded with AddPfxSourceData, the entire file is encrypted, not just the private key inside
  2. In the documentation for LoadFromFile() references other file types it can load, and they are all (as I understand it) public keys only, and therefore cannot be used for decryption. Also, it was added to CkCrypt2 with AddEncryptCert(), which doesn't appear to use it for decryption.

I can provide code snippets of my approaches if one of them is supposed to work, but I get the feeling that this might be unsupported.


Answer

I get to answer my own question. You have to create a CkCert from the in-memory PEM file, export it to disk as a PFX file, then read it into the CkCrypt2 object.

CkCrypt2 crypt;    
CkByteData bytes;
bytes.append2(fileBuffer, size);
CkCert cert;
cert.LoadFromBinary(bytes);
cert.ExportToPfxFile(tempFile, password, true);
crypt.AddPfxSourceFile(tempFile, password);

Also, this appears to work no matter what you use for password. You don't even need the password used to encrypt the private key inside the PEM file...


Answer

I'll have to look at your solution in more detail, but I was working on this alternate solution:

I created a new CkCertStore method for loading a PEM that contains multiple certs. The procedure would go like this:

  1. Load the PEM into a CkCertStore (this ignores the private key, but loads the certs)
  2. Load the PEM into a CkPrivateKey (this will only pick out the private key and ignore the certs)
  3. Find the desired CkCert from the CkCertStore.
  4. Load the private key into the CkCert.
  5. Call crypt.SetDecryptCert passing the CkCert object.

Here is an example (with no error checking)

    CkCertStore certStore;

bool success = certStore.LoadPemFile("test.pem");

CkPrivateKey privKey;
success = privKey.LoadEncryptedPemFile("test.pem","test");

CkCert \*cert = certStore.FindCertBySubjectCN("my_cert_subject");

success = cert->SetPrivateKey(privKey);

CkCrypt2 crypt;
// ...

crypt.SetDecryptCert(*cert);

delete cert;

If you'd like a new build with this functionality, please let me know what operating system, and if Windows, what version of VC++. (also if it's 32-bit or 64-bit)