web-dev-qa-db-fra.com

Cryptage vraiment simple avec C # et SymmetricAlgorithm

Je cherche une méthode très simple de cryptage/décryptage. J'utiliserai toujours la même clé statique. Je suis conscient des risques de cette approche. Actuellement, j'utilise le code suivant, mais il ne génère pas le même résultat après le cryptage et le décryptage de la même chaîne (il y a des ordures au milieu de la chaîne).

public static string Crypt(this string text)
{
    string result = null;

    if (!String.IsNullOrEmpty(text))
    {
        byte[] plaintextBytes = Encoding.Unicode.GetBytes(text);

        SymmetricAlgorithm symmetricAlgorithm = DES.Create();
        symmetricAlgorithm.Key = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8};
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, symmetricAlgorithm.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cryptoStream.Write(plaintextBytes, 0, plaintextBytes.Length);
            }

            result = Encoding.Unicode.GetString(memoryStream.ToArray());
        }
    }

    return result;
}

public static string Decrypt(this string text)
{
    string result = null;

    if (!String.IsNullOrEmpty(text))
    {
        byte[] encryptedBytes = Encoding.Unicode.GetBytes(text);

        SymmetricAlgorithm symmetricAlgorithm = DES.Create();
        symmetricAlgorithm.Key = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        using (MemoryStream memoryStream = new MemoryStream(encryptedBytes))
        {
            using (CryptoStream cryptoStream = new CryptoStream(memoryStream, symmetricAlgorithm.CreateDecryptor(), CryptoStreamMode.Read))
            {
                byte[] decryptedBytes = new byte[encryptedBytes.Length];
                cryptoStream.Read(decryptedBytes, 0, decryptedBytes.Length);
                result = Encoding.Unicode.GetString(decryptedBytes);
            }
        }
    }

    return result;
}

Je peux changer tout ce qui est nécessaire, pas de limites (mais je veux juste avoir une méthode pour crypter et une autre pour décrypter sans partager de variables entre elles).

Merci.

26

Si vous ne voulez pas gérer les clés vous-même, laissez le système d'exploitation le faire pour vous. Par exemple. utilisez Protection des données Windows (DPAPI).

Vous pouvez écrire votre propre version, basée sur string, System.Security.Cryptography.ProtectedData.Protect et Unprotect méthodes en utilisant quelque chose comme:

public static string Crypt (this string text)
{
    return Convert.ToBase64String (
        ProtectedData.Protect (
            Encoding.Unicode.GetBytes (text) ) );
}

public static string Derypt (this string text)
{
    return Encoding.Unicode.GetString (
        ProtectedData.Unprotect (
             Convert.FromBase64String (text) ) );
}
54
poupou

Que diriez-vous quelque chose comme ça?

Code

using System;
using System.Security.Cryptography;
using System.Text;

public static class StringUtil
{
    private static byte[] key = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8};
    private static byte[] iv = new byte[8] {1, 2, 3, 4, 5, 6, 7, 8};

    public static string Crypt(this string text)
    {
        SymmetricAlgorithm algorithm = DES.Create();
        ICryptoTransform transform = algorithm.CreateEncryptor(key, iv);
        byte[] inputbuffer = Encoding.Unicode.GetBytes(text);
        byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
        return Convert.ToBase64String(outputBuffer);
    }

    public static string Decrypt(this string text)
    {
        SymmetricAlgorithm algorithm = DES.Create();
        ICryptoTransform transform = algorithm.CreateDecryptor(key, iv);
        byte[] inputbuffer = Convert.FromBase64String(text);
        byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length);
        return Encoding.Unicode.GetString(outputBuffer);
    }
}

Test unitaire

[Test]
public void Test()
{
    string expected = "this is my test string";
    string a = expected.Crypt();
    Debug.WriteLine(a);
    string actual = a.Decrypt();
    Assert.AreEqual(expected, actual);
}

MODIFIER:

Pour clarifier: je suis conscient que ce n'est pas une bonne pratique.

"Je suis conscient des risques de cette approche."

Iv'e a fait l'hypothèse que l'OP est également au courant et apportera les modifications de code pertinentes avant d'envisager d'utiliser quelque chose comme ça dans un environnement de production.

La question met l'accent sur la simplicité plutôt que sur les bonnes pratiques.

33
Sam Greenhalgh

Vous devrez définir le mode de chiffrement sur CipherMode.ECB ou utiliser un IV.

SymmetricAlgorithm symmetricAlgorithm = DES.Create();
symmetricAlgorithm.Key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
symmetricAlgorithm.Mode = CipherMode.ECB;
...

Un autre point est de ne pas utiliser le codage Unicode. Utilisez plutôt Base64. Unicode peut "détruire" les octets qui ne sont pas UTF-16.

9
Sani Singh Huttunen