Cifrado realmente simple con C# y algoritmo simétrico


Estoy buscando un muy método simple crypt / decrypt. Usaré siempre la misma clave estática. Soy consciente de los riesgos de este enfoque. Actualmente estoy usando el siguiente código, pero no genera el mismo resultado después de cifrar y descifrar la misma cadena (hay algo de basura en el medio de la cadena).

    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;
    }

Puedo cambiar lo que sea necesario, sin límites (pero solo quiero tener un método para cifrar y otro para descifrar sin compartir variables entre ellos).

Gracias.

Author: Ignacio Soler Garcia, 2012-01-27

3 answers

Si no desea manejar las claves usted mismo, deje que el sistema operativo lo haga por usted. Por ejemplo, use Protección de datos de Windows (DPAPI).

Puedes escribir tu propia versión basada en string de System.Security.Cryptography.ProtectedData.Protect y Unprotect métodos usando algo como:

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) ) );
}
 42
Author: poupou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:54:00

¿Qué tal algo como esto?

Código

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);
    }
}

Prueba unitaria

[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);
}

EDITAR:

Para aclarar: Soy consciente de que esto no es una buena práctica.

"Soy consciente de los riesgos de este enfoque. "

Iv'e hizo la suposición de que el OP también es consciente y hará cambios de código relevantes antes de considerar usar algo como esto en un entorno de producción.

La pregunta enfatiza la simplicidad sobre buenas prácticas.

 25
Author: Sam Greenhalgh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 13:58:15

Tendrá que establecer el modo de cifrado en cifromodo.ECB or use an IV.

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

Otro punto es no usar codificación Unicode. Utilice Base64 en su lugar. Unicode podría "destruir" bytes que no sean UTF-16.

 6
Author: Sani Singh Huttunen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-27 10:18:15