Rebex Security
XTS-AES and other handy security classes for .NET
Download 30-day free trial Buy from $199More .NET libraries
-
Rebex SFTP
.NET SFTP client
-
Rebex SSH Shell
.NET SSH Shell
-
Rebex Total Pack
All Rebex .NET libraries together
Back to feature list...
Cryptographic algorithms
On this page:
- Cryptographic Message Syntax (PKCS #7) SignedData
- Cryptographic Message Syntax (PKCS #7) SignedData with RSASSA-PSS
- Cryptographic Message Syntax (PKCS #7) EnvelopedData
- Cryptographic Message Syntax (PKCS #7) EnvelopedData with RSAES-OAEP
- AES/GCM AEAD cipher
- ChaCha20/Poly1305 AEAD cipher
- Twofish symmetric cipher
- Blowfish symmetric cipher
- RC2 symmetric cipher
- ArcFour symmetric cipher (compatible with RC4)
- MD4 legacy hash algorithm
- MD5 legacy hash algorithm
- SHA-2 hash algorithms for .NET CF
- Argon2 hash algorithm
- BLAKE2 hash and message authentication algorithm
- RSA public-key cryptography
- DSA public-key cryptography
- Diffie-Hellman key exchange algorithm
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.
AES/GCM AEAD cipher
AesGcm
class
provides multi-platform support for AES/GCM symmetric encryption algorithm.
This is an AEAD algorithm that combines encryption, confidentiality, integrity, and authenticity into a single efficient operation.
The API resembles AesGcm
class from recent .NET editions, but Rebex implementation is available on
all supported platforms.
The underlying implementation uses Windows CNG API or .NET's AesGcm
class when available.
Otherwise, a custom managed implementation is used instead.
Encrypting and decrypting data using AES/GCM:
// prepare key and nonce
byte[] key;
byte[] nonce;
using (var randomGenerator = RandomNumberGenerator.Create())
{
// generate random key.
key = new byte[AesGcm.KeyByteSizes.MaxSize];
randomGenerator.GetBytes(key);
// generate random nonce.
nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
randomGenerator.GetBytes(nonce);
}
// prepare the array in which the authentication tag will be stored
var authTag = new byte[AesGcm.TagByteSizes.MaxSize];
// encrypt data
using (var aesGcm = new AesGcm(key))
{
aesGcm.Encrypt(nonce, plainText, cipherText, authTag);
// after a successful call cipherText contains the encrypted data
// and authTag contains the authentication tag
}
// later decrypt data
using (var aesGcm = new AesGcm(key))
{
aesGcm.Decrypt(nonce, cipherText, authTag, decryptedText);
}
ChaCha20/Poly1305 AEAD cipher
ChaCha20Poly1305
class
provides multi-platform support for ChaCha20/Poly1305 symmetric encryption algorithm.
This is an AEAD algorithm that combines encryption, confidentiality, integrity, and authenticity into a single efficient operation.
The API resembles ChaCha20Poly1305
class from recent .NET editions, but Rebex implementation is available on
all supported platforms.
The underlying implementation uses .NET's ChaCha20Poly1305
class when available.
Otherwise, a custom managed implementation is used instead.
Encrypting and decrypting data using ChaCha20/Poly1305:
// prepare key and nonce
byte[] key;
byte[] nonce;
using (var randomGenerator = RandomNumberGenerator.Create())
{
// generate random key.
key = new byte[ChaCha20Poly1305.KeySize];
randomGenerator.GetBytes(key);
// generate random nonce.
nonce = new byte[ChaCha20Poly1305.NonceSize];
randomGenerator.GetBytes(nonce);
}
// prepare the array in which the authentication tag will be stored
var authTag = new byte[ChaCha20Poly1305.AuthenticationTagSize];
// encrypt data
using (var chacha20Poly1305 = new ChaCha20Poly1305(key))
{
chacha20Poly1305.Encrypt(nonce, plainText, cipherText, authTag);
// after a successful call cipherText contains the encrypted data
// and authTag contains the authentication tag
}
// later decrypt data
using (var chacha20Poly1305 = new ChaCha20Poly1305(key))
{
chacha20Poly1305.Decrypt(nonce, cipherText, authTag, decryptedText);
}
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.
Argon2 hash algorithm
The Argon2
class
provides memory-hard hash algorithm for password hashing and proof-of-work applications
(designed to protect against brute-force attacks).
Specified by RFC 9106.
Rebex implementation of Argon2 supports all variants:
Argon2i
,
Argon2d
,
and Argon2id
.
When hashing a password using Argon2, you can customize several parameters (such as memory usage, number of iterations, and parallelism) to better fit your application's security and performance needs.
// Use Argon2 configuration suitable for your environment.
// In typical 'hash user password' scenarios, the configuration does not change between
// method calls, so it is recommended to cache the Argon2Configuration instance.
var configuration = new Argon2Configuration(argon2Type: Argon2Type.Argon2id,
numberOfLanes: 4, numberOfIterations: 10, memoryCost: 65536);
// The size of the raw hash to compute. Must be at least 4 bytes long.
// Please note that the encoded hash (in string form) will be longer than the raw hash.
int hashLength = 32;
// Compute the hash of the password.
// This method generates a random (16 bytes long) salt value.
// To provide custom salt, use another overload of the HashPassword method.
string encodedHash = Argon2.HashPassword(userPassword, hashLength, configuration);
// --------------------------------------------------------------
// Verify the password.
if (!Argon2.VerifyPassword(encodedHash, userPasswordFromUi))
throw new UnauthorizedAccessException("Wrong password");
BLAKE2 hash and message authentication algorithm
The Blake2b
class
represents the BLAKE2b cryptographic hash and message authentication code (MAC) algorithm
with custom (user-defined) hash size.
Specified by RFC 7693.
BLAKE2 provides better security than SHA-2 (it is comparable to that of SHA-3).
To create a hash, keep the key
argument empty:
// create an instance of Blake2b class for constructing 32-bytes hash
using (var blake2b = new Blake2b(32))
{
// create the hash
byte[] hash = blake2b.ComputeHash(sourceData);
}
To create a message authentication code (HMAC), use a 1–64 bytes long key
:
// create an instance of Blake2b class for constructing 32-bytes message authentication code
using (var blake2b = new Blake2b(32, key))
{
// create the HMAC
byte[] hmac = blake2b.ComputeHash(sourceData);
}
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...