Certificats et csharp

De Banane Atomic
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigationAller à la recherche

Accéder aux clés

Csharp.svg
X509Certificate2 certificat;

var privateKey = certificat.PrivateKey.ToXmlString(true);
var publicKey = certificat.PublicKey.Key.ToXmlString(false);

var publicKeyBase64 = Convert.ToBase64String(certificat.RawData);

Lire un fichier de certificat

Csharp.svg
// certificat avec clé publique seulement
var certificate = new X509Certificate2(certificateFilePath);

// certificat avec clé publique et privée
var certificate = new X509Certificate2(certificateFilePath, certificateFilePassword, X509KeyStorageFlags.Exportable);

Lire un certificat depuis le Windows Store Certificate

Certificats identifiés par leur Serial Number et stocké dans CurrentUser ou LocalMachine.
Possibilité d'enregistrer les formats X509, PKCS12
Possibilité d'exporter le certificat (mais pas la clé privée) au format DER, PEM
Demande du mot de passe pour l'export de la clé privée
L'import d'un fichier *.cer n'importe que le certificat même si le fichier contient la clé privée.
L'import d'un fichier *.p12 ne permet l'accès à la clé privée que si elle a été importée comme exportable (Mark this key as exportable).

Csharp.svg
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
X509Certificate2 x509 = null;
foreach (X509Certificate2 certificat in store.Certificates)
{
    if (!certificat.HasPrivateKey) continue; // skip certificats without private keys

    if (certificat.SerialNumber.Equals("xxxxxxxxxxxxxxxxxx", StringComparison.InvariantCultureIgnoreCase))
    {
        x509 = certificat;
        break;
    }
}
store.Close();

Signer un fichier XML

Csharp.svg
// Use “enveloping” signature and create SHA2-256 hash
// create an RSA digital signature using the 2048-bit private key

XmlDocument doc;
string signatureCanonicalizationMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
string signatureMethod = @"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
string digestMethod = @"http://www.w3.org/2001/04/xmlenc#sha256";

CryptoConfig.AddAlgorithm(typeof(RSAPKCS1SHA256SignatureDescription), signatureMethod);

// This small hack is needed to switch to Enhanced RSA and AES Cryptographic Provider
// to be able to use RSA-SHA256 signatures.
// The privateKey HAS TO BE EXPORTABLE, otherwise the call ToXmlString will fail
CspParameters cspParams = new CspParameters(24);
RSACryptoServiceProvider privateKey = new RSACryptoServiceProvider(cspParams);
privateKey.FromXmlString(signingCertificate.PrivateKey.ToXmlString(true));

// Create signed xml from input and initialize it.
SignedXml signer = new SignedXml(doc);
signer.SigningKey = privateKey;
signer.SignedInfo.CanonicalizationMethod = signatureCanonicalizationMethod;
signer.SignedInfo.SignatureMethod = signatureMethod;
XmlDsigExcC14NTransform cn14Transform = new XmlDsigExcC14NTransform();

// Add the data to be signed as a sub-element of the Signature-element (Enveloping).
DataObject dataObject = new DataObject();
dataObject.Data = doc.GetElementsByTagName("balise root");
dataObject.Id = "Id";
signer.AddObject(dataObject);

// Add a reference to the signed data.
Reference signatureReference = new Reference();
signatureReference.Uri = "#Id";
signatureReference.AddTransform(cn14Transform);
signatureReference.DigestMethod = digestMethod;
signer.AddReference(signatureReference);

// Create the signature
signer.ComputeSignature();

// Get the XML representation of the signature and save it to an XmlElement object.
StringBuilder xmlBuilder = new StringBuilder();
xmlBuilder.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
xmlBuilder.Append(signer.GetXml().OuterXml);

File.WriteAllText(destinationPath, xmlBuilder.ToString(), Encoding.UTF8);

(Dé)chiffrer un fichier

Chiffrement asymétrique avec une clé publique

Csharp.svg
byte[] bytesToBeEncrypted = File.ReadAllBytes(filePathToEncrypt);
var certificate = new X509Certificate2(certificateFilePath);

CspParameters cspParams = new CspParameters(24);
using (var provider = new RSACryptoServiceProvider(cspParams))
{
    provider.FromXmlString(certificate.PublicKey.Key.ToXmlString(false));
    byte[] bytesEncrypted = provider.Encrypt(bytesToBeEncrypted, false);
    File.WriteAllBytes(encryptedFilePath, bytesEncrypted);
}

Déchiffrement asymétrique avec une clé privée

Csharp.svg
byte[] bytesToBeDecrypted = File.ReadAllBytes(encryptedFilePath);
var certificate = new X509Certificate2(certificateFilePath, certificateFilePassword, X509KeyStorageFlags.Exportable);

CspParameters cspParams = new CspParameters(24);
using (var provider = new RSACryptoServiceProvider(cspParams))
{
    provider.FromXmlString(certificate.PrivateKey.ToXmlString(true));
    byte[] bytesDecrypted = provider.Decrypt(bytesToBeDecrypted, false);
    File.WriteAllBytes(decryptedFilePath, bytesDecrypted);
}

Chiffrement symétrique avec une clé AES-256 générée aléatoirement

Csharp.svg
string password = GetRandomString();

byte[] bytesToBeEncrypted = File.ReadAllBytes(filePathToEncrypt);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
byte[] bytesEncrypted;

// Hash the password with SHA256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
// Store the key in a file
File.WriteAllBytes(keyFilePath, passwordBytes);

using (MemoryStream ms = new MemoryStream())
{
    using (AesManaged AES = new AesManaged())
    {
        AES.KeySize = 256;
        AES.Mode = CipherMode.ECB;
        AES.IV = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // CRB mode uses an empty IV
        AES.Key = passwordBytes;
        AES.Padding = PaddingMode.PKCS7;

        using (CryptoStream cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
        {
            cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
            cs.Close();
        }
        bytesEncrypted = ms.ToArray();
    }
}

File.WriteAllBytes(encryptedFilePath, bytesEncrypted);

private string GetRandomString()
{
    var sb = new StringBuilder();
    Random rnd = new Random();
    int size = rnd.Next(5, 10);

    for (int i = 0; i < size; i++)
    {
        sb.Append(Guid.NewGuid().ToString());
    }
    return sb.ToString();
}

Déchiffrement symétrique avec une clé AES-256

Csharp.svg
byte[] bytesToBeDecrypted = File.ReadAllBytes(encryptedFilePath);
byte[] passwordBytes = File.ReadAllBytes(keyFilePath);
byte[] bytesDecrypted;

using (MemoryStream ms = new MemoryStream(bytesToBeDecrypted))
{
    using (AesManaged AES = new AesManaged())
    {
        AES.KeySize = 256;
        AES.Mode = CipherMode.ECB;
        AES.IV = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // CRB mode uses an empty IV
        AES.Key = passwordBytes;
        AES.Padding = PaddingMode.PKCS7;

        using (CryptoStream cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
        {
            cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
            cs.Close();
        }
        bytesDecrypted = ms.ToArray();
    }
}
File.WriteAllBytes(decryptedFilePath, bytesDecrypted);