Really simple encryption with C# and SymmetricAlgorithm

倖福魔咒の 提交于 2019-12-18 10:33:46

问题


I'm looking for a very simple crypt / decrypt method. I will be using always the same static key. I'm aware of the risks of this approach. Currently I'm using the following code but it does not generate the same result after crypting and decripting the same string (there is some garbage in the middle of the string).

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

I can change whatever is needed, no limits (but I want just to have on method to crypt and another one to decrypt without sharing variables between them).

Thanks.


回答1:


If you don't want to handle keys yourself then let the operating system do it for your. E.g. use Windows Data Protection (DPAPI).

You can write your own, string-based, version of System.Security.Cryptography.ProtectedData.Protect and Unprotect methods by using something like:

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



回答2:


How about something like this?

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

Unit Test

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

EDIT:

To clarify: I am aware this is not good practice.

"I'm aware of the risks of this approach. "

Iv'e made the assumption that the OP is also aware and will make relevant code changes before considering using anything like this in a production environment.

The question emphasizes simplicity over good practice.




回答3:


You'll need to set the cipher mode to CipherMode.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;
...

Another point is not to use Unicode encoding. Use Base64 instead. Unicode might "destroy" bytes that are not UTF-16.



来源:https://stackoverflow.com/questions/9031537/really-simple-encryption-with-c-sharp-and-symmetricalgorithm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!