Posts Tagged ‘SMIME’

EnvelopedCms decrypt problem

Monday, February 3rd, 2014

.NET’s EnvelopedCms class represents a CMS/PKCS #7 structure for enveloped data. Such data are for example used in S/MIME encrypted messages.

EnvelopedCms class contains several Decrypt method overloads:

  • Decrypt()
  • Decrypt(RecipientInfo)
  • Decrypt(X509Certificate2Collection)
  • Decrypt(RecipientInfo, X509Certificate2Collection)

Each Decrypt method decrypts the contents of the decoded enveloped CMS/PKCS #7 data. Each searches the current user and local machine My stores for the appropriate certificate and private key.

Last two overloads allow passing additional collection of X509 certificates, that should be searched to find matching certificate for decryption.

There are 2 most common errors that can occur while decrypting:

  • “The enveloped-data message does not contain the specified recipient.” – Which means that no matching certificate was found in My stores and in the additional certificate collection.
  • “Cannot find object or property.” – Certificate was found, but there is no private key in it, so it can not be used to decryped the enveloped data.

There are 3 ways of adding certificates to My store, 2 of those don’t import private key:

  • “Personal” tab in CertMgr (does not import private key).
  • MMC “Certificates” snap-in (“My user account”) (does not import private key).
  • Double clicking the pfx file (imports private key).

In many cases data are encrypted using 2 or more certificates (so both sender and receiver are able to decrypt the message)

The problem with all Decrypt methods is that they try to use only the first certificate they find. The matching is based on certificate SN. First, both My stores are search, then extra store (passed certificate collection).

This leads to a problem when, both certificates are in My store, but only one contains a private key.

.NET is going to use the first certificate it finds – if it’s the one without the private key, “Cannot find object or property” exception is going to be thrown.

The only workaround for this problem is to try to decrypt the message for each ReceipientInfo separately. This way we are sure that all certificates will be tried.

Mail.dll .NET secure email component does this automatically, so no additional code is required.

Send encrypted email using S/MIME (AES‑256)

Monday, September 24th, 2012

In many cases it is required to use better that standard encryption algorithms. With Mail.dll it is easy to specify algorithm that is used for encryption. In this article we’ll show how to send S/MIME encrypted and signed email using Mail.dll email component and AES-256 and SHA-512.

If you don’t need to specify encryption algorithm you can lean on default values: send encrypted email using S/MIME.

Encryption algorithm selection is done through Algorithm property of the EncryptionConfiguration class. You can use CommonOids class static properties to retrieve common oids (object identifiers): TrippleDes (3-DES), Aes128, Aes256.

Encryption using MailBuilder

EncryptionConfiguration encryption = new EncryptionConfiguration();
encryption.Algorithm = new Oid(CommonOids.Aes256);
encryption.Certificates.Add(new X509Certificate2(...));
encryption.Certificates.Add(new X509Certificate2(...));

SignatureConfiguration signature = new SignatureConfiguration(
    new X509Certificate2(...));
signature.Algorithm = new Oid(CommonOids.Sha512);

MailBuilder builder = new MailBuilder();
builder.Text = "Encrypted and signed";
builder.EncryptWith(encryption);
builder.SignWith(signature);

IMail mail = builder.Create();

Encryption using fluent interface

EncryptionConfiguration encryption = new EncryptionConfiguration();
encryption.Algorithm = new Oid(CommonOids.Aes256);
encryption.Certificates.Add(new X509Certificate2(...));
encryption.Certificates.Add(new X509Certificate2(...));

SignatureConfiguration signature = new SignatureConfiguration(
    new X509Certificate2(...));
signature.Algorithm = new Oid(CommonOids.Sha512);

IMail mail = Mail.Text("Encrypted")
    .EncryptWith(encryption)
    .SignWith(signature)
    .Create();

Remember to encrypt your emails with both sender’s and receiver’s certificates. This way both parties are able to decrypt such emails.

Sending email using SMTP

Now we can connect to SMTP server and send the email we recently created:

using (Smtp client = new Smtp())
{
    client.Connect("smtp.example.com"); // or ConnectSSL
    client.UseBestLogin("user", "password");
    client.SendMessage(email);
    client.Close();
}

Send signed email using S/MIME (SHA‑512)

Monday, September 24th, 2012

In many cases it is required to use better that standard signing algorithms. With Mail.dll it is easy to specify algorithm that is used for signing. In this article we’ll show how to send S/MIME signed email using Mail.dll email component and specific signature algorithm (SHA-512).

If you don’t need to specify signature algorithm you can lean on default values: send signed email using S/MIME.

Signature algorithm selection is done through Algorithm property of the SignatureConfiguration class. You can use CommonOids class static properties to retrieve common oids (object identifiers): Sha1, Sha256, Sha512.

Signing using fluent interface

IMail mail = Mail.Text("text")
    .From("email@in-the-certificate.com")
    .SignWith(new SignatureConfiguration(new X509Certificate2(...)) 
        { 
            Algorithm = CommonOids.Sha512
        })
    .Create();

Signing using MailBuilder

MailBuilder builder = new MailBuilder();
builder.Text = "text";
builder.From.Add(new MailBox("email@in-the-certificate.com"));
builder.SignWith(new SignatureConfiguration(certificate) 
    { 
        Algorithm = CommonOids.Sha512
    });
IMail mail = builder.Create();

Sending email using SMTP

Now we can connect to SMTP server and send the email we recently created:

using (Smtp client = new Smtp())
{
    client.Connect("smtp.example.com"); // or ConnectSSL
    client.UseBestLogin("user", "password");
    client.SendMessage(email);
    client.Close();
}

Import certificate, private or public keys (PEM, CER, PFX)

Tuesday, November 22nd, 2011

Encrypted private key, RSA private key in PEM file

PEM stands for Privacy Enhanced Mail format. The PEM format is the most common format that Certificate Authorities issue certificates in. PEM certificates usually have extensions such as .pem, .crt, .cer, and .key. They are Base64 encoded ASCII files.

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadEncryptedPrivateKeyFromFile(
   "EncryptedPrivateKey.pem", // "EncryptedRSAPrivateKey.pem"
   "cypher");

This code handles following formats:

PKCS #8 EncryptedPrivateKeyInfo Encrypted Format:

-----BEGIN ENCRYPTED PRIVATE KEY-----
MIICojAcBgoqhkiG9w0BD .....

Private Key (Traditional SSLeay RSAPrivateKey format) Encrypted:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,24A667C253F8A1B9

mKz .....

You can remove the passphrase from the private key using openssl:
openssl rsa -in EncryptedPrivateKey.pem -out PrivateKey.pem

Unencrypted private key in PEM file

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadPrivateKeyFromFile("PrivateKey.pem");

This code handles following formats:

PKCS #8 PrivateKeyInfo Unencrypted:

-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0B ......

Private Key (Traditional SSLeay RSAPrivateKey format) Unencrypted:

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCcHVm .....

Public key in PEM file

PemReader pem = new PemReader();
RSACryptoServiceProvider rsa = pem.ReadPublicKeyFromFile("PublicKey.pem")

This code handles following formats:

Public Key (SubjecPublicKeyInfo):

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEB .....

Certificate/private key in PFX file

X509Certificate2 certificate  = new X509Certificate2(
   "certificate.pfx",
   "",
   X509KeyStorageFlags.PersistKeySet)

if (certificate.HasPrivateKey)
{
  using (var rsa = (RSACryptoServiceProvider)certificate.PrivateKey)
  {
    // ...
  }
}

Certificate in PEM/CER file

Note: The private key is never stored in a .pem/.cer certificate file.

X509Certificate2 certificate = new X509Certificate2("certificate.cer");

-or-

PemReader pem = new PemReader();
X509Certificate2 certificate = pem.ReadCertificateFromFile("certificate.cer");

This code handles following formats:


-----BEGIN CERTIFICATE-----
MIIFsTCCA5mgAwIBAgIKYQ .....

Send signed email receive encrypted

Tuesday, May 24th, 2011

In this article we’ll show how to create test certificates or use existing certificate, for sending signed emails. Our recipients will use the public key information from the signed email to encrypt emails they’ll be sending to us. Finally we’ll show how to decrypt those emails.

Create test certificate

We’ll use makecert.exe tool to create certificate in cer format and pvk2pfx.exe tool to convert it to pfx format:


makecert.exe -pe -r -sv Test_Keys.pvk -n "CN=Alice,E=alice2@testdomain.com" -sky exchange Test.cer


pvk2pfx.exe -pvk Test_Keys.pvk -spc Test.cer -pfx Test.pfx

If you use CER or PEM files you can find more information in this article:
Importing private/public keys or certificates in PEM, CER formats.

Create S/MIME signed email

Now we’ll create a signed message using Mail.dll. It is a simple task we just need to load certifcate from disk and use SignWith method:

X509Certificate2 certificate = new X509Certificate2(
    @"c:\Test.pfx";, 
    "", 
    X509KeyStorageFlags.PersistKeySet);

IMail email = Limilabs.Mail.Fluent.Mail.Text("This is a signed message")
    .Subject("This is a signed message")
    .From("alice2@testdomain.com")
    .To("test@testdomain.com")
    .SignWith(certificate)
    .Create();

Send S/MIME signed email

Now we’ll use Smtp class to connect and authenticate to our SMTP server and send the email message:

using(Smtp smtp = new Smtp())
{
    smtp.Connect("smtp.server.com");  // or ConnectSSL for SSL
    smtp.UseBestLogin("user", "password");
 
    smtp.SendMessage(email);                     
 
    smtp.Close();   
}              

Here you can find more details on sending S/MIME signed email.

S/MIME signed email is received

Here’s how the recipient will see the message. Please note that we are using self-signed certificates and this is why we are seeing this warning message.

Next step for the recipient is to mark received certificate as trusted.

The recipient should then add the certificate to the contact list:

As you can see there is a DigitalID assigned to Alice (email sender):

S/MIME encrypted email reply

Finally recipient replies to the message marking the new message to be encrypted.

Receiving S/MIME encrypted email reply

We’ll use IMAP component to download this message. You can use IMAP or POP3 components to download it.

In fact we can see that it is encrypted (we are showing raw eml variable here):

Now we can decrypt the message using the same certificate, we used for signing. Note that we are adding this certificate to SMIMEConfiguration.Certificates collection:

X509Certificate2 certificate = new X509Certificate2(
    @"c:\Text.pfx", 
    "", 
    X509KeyStorageFlags.PersistKeySet);

using(Imap imap = new Imap())
{
    imap.Connect("imap.testdomain.com");
    imap.UseBestLogin("alice2@testdomain.com", "password");

    var eml = imap.GetMessageByNumber(1);

    MailBuilder builder = new MailBuilder();
    builder.SMIMEConfiguration.Certificates.Add(certificate);
    IMail email = builder.CreateFromEml(eml);

    Console.WriteLine(email.IsEncrypted);
    Console.WriteLine(email.Html);
    Console.WriteLine(email.Text);

    imap.Close();
}

You can also find more information about SMIME and Mail.dll here: