I am quite new to PKI and is somewhat confused with all the standards and algorithms involved.
We have a small specification of how the mail messages must be encrypted and signed (some names are replaced with text inside <>):
The security mechanism for controlling <sending party> access is built around the IDA PKI; digital certificates for all <sending party> mailboxes must be submitted to the <receiving party> before they can submit any transaction to the <receiving party>. In addition, <sending party> must have been sent digital certificates from the <receiving party> to enable the <sending party> to accept any transaction returned from the <receiving party>. For all incoming transaction requests, digital signatures attached to the transactions will be verified using the submitting authority’s certificate. The <receiving party> will only process transactions with valid digital signatures. The certificate will be a X.509 v3 certificate, sourced from the IDA PKI and currently supplied by <SomeCompany> until <YearInThePast>. The certificate security level will be Class 2. The private key and certificate will be saved in a PKCS#12 file (also known as PFX). Each <sending party> will be responsible for the physical protection of this file. Each <sending party> will be responsible for the administration and management of their certificates.
Secure Messaging will be based on S/MIME v2.
IDA PKI can only support RSA and for <TheReceivingSystem> the key length must be 1024.
The symmetric algorithm to be used will be 3DES with a key length of 168.
The hash algorithm to be used will be SHA-1.
With regard to the relative order of signature and encryption, the <receiving party> will only accept an email with a file attachment that has been encrypted then signed.
Incoming transactions that are not encrypted to the above specifications will be rejected by the <receiving party>.
We have been asked to re-implement an already working system (developed by us), but in the old system we use a third party package for encrypting, signing and sending the e-mails which do not have details about. It’s a blackbox for us. Now we want to do it ourselves using your components.
But it looks like the MailMan will sign and then encrypt. And I’m not sure if it will use the above properties for encryption and signing.
Can I instead use the Crypt2 class to encrypt and sign the attachment and then add it as bytes?
I have some certificates, but I’m not quite sure which certificates I should use when doing the encryption and signing:
2 and 4 are in use when receiving files. We have received a mail message coming from the <receiving party> which we are able to decrypt using the same set of certificates, just using your MailMan component and use the certificates which are installed on the computer. These mails have this:
Content-Type:application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m
I would think that the outgoing messages should looks similar.
Given the scenario, how should I encrypt and sign the mails? Or is it just the attachments which are encrypted and signed?
There are a lot of examples on your web site, but it’s hard for me to understand which ones to look at. Can you tell me which ones apply to me?
It should be easy to accomplish using Chilkat.
I'll begin with simple answers that may be sufficient, and if not, then you can ask for more details.
1) You shouldn't need the Crypt2 class.
2) When sending a signed + encrypted email, the typical order (used by Mozilla Thunderbird as an example) is to sign first and then encrypt. (Technically, a receiver should be able to handle either.) The Chilkat MailMan conforms to what is most typical -- it signs first and then encrypts. This is the opposite of what you need. To solve the problem, I would recommend using Chilkat Mime to build the encrypted/signed email. You can create the email using the Chilkat.Email object, then call Chilkat.Email.GetMimeObject to get the email as a Chilkat.Mime object. Using the Chilkat.Mime methods, you can encrypt and then sign it. The signed + encrypted email can be sent by calling Chilkat.MailMan.SendMime, passing the MIME content returned by Chilkat.Mime.GetMime.
3) Encrypt a Chilkat.Mime object by calling the Encrypt method. You'll need to pass a Chilkat.Cert object to the Encrypt method. The certificate used for encryption is the cert of the receiver. You only need the public key for encryption. Therefore, the cert used for encryption probably won't be in a .p12 (.pfx) because no private key is required. You'll likely have the cert as a .cer, .pem, etc. The certificate file can be loaded into a Chilkat.Cert object via the Cert.LoadFromFile method, which automatically handles most formats. (After calling Mime.Encrypt, you can call Mime.GetMime and you'll see that the MIME returned is encrypted.)
4) Sign a Chilkat.Mime object by calling either Mime.AddDetachedSignature, or Mime.ConvertToSigned, depending on whether you want an opaque signature or not. Both methods accept a Chilkat.Cert argument. In this case, you'll need to load the Cert from a .p12 (.pfx) because signing requires a private key. You'll add the signature to the Mime object after calling Encrypt.
5) If on a Windows platform where the certs are pre-installed, there are Chilkat.Cert methods for loading the Cert object from the Windows registry-based certificate stores. See the online reference docs for the various methods for the various "LoadBy*" methods.
6) After encrypting and signing the Mime object, pass the encrypted/signed MIME to MailMan.SendMime to send the encrypted/signed email. (You get the encrypted/signed email by calling Mime.GetMime)
The first impression is very good. I get an e-mail which looks very similar to the one we receive. Now we need to test it with a real e-mail with a real recipient.
The short no-check-for-error-code looks like this:
var encryptCert = new Cert(); encryptCert.LoadFromFile(@"my.cer"); var signCert = new Cert(); signCert.LoadPfxFile(@"my.pfx", "password")); var mime = EmailCreatedBeforeThisExampleCode.GetMimeObject(); mime.Pkcs7CryptAlg = "des"; mime.Pkcs7KeyLength = 168; mime.Encrypt(encryptCert); mime.SigningHashAlg = "sha-1"; mime.ConvertToSigned(signCert); var mailman = new MailMan(); mailman.SmtpHost = "mailserver"; mailman.SendMime("firstname.lastname@example.org", "email@example.com", mime.GetMime());