Rebex Security

XTS-AES and other handy security classes for .NET

Download 30-day free trial Buy from $99
More .NET libraries

Back to feature list...

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 X.509 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:

// 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);
}
' 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:

// 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);
}
' 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) SignedData with RSASSA-PSS 

In addition to classic RSA cryptographic signature scheme (PKCS#1 v1.5), Rebex.Security.Cryptography.Pkcs.SignedData also supports Probabilistic Signature Scheme (PSS), whose security has been proven to directly relate to that of RSA itself. Because there is no such proof for classic PKCS#1 scheme, RSA/PSS is quickly becoming the preferred signature scheme.

Rebex Security supports RSA with PSS on all platforms. Use the same code as above, but specify the PaddingScheme in SignerInfo constructor call:

// ...
// add one ore more signers
var signer = new SignerInfo(certificate, new SignatureParameters()
{
    PaddingScheme = SignaturePaddingScheme.Pss
});
signedData.SignerInfos.Add(signer);

// create the signature
signedData.Sign();

// ...

Note: As of 2017, RSASSA-PSS is still not widely supported. OpenSSL supports it starting with version 1.0.2.

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 X.509 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:

// 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);
}
' 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:

// 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);
    }
}
' 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.

Cryptographic Message Syntax (PKCS #7) EnvelopedData with RSAES-OAEP 

In addition to classic RSA cryptographic signature scheme (PKCS#1 v1.5), Rebex.Security.Cryptography.Pkcs.EnvelopedData also supports Optimal asymmetric encryption padding (OAEP), which converts the traditional RSA deterministic encryption scheme into a probabilistic scheme. RSA/OAEP offers protection against chosen ciphertext attacks and is quickly becoming the preferred padding scheme for RSA encryption.

Rebex Security supports RSA with OAEP on all platforms. Use the same code as above, but specify the PaddingScheme in KeyTransRecipientInfo constructor call:

// ...
// add one ore more recipients
var recipient = new KeyTransRecipientInfo(certificate, new EncryptionParameters()
{
    PaddingScheme = EncryptionPaddingScheme.Oaep
});
envelopedData.RecipientInfos.Add(recipient);

// encrypt data
envelopedData.Encrypt();

// ...

Use EncryptionParameters.Label to specify OAEP label (also known as input parameter).

Note: As of January 2018, RSAES-OAEP is still not widely supported. OpenSSL supports it starting with version 1.0.2.

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 note 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.

Back to feature list...