More .NET components

Cryptographic algorithms

Cryptographic Message Syntax (PKCS #7) SignedData #

Rebex.Security.Cryptography.Pkcs.SignedData provides an API for creating and parsing CMS (PKCS #7) SignedData structures. This is a standard format for electronic signature of binary data using X509 certificates. CMS/PKCS #7's SignedData structure is part of many other standards such as S/MIME.

For example, this is how to create a detached .P7S signature file for a PDF document (or any other file) using a certificate:

CSharp

// get a certificate with a private key
var certificate = Certificate.LoadPfx("mycert.pfx", "password");

// load the content of a file we need to sign
byte[] content = File.ReadAllBytes("document.pdf");
var contentInfo = new ContentInfo(content);

// create a PKCS #7 SignedData object based on this,
// the second argument specifies "detached" style
var signedData = new SignedData(contentInfo, true);

// add one ore more signers
var signer = new SignerInfo(certificate);
signedData.SignerInfos.Add(signer);

// create the signature
signedData.Sign();

// save the signature into a detached signature file
using (var output = File.Create("document.pdf.p7s"))
{
    signedData.Save(output);
}

VisualBasic

' get a certificate with a private key
Dim cert = Certificate.LoadPfx("mycert.pfx", "password")

' load the content of a file we need to sign
Dim content As Byte() = File.ReadAllBytes("document.pdf")
Dim contentInfo = New ContentInfo(content)

' create a PKCS #7 SignedData object based on this,
' the second argument specifies "detached" style
Dim signedData = New SignedData(contentInfo, True)

' add one ore more signers
Dim signer = New SignerInfo(cert)
signedData.SignerInfos.Add(signer)

' create the signature
signedData.Sign()

' save the signature into a detached signature file
Using output = File.Create("document.pdf.p7s")
    signedData.Save(output)
End Using

At the other end, use this code to validate the detached .P7S signature:

CSharp

// load the content of a file whose signature we wish to check
byte[] content = File.ReadAllBytes("document.pdf");
var contentInfo = new ContentInfo(content);

// create a PKCS #7 SignedData object base on this,
// the second argument specifies "detached" style
var signedData = new SignedData(contentInfo, true);

// load the detached signature file
using (Stream input = File.OpenRead("document.pdf.p7s"))
{
    signedData.Load(input);
}

// validate the signature and the certificates
SignatureValidationResult result = signedData.Validate();

// display the validation result
if (result.Valid)
{
    Console.WriteLine("Both signature and certificates are valid.");
}
else
{
    Console.WriteLine("Signature or certificates are NOT valid.");
    Console.WriteLine("Signature problems: {0}", result.Status);
    Console.WriteLine("Certificate problems: {0}", result.CertificateValidationStatus);
}

VisualBasic

' load the content of a file whose signature we wish to check
Dim content As Byte() = File.ReadAllBytes("document.pdf")
Dim contentInfo = New ContentInfo(content)

' create a PKCS #7 SignedData object base on this,
' the second argument specifies "detached" style
Dim signedData = New SignedData(contentInfo, True)

' load the detached signature file
Using input As Stream = File.OpenRead("document.pdf.p7s")
    signedData.Load(input)
End Using

' validate the signature and the certificates
Dim result As SignatureValidationResult = signedData.Validate()

' display the validation result
If result.Valid Then
    Console.WriteLine("Both signature and certificates are valid.")
Else
    Console.WriteLine("Signature or certificates are NOT valid.")
    Console.WriteLine("Signature problems: {0}", result.Status)
    Console.WriteLine("Certificate problems: {0}", result.CertificateValidationStatus)
End If

SignedData object's encoding/decoding methods emit/parse an outer ContentInfo structure, which is wrapped around the inner SignedData structure. This is a part of the CMS standard.

Cryptographic Message Syntax (PKCS #7) EnvelopedData #

Rebex.Security.Cryptography.Pkcs.EnvelopedData provides an API for creating and parsing CMS (PKCS #7) EnvelopedData structures. This a standard format for encryption of binary data using X509 certificates. CMS/PKCS #7's EnvelopedData structure is part of many other standards such as S/MIME.

For example, this is how to encrypt a PDF document (or any other file) using a certificate:

CSharp

// get the recipient's certificate
// (no private key needed)
var certificate = Certificate.LoadDer("theircert.cer");

// load the content of a file we need to encrypt
byte[] content = File.ReadAllBytes("document.pdf");
var contentInfo = new ContentInfo(content);

// create a PKCS #7 EnvelopedData object based on this
var envelopedData = new EnvelopedData(contentInfo);

// add one ore more recipients
var recipient = new KeyTransRecipientInfo(certificate);
envelopedData.RecipientInfos.Add(recipient);

// encrypt data
envelopedData.Encrypt();

// save encrypted data into a .p7m file
using (var output = File.Create("document.p7m"))
{
    envelopedData.Save(output);
}

VisualBasic

' get the recipient's certificate
' (no private key needed)
Dim cert = Certificate.LoadDer("theircert.cer")

' load the content of a file we need to encrypt
Dim content As Byte() = File.ReadAllBytes("document.pdf")
Dim contentInfo = New ContentInfo(content)

' create a PKCS #7 EnvelopedData object based on this
Dim envelopedData = New EnvelopedData(contentInfo)

' add one ore more recipients
Dim recipient = New KeyTransRecipientInfo(cert)
envelopedData.RecipientInfos.Add(recipient)

' encrypt data
envelopedData.Encrypt()

' save encrypted data into a .p7m file
Using output = File.Create("document.p7m")
    envelopedData.Save(output)
End Using

At the other end, use this code to decrypt the document:

CSharp

// create an empty PKCS #7 EnvelopedData object
var envelopedData = new EnvelopedData();

// load the encrypted file into it
using (Stream input = File.OpenRead("document.p7m"))
{
    envelopedData.Load(input);
}

// check whether it's possible to decrypt the file
if (envelopedData.HasPrivateKey)
{
    // decrypt it if possible (when a suitable decryption certificate with
    // an associated private key is available in Windows Certificate store)
    envelopedData.Decrypt();

    // save decrypted content into a file
    File.WriteAllBytes("document.pdf", envelopedData.ContentInfo.ToArray());
}
else
{
    // otherwise, display a list of intended recipients
    foreach (RecipientInfo recipient in envelopedData.RecipientInfos)
    {
        SubjectIdentifier id = recipient.RecipientIdentifier;
        Console.WriteLine("Recipient info:");

        if (id.Issuer != null)
            Console.WriteLine("  Certificate issuer: {0}", id.Issuer);

        if (id.SerialNumber != null)
            Console.WriteLine("  Serial number: {0}", BitConverter.ToString(id.SerialNumber));

        if (id.SubjectKeyIdentifier != null)
            Console.WriteLine("  Subject key identifier: {0}", BitConverter.ToString(id.SubjectKeyIdentifier));

        if (id.PublicKey != null)
            Console.WriteLine("  Public key: {0}", BitConverter.ToString(id.PublicKey));

        if (id.PublicKeyAlgorithm != null)
            Console.WriteLine("  Key algorithm: {0}", id.PublicKeyAlgorithm.Oid);
    }
}

VisualBasic

' create an empty PKCS #7 EnvelopedData object
Dim envelopedData = New EnvelopedData()

' load the encrypted file into it
Using input As Stream = File.OpenRead("document.p7m")
    envelopedData.Load(input)
End Using

' check whether it's possible to decrypt the file
If envelopedData.HasPrivateKey Then
    ' decrypt it if possible (when a suitable decryption certificate with
    ' an associated private key is available in Windows Certificate store)
    envelopedData.Decrypt()

    ' save decrypted content into a file
    File.WriteAllBytes("document.pdf", envelopedData.ContentInfo.ToArray())
Else
    ' otherwise, display a list of intended recipients
    For Each recipient As RecipientInfo In envelopedData.RecipientInfos
        Dim id As SubjectIdentifier = recipient.RecipientIdentifier
        Console.WriteLine("Recipient info:")

        If id.Issuer IsNot Nothing Then
            Console.WriteLine("  Certificate issuer: {0}", id.Issuer)
        End If

        If id.SerialNumber IsNot Nothing Then
            Console.WriteLine("  Serial number: {0}", BitConverter.ToString(id.SerialNumber))
        End If

        If id.SubjectKeyIdentifier IsNot Nothing Then
            Console.WriteLine("  Subject key identifier: {0}", BitConverter.ToString(id.SubjectKeyIdentifier))
        End If

        If id.PublicKey IsNot Nothing Then
            Console.WriteLine("  Public key: {0}", BitConverter.ToString(id.PublicKey))
        End If

        If id.PublicKeyAlgorithm IsNot Nothing Then
            Console.WriteLine("  Key algorithm: {0}", id.PublicKeyAlgorithm.Oid)
        End If
    Next
End If

EnvelopedData object's encoding/decoding methods emit/parse an outer ContentInfo structure, which is wrapped around the inner EnvelopedData structure. This is a part of the CMS standard.

Twofish symmetric cipher #

Rebex.Security.Cryptography.TwofishManaged is a managed implementation of Bruce Schneier's Twofish, a symmetric key block cipher. It derives from .NET's SymmetricAlgorithm object, which means it fits nicely into applications that already utilize another symmetric algorithms provided by .NET. For example, it works nicely with .NET's CryptoStream object.

Blowfish symmetric cipher #

Rebex.Security.Cryptography.BlowfishManaged is a managed implementation of Bruce Schneier's Twofish, a symmetric key block cipher. It derives from .NET's SymmetricAlgorithm object, which means it fits nicely into applications that already utilize another symmetric algorithms provided by .NET. For example, it works nicely with .NET's CryptoStream object.

RC2 symmetric cipher #

Rebex.Security.Cryptography.ArcTwoManaged is a managed implementation of RSA Security's RC2(r), a symmetric key block cipher. It derives from .NET's SymmetricAlgorithm object, which means it fits nicely into applications that already utilize another symmetric algorithms provided by .NET. For example, it works nicely with .NET's CryptoStream object.

Unlike .NET's RC2CryptoServiceProvider object, ArcTwo makes it possible to specify an effective key size with EffectiveKeySize property.

ArcFour symmetric cipher (compatible with RC4) #

Rebex.Security.Cryptography.ArcFourManaged is a managed implementation of an algorithm compatible with RSA Security's RC4, a widely used symmetric key stream cipher. It derives from .NET's SymmetricAlgorithm object, which means it fits nicely into applications that already utilize another symmetric algorithms provided by .NET.

When using ArcFour, please not that it's a stream cipher, unlike most other symmetric algorithms that are block ciphers.

MD4 legacy hash algorithm #

Rebex.Security.Cryptography.MD4Managed is a managed implementation of RSA Security's MD4 cryptographic hash function. It derives from .NET's HashAlgorithm object, which means it fits nicely into .NET applications.

The MD4 algorithm is no longer considered secure and should no longer be used. However, it is still useful to ensure interoperability with legacy systems that still use MD4 and can't be easily upgraded to use a more secure hash algorithm.

MD5 legacy hash algorithm #

Rebex.Security.Cryptography.MD5Managed is a managed implementation of RSA Security's MD5 cryptographic hash function. It derives from .NET's HashAlgorithm object, which means it fits nicely into .NET applications. Unlike .NET's MD5CryptoServiceProvider, it is fully managed and doesn't rely on Windows CryptoAPI.

The MD5 algorithm is no longer considered secure and should no longer be used. However, it is still useful to ensure interoperability with legacy systems that still use MD5 and can't be easily upgraded to use a more secure hash algorithm.

SHA-2 hash algorithms for .NET CF #

Rebex.Security.Cryptography.SHA256Managed, SHA384Managed and SHA512Managed are managed implementation of NSA's SHA-2 cryptographic hash functions. These classes are only available on .NET Compact Framework, which lacks the standard .NET System.Security.Cryptography.SHA256Managed and System.Security.Cryptography.SHA256CryptoServiceProvider classes (and their SHA-384/SHA-512 counterparts). The three Rebex SHA-2 classes are fully managed and don't rely on Windows CryptoAPI. They are compatible with the missing .NET classes.

RSA public-key cryptography #

Rebex.Security.Cryptography.RSAManaged is a managed implementation of RSA Security's RSA public key algorithm. It derives from .NET's RSA object, which means it fits nicely into .NET applications. Unlike .NET's RSACryptoServiceProvider, it is fully managed, doesn't rely on Windows CryptoAPI and implements EncryptValue and DecryptValue methods.

RSAManaged does not currently support key generation.

DSA public-key cryptography #

Rebex.Security.Cryptography.DSAManaged is a managed implementation of DSA (Digital Signature Algorihm) public key algorithm. It derives from .NET's DSA object, which means it fits nicely into .NET applications. Unlike .NET's DSACryptoServiceProvider, it is fully managed and doesn't rely on Windows CryptoAPI.

DSAManaged does not currently support key generation.

Diffie-Hellman key exchange algorithm #

Rebex.Security.Cryptography.DiffieHellmanManaged is a managed implementation of Diffie-Hellman key exchange algorithm. Rebex.Security.Cryptography.DiffieHellmanCryptoServiceProvider is another implementation that uses Windows CryptoAPI, making it faster.