More .NET components

S/MIME - secure mail

The sample code in this section uses our certificates and certificate store API.
If you are new to X509 certificates and public key cryptography, check out our introduction.

Signature algorithms #

Rebex S/MIME library supports following signature algorithms:

  • RSA with MD4/MD5/SHA-1/SHA-256/SHA-384/SHA-512
  • DSA with SHA-1

and following signature padding schemes:

  • Public-Key Cryptography Standards (PKCS) #1 v1.5
  • Probabilistic Signature Scheme (PSS)

Signing mail messages #

To sign an e-mail message, you need a suitable signer certificate and a corresponding private key. Please note that the private key is only needed for signing, not for validating the signature.

The following code shows how to sign a mail message using a certificate with private key loaded from a .PFX/.P12 file:

CSharp

// create mail
var mail = new Rebex.Mail.MailMessage();
// fill some fields
// ...

// prepare certificate for signing
//  - Certificate with private key is necessary for signing
Certificate signer = Certificate.LoadPfx(@"C:\MyData\certificate.pfx", "password");

// sign the mail
mail.Sign(signer);

VisualBasic

' create mail
Dim mail = New Rebex.Mail.MailMessage()
' fill some fields
' ...

' prepare certificate for signing
'  - Certificate with private key is necessary for signing
Dim signer As Certificate = Certificate.LoadPfx("C:\MyData\certificate.pfx", "password")

' sign the mail
mail.Sign(signer)

Signing using RSA with PSS (RSASSA-PSS) #

To sign an e-mail message using RSASSA-PSS padding scheme, use MailSignatureParameters and specify MailSignaturePaddingScheme.Pss for padding scheme:

CSharp

// create mail
var mail = new Rebex.Mail.MailMessage();
// fill some fields
// ...

// prepare certificate for signing
//  - Certificate with private key is necessary for signing
Certificate signer = Certificate.LoadPfx(@"C:\MyData\certificate.pfx", "password");

// define signing parameters
var parameters = new MailSignatureParameters()
{
     PaddingScheme = MailSignaturePaddingScheme.Pss,
     HashAlgorithm = MailHashingAlgorithm.SHA256,
};

// sign the mail
mail.Sign(parameters, signer);

VisualBasic

' create mail
Dim mail = New Rebex.Mail.MailMessage()
' fill some fields
' ...

' prepare certificate for signing
'  - Certificate with private key is necessary for signing
Dim signer As Certificate = Certificate.LoadPfx("C:\MyData\certificate.pfx", "password")

' define signing parameters
Dim parameters As New MailSignatureParameters()
With parameters
    .PaddingScheme = MailSignaturePaddingScheme.Pss
    .HashAlgorithm = MailHashingAlgorithm.SHA256
End With

' sign the mail
mail.Sign(parameters, signer)

Validating signature #

To validate a mail message signature, you only need access to the signer's certificate. No private key is needed.

Signer certificate is usually embedded inside the S/MIME message itself. If it's not, MailMessage tries locating it in the current user's certificate store).

In both cases, you only have to call the ValidateSignature method:

CSharp

// load a mail
var mail = new Rebex.Mail.MailMessage();
mail.Load(@"C:\MyData\mail.eml");

// validate the signature if the message is signed
if (mail.IsSigned)
{
    MailSignatureValidity result = mail.ValidateSignature();
    if (result.Valid)
        Console.WriteLine("The message is signed and the signature is valid.");
    else
        Console.WriteLine("Signature of the message is not valid ({0}).", result.Status);
}
else
{
    Console.WriteLine("The message is not signed.");
}

VisualBasic

' load a mail
Dim mail = New Rebex.Mail.MailMessage()
mail.Load("C:\MyData\mail.eml")

' validate the signature if the message is signed
If mail.IsSigned Then
    Dim result As MailSignatureValidity = mail.ValidateSignature()
    If result.Valid Then
        Console.WriteLine("The message is signed and the signature is valid.")
    Else
        Console.WriteLine("Signature of the message is not valid ({0}).", result.Status)
    End If
Else
    Console.WriteLine("The message is not signed.")
End If

Encryption algorithms #

Rebex S/MIME library supports following encryption algorithms:

  • AES-128, AES-192, AES-256
  • 3DES
  • DES (intended for interoperability with legacy systems)
  • RC2 (intended for interoperability with legacy systems)

and following encryption padding schemes:

  • Public-Key Cryptography Standards (PKCS) #1 v1.5
  • Optimal Asymmetric Encryption Padding (OAEP)

Encrypting mail messages #

Encrypting a message with a certificate produces a message that can only be decrypted by the owner of the certificate's private key. It is possible to use multiple certificates for encryption - any one of them can decrypt the message.

Please note that only the message body is encrypted - everyone can still read the message headers such as From, To, Date or Subject.

Usually, the sender encrypts the message using his certificate in addition to the recipients certificate. This makes it possible for both the sender and the recipient (but no one else) do decrypt the message later.

The Following code shows how to encrypt a mail message using a recipient and sender certificates:

CSharp

// create mail
var mail = new Rebex.Mail.MailMessage();
// fill some fields
// ...

// load receiver's certificate
//  - For encryption, receiver's public key is necessary
Certificate recipient = Certificate.LoadDer(@"C:\MyData\ReceiverCertificate.der");

// load sender's (my) certificate
//  - For encryption, only the public key is necessary,
//    however, loading certificate with private key e.g. PFX is also possible
Certificate sender = Certificate.LoadDer(@"C:\MyData\MyCertificate.der");

// encrypt the message using both receiver's and sender's certificates
//  - It allows the sender to decrypt the message later
//  - If the message is encrypted using the receiver's certificate only,
//    only the recipient will be able to decrypt the message
mail.Encrypt(recipient, sender);

VisualBasic

' create mail
Dim mail = New Rebex.Mail.MailMessage()
' fill some fields
' ...

' load receiver's certificate
'  - For encryption, receiver's public key is necessary
Dim recipient As Certificate = Certificate.LoadDer("C:\MyData\ReceiverCertificate.der")

' load sender's (my) certificate
'  - For encryption, only the public key is necessary,
'    however, loading certificate with private key e.g. PFX is also possible
Dim sender As Certificate = Certificate.LoadDer("C:\MyData\MyCertificate.der")

' encrypt the message using both receiver's and sender's certificates
'  - It allows the sender to decrypt the message later
'  - If the message is encrypted using the receiver's certificate only,
'    only the recipient will be able to decrypt the message
mail.Encrypt(recipient, sender)

Encrypting using RSA with OAEP (RSAES-OAEP) #

To encrypt an e-mail message using RSAES-OAEP padding scheme, use MailEncryptionParameters and specify MailEncryptionPaddingScheme.Oaep for padding scheme:

CSharp

// create mail
var mail = new Rebex.Mail.MailMessage();
// fill some fields
// ...

// load receiver's certificate
//  - For encryption, receiver's public key is necessary
Certificate recipient = Certificate.LoadDer(@"C:\MyData\ReceiverCertificate.der");

// load sender's (my) certificate
//  - For encryption, only the public key is necessary,
//    however, loading certificate with private key e.g. PFX is also possible
Certificate sender = Certificate.LoadDer(@"C:\MyData\MyCertificate.der");

// define encryption parameters
var parameters = new MailEncryptionParameters()
{
    EncryptionAlgorithm = MailEncryptionAlgorithm.AES256,
    PaddingScheme = MailEncryptionPaddingScheme.Oaep,
    HashAlgorithm = MailHashingAlgorithm.SHA256,
};

// encrypt the message using both receiver's and sender's certificates
//  - It allows the sender to decrypt the message later
//  - If the message is encrypted using the receiver's certificate only,
//    only the recipient will be able to decrypt the message
mail.Encrypt(parameters, recipient, sender);

VisualBasic

' create mail
Dim mail = New Rebex.Mail.MailMessage()
' fill some fields
' ...

' load receiver's certificate
'  - For encryption, receiver's public key is necessary
Dim recipient As Certificate = Certificate.LoadDer("C:\MyData\ReceiverCertificate.der")

' load sender's (my) certificate
'  - For encryption, only the public key is necessary,
'    however, loading certificate with private key e.g. PFX is also possible
Dim sender As Certificate = Certificate.LoadDer("C:\MyData\MyCertificate.der")

' define encryption parameters
Dim parameters As New MailEncryptionParameters()
With parameters
    .EncryptionAlgorithm = MailEncryptionAlgorithm.AES256
    .PaddingScheme = MailEncryptionPaddingScheme.Oaep
    .HashAlgorithm = MailHashingAlgorithm.SHA256
End With

' encrypt the message using both receiver's and sender's certificates
'  - It allows the sender to decrypt the message later
'  - If the message is encrypted using the receiver's certificate only,
'    only the recipient will be able to decrypt the message
mail.Encrypt(parameters, recipient, sender)

Decrypting mail messages #

To decrypt a mail message, you must have access to the private key corresponding to one of the certificates used for message encryption. By default, MailMessage tries locating a suitable private key in the current user's key store.

The following code shows how to decrypt a mail message:

CSharp

// load a mail
var mail = new Rebex.Mail.MailMessage();
mail.Load(@"C:\MyData\mail.eml");

// decrypt the message if it is encrypted
if (mail.IsEncrypted)
{
    if (mail.CanDecrypt)
    {
        mail.Decrypt();
        Console.WriteLine("The message was decrypted successfully.");
    }
    else
    {
        Console.WriteLine("You don't have the private key to decrypt the message.");
    }
}
else
{
    Console.WriteLine("The message is not encrypted.");
}

VisualBasic

' load a mail
Dim mail = New Rebex.Mail.MailMessage()
mail.Load("C:\MyData\mail.eml")

' decrypt the message if it is encrypted
If mail.IsEncrypted Then
    If mail.CanDecrypt Then
        mail.Decrypt()
        Console.WriteLine("The message was decrypted successfully.")
    Else
        Console.WriteLine("You don't have the private key to decrypt the message.")
    End If
Else
    Console.WriteLine("The message is not encrypted.")
End If

Combining encryption and signature #

A mail message can be both signed and encrypted. This ensures message integrity, confidentiality, and authentition of the sender.

There are two ways to produce a message that is both encrypted and sign:

  1. Encrypt a signed message (sign first, then encrypt).
  2. Sign an encrypted message (encrypt first, then sign).

In the first case, no one but the recipient will be able to validate the signature and access the message content. In the second case, no one but the recipient will be able to access the message content, but anyone will be able to validate the signature.

Both ways have their pros and cons, but there is a very strong reason to prefer the first way: Some e-mail clients (such as Outlook Express or Windows Live Mail) do not handle the second way correctly, and claim the correct signature is not valid.

The following code signs a message and encrypts it:

CSharp

// create mail
var mail = new Rebex.Mail.MailMessage();
// fill some fields
// ...

// load sender's certificate
Certificate signer = Certificate.LoadPfx(@"C:\MyData\MyCertificate.pfx", "password");

// load receiver's certificate
Certificate recipient = Certificate.LoadDer(@"C:\MyData\ReceiverCertificate.der");

// sign the message using sender's certificate
mail.Sign(signer);

// encrypt the message using both receiver's and sender's certificates
mail.Encrypt(recipient, signer);

VisualBasic

' create mail
Dim mail = New Rebex.Mail.MailMessage()
' fill some fields
' ...

' load sender's certificate
Dim signer As Certificate = Certificate.LoadPfx("C:\MyData\MyCertificate.pfx", "password")

' load receiver's certificate
Dim recipient As Certificate = Certificate.LoadDer("C:\MyData\ReceiverCertificate.der")

' sign the message using sender's certificate
mail.Sign(signer)

' encrypt the message using both receiver's and sender's certificates
mail.Encrypt(recipient, signer)