C#的简单不安全双向“混淆”

时间:2008-10-03 05:41:32

标签: c# obfuscation

我正在为某些数据寻找非常简单的混淆(如加密和解密但不一定是安全的)功能。这不是关键任务。我需要一些东西来保持诚实的人诚实,但有点强于ROT13Base64

我更喜欢已经包含在.NET框架2.0中的内容,因此我不必担心任何外部依赖项。

我真的不想乱用公钥/私钥等等。我对加密知之甚少,但我知道我写的任何内容都不会毫无价值......事实上,我可能搞砸了数学并且让它变得微不足道。

17 个答案:

答案 0 :(得分:470)

此处的其他答案工作正常,但AES是一种更安全和最新的加密算法。这是我几年前用来执行AES加密的类,我已经修改了一段时间以便对Web应用程序更友好(例如,我已经构建了使用URL友好字符串的加密/解密方法)。它还具有与字节数组一起使用的方法。

注意:您应该在Key(32字节)和Vector(16字节)数组中使用不同的值!您不希望有人通过假设您按原样使用此代码来弄清楚您的密钥!你所要做的就是改变Key和Vector数组中的一些数字(必须是< = 255)(我在Vector数组中留下了一个无效值,以确保你这样做......)。您可以使用https://www.random.org/bytes/轻松生成新集:

使用它很简单:只需实例化该类,然后调用(通常)EncryptToString(string StringToEncrypt)和DecryptString(string StringToDecrypt)作为方法。一旦你有这个课程,它就不会更容易(或更安全)。


using System;
using System.Data;
using System.Security.Cryptography;
using System.IO;


public class SimpleAES
{
    // Change these keys
    private byte[] Key = __Replace_Me__({ 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 });

    // a hardcoded IV should not be used for production AES-CBC code
    // IVs should be unpredictable per ciphertext
    private byte[] Vector = __Replace_Me__({ 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 2521, 112, 79, 32, 114, 156 });


    private ICryptoTransform EncryptorTransform, DecryptorTransform;
    private System.Text.UTF8Encoding UTFEncoder;

    public SimpleAES()
    {
        //This is our encryption method
        RijndaelManaged rm = new RijndaelManaged();

        //Create an encryptor and a decryptor using our encryption method, key, and vector.
        EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector);
        DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector);

        //Used to translate bytes to text and vice versa
        UTFEncoder = new System.Text.UTF8Encoding();
    }

    /// -------------- Two Utility Methods (not used but may be useful) -----------
    /// Generates an encryption key.
    static public byte[] GenerateEncryptionKey()
    {
        //Generate a Key.
        RijndaelManaged rm = new RijndaelManaged();
        rm.GenerateKey();
        return rm.Key;
    }

    /// Generates a unique encryption vector
    static public byte[] GenerateEncryptionVector()
    {
        //Generate a Vector
        RijndaelManaged rm = new RijndaelManaged();
        rm.GenerateIV();
        return rm.IV;
    }


    /// ----------- The commonly used methods ------------------------------    
    /// Encrypt some text and return a string suitable for passing in a URL.
    public string EncryptToString(string TextValue)
    {
        return ByteArrToString(Encrypt(TextValue));
    }

    /// Encrypt some text and return an encrypted byte array.
    public byte[] Encrypt(string TextValue)
    {
        //Translates our text value into a byte array.
        Byte[] bytes = UTFEncoder.GetBytes(TextValue);

        //Used to stream the data in and out of the CryptoStream.
        MemoryStream memoryStream = new MemoryStream();

        /*
         * We will have to write the unencrypted bytes to the stream,
         * then read the encrypted result back from the stream.
         */
        #region Write the decrypted value to the encryption stream
        CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write);
        cs.Write(bytes, 0, bytes.Length);
        cs.FlushFinalBlock();
        #endregion

        #region Read encrypted value back out of the stream
        memoryStream.Position = 0;
        byte[] encrypted = new byte[memoryStream.Length];
        memoryStream.Read(encrypted, 0, encrypted.Length);
        #endregion

        //Clean up.
        cs.Close();
        memoryStream.Close();

        return encrypted;
    }

    /// The other side: Decryption methods
    public string DecryptString(string EncryptedString)
    {
        return Decrypt(StrToByteArray(EncryptedString));
    }

    /// Decryption when working with byte arrays.    
    public string Decrypt(byte[] EncryptedValue)
    {
        #region Write the encrypted value to the decryption stream
        MemoryStream encryptedStream = new MemoryStream();
        CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write);
        decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length);
        decryptStream.FlushFinalBlock();
        #endregion

        #region Read the decrypted value from the stream.
        encryptedStream.Position = 0;
        Byte[] decryptedBytes = new Byte[encryptedStream.Length];
        encryptedStream.Read(decryptedBytes, 0, decryptedBytes.Length);
        encryptedStream.Close();
        #endregion
        return UTFEncoder.GetString(decryptedBytes);
    }

    /// Convert a string to a byte array.  NOTE: Normally we'd create a Byte Array from a string using an ASCII encoding (like so).
    //      System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    //      return encoding.GetBytes(str);
    // However, this results in character values that cannot be passed in a URL.  So, instead, I just
    // lay out all of the byte values in a long string of numbers (three per - must pad numbers less than 100).
    public byte[] StrToByteArray(string str)
    {
        if (str.Length == 0)
            throw new Exception("Invalid string value in StrToByteArray");

        byte val;
        byte[] byteArr = new byte[str.Length / 3];
        int i = 0;
        int j = 0;
        do
        {
            val = byte.Parse(str.Substring(i, 3));
            byteArr[j++] = val;
            i += 3;
        }
        while (i < str.Length);
        return byteArr;
    }

    // Same comment as above.  Normally the conversion would use an ASCII encoding in the other direction:
    //      System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    //      return enc.GetString(byteArr);    
    public string ByteArrToString(byte[] byteArr)
    {
        byte val;
        string tempStr = "";
        for (int i = 0; i <= byteArr.GetUpperBound(0); i++)
        {
            val = byteArr[i];
            if (val < (byte)10)
                tempStr += "00" + val.ToString();
            else if (val < (byte)100)
                tempStr += "0" + val.ToString();
            else
                tempStr += val.ToString();
        }
        return tempStr;
    }
}

答案 1 :(得分:175)

我清理了SimpleAES(上面)供我使用。固定的复杂加密/解密方法;用于编码字节缓冲区,字符串和URL友好字符串的分离方法;利用现有的库进行URL编码。

代码小,更简单,更快,输出更简洁。例如,johnsmith@gmail.com生成:

SimpleAES: "096114178117140150104121138042115022037019164188092040214235183167012211175176167001017163166152"
SimplerAES: "YHKydYyWaHmKKnMWJROkvFwo1uu3pwzTr7CnARGjppg%3d"

代码:

public class SimplerAES
{
    private static byte[] key = __Replace_Me__({ 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 });

    // a hardcoded IV should not be used for production AES-CBC code
    // IVs should be unpredictable per ciphertext
    private static byte[] vector = __Replace_Me_({ 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 221, 112, 79, 32, 114, 156 });

    private ICryptoTransform encryptor, decryptor;
    private UTF8Encoding encoder;

    public SimplerAES()
    {
        RijndaelManaged rm = new RijndaelManaged();
        encryptor = rm.CreateEncryptor(key, vector);
        decryptor = rm.CreateDecryptor(key, vector);
        encoder = new UTF8Encoding();
    }

    public string Encrypt(string unencrypted)
    {
        return Convert.ToBase64String(Encrypt(encoder.GetBytes(unencrypted)));
    }

    public string Decrypt(string encrypted)
    {
        return encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
    }

    public byte[] Encrypt(byte[] buffer)
    {
        return Transform(buffer, encryptor);
    }

    public byte[] Decrypt(byte[] buffer)
    {
        return Transform(buffer, decryptor);
    }

    protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
    {
        MemoryStream stream = new MemoryStream();
        using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
        {
            cs.Write(buffer, 0, buffer.Length);
        }
        return stream.ToArray();
    }
}

答案 2 :(得分:36)

是的,添加System.Security程序集,导入System.Security.Cryptography命名空间。以下是对称(DES)算法加密的简单示例:

DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.GenerateKey();
byte[] key = des.Key; // save this!

ICryptoTransform encryptor = des.CreateEncryptor();
// encrypt
byte[] enc = encryptor.TransformFinalBlock(new byte[] { 1, 2, 3, 4 }, 0, 4);

ICryptoTransform decryptor = des.CreateDecryptor();

// decrypt
byte[] originalAgain = decryptor.TransformFinalBlock(enc, 0, enc.Length);
Debug.Assert(originalAgain[0] == 1);

答案 3 :(得分:26)

我想通过添加一个在加密字符串中传回的随机IV来补充我已经改进了Mud的SimplerAES。这改进了加密,因为加密相同的字符串每次都会导致不同的输出。

public class StringEncryption
{
    private readonly Random random;
    private readonly byte[] key;
    private readonly RijndaelManaged rm;
    private readonly UTF8Encoding encoder;

    public StringEncryption()
    {
        this.random = new Random();
        this.rm = new RijndaelManaged();
        this.encoder = new UTF8Encoding();
        this.key = Convert.FromBase64String("Your+Secret+Static+Encryption+Key+Goes+Here=");
    }

    public string Encrypt(string unencrypted)
    {
        var vector = new byte[16];
        this.random.NextBytes(vector);
        var cryptogram = vector.Concat(this.Encrypt(this.encoder.GetBytes(unencrypted), vector));
        return Convert.ToBase64String(cryptogram.ToArray());
    }

    public string Decrypt(string encrypted)
    {
        var cryptogram = Convert.FromBase64String(encrypted);
        if (cryptogram.Length < 17)
        {
            throw new ArgumentException("Not a valid encrypted string", "encrypted");
        }

        var vector = cryptogram.Take(16).ToArray();
        var buffer = cryptogram.Skip(16).ToArray();
        return this.encoder.GetString(this.Decrypt(buffer, vector));
    }

    private byte[] Encrypt(byte[] buffer, byte[] vector)
    {
        var encryptor = this.rm.CreateEncryptor(this.key, vector);
        return this.Transform(buffer, encryptor);
    }

    private byte[] Decrypt(byte[] buffer, byte[] vector)
    {
        var decryptor = this.rm.CreateDecryptor(this.key, vector);
        return this.Transform(buffer, decryptor);
    }

    private byte[] Transform(byte[] buffer, ICryptoTransform transform)
    {
        var stream = new MemoryStream();
        using (var cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
        {
            cs.Write(buffer, 0, buffer.Length);
        }

        return stream.ToArray();
    }
}

奖金单元测试

[Test]
public void EncryptDecrypt()
{
    // Arrange
    var subject = new StringEncryption();
    var originalString = "Testing123!£$";

    // Act
    var encryptedString1 = subject.Encrypt(originalString);
    var encryptedString2 = subject.Encrypt(originalString);
    var decryptedString1 = subject.Decrypt(encryptedString1);
    var decryptedString2 = subject.Decrypt(encryptedString2);

    // Assert
    Assert.AreEqual(originalString, decryptedString1, "Decrypted string should match original string");
    Assert.AreEqual(originalString, decryptedString2, "Decrypted string should match original string");
    Assert.AreNotEqual(originalString, encryptedString1, "Encrypted string should not match original string");
    Assert.AreNotEqual(encryptedString1, encryptedString2, "String should never be encrypted the same twice");
}

答案 4 :(得分:12)

Marks(优秀)答案的变体

  • 添加“使用”s
  • 使类IDisposable
  • 删除URL编码代码以使示例更简单。
  • 添加一个简单的测试夹具以演示用法

希望这有帮助

[TestFixture]
public class RijndaelHelperTests
{
    [Test]
    public void UseCase()
    {
        //These two values should not be hard coded in your code.
        byte[] key = {251, 9, 67, 117, 237, 158, 138, 150, 255, 97, 103, 128, 183, 65, 76, 161, 7, 79, 244, 225, 146, 180, 51, 123, 118, 167, 45, 10, 184, 181, 202, 190};
        byte[] vector = {214, 11, 221, 108, 210, 71, 14, 15, 151, 57, 241, 174, 177, 142, 115, 137};

        using (var rijndaelHelper = new RijndaelHelper(key, vector))
        {
            var encrypt = rijndaelHelper.Encrypt("StringToEncrypt");
            var decrypt = rijndaelHelper.Decrypt(encrypt);
            Assert.AreEqual("StringToEncrypt", decrypt);
        }
    }
}

public class RijndaelHelper : IDisposable
{
    Rijndael rijndael;
    UTF8Encoding encoding;

    public RijndaelHelper(byte[] key, byte[] vector)
    {
        encoding = new UTF8Encoding();
        rijndael = Rijndael.Create();
        rijndael.Key = key;
        rijndael.IV = vector;
    }

    public byte[] Encrypt(string valueToEncrypt)
    {
        var bytes = encoding.GetBytes(valueToEncrypt);
        using (var encryptor = rijndael.CreateEncryptor())
        using (var stream = new MemoryStream())
        using (var crypto = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
        {
            crypto.Write(bytes, 0, bytes.Length);
            crypto.FlushFinalBlock();
            stream.Position = 0;
            var encrypted = new byte[stream.Length];
            stream.Read(encrypted, 0, encrypted.Length);
            return encrypted;
        }
    }

    public string Decrypt(byte[] encryptedValue)
    {
        using (var decryptor = rijndael.CreateDecryptor())
        using (var stream = new MemoryStream())
        using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Write))
        {
            crypto.Write(encryptedValue, 0, encryptedValue.Length);
            crypto.FlushFinalBlock();
            stream.Position = 0;
            var decryptedBytes = new Byte[stream.Length];
            stream.Read(decryptedBytes, 0, decryptedBytes.Length);
            return encoding.GetString(decryptedBytes);
        }
    }

    public void Dispose()
    {
        if (rijndael != null)
        {
            rijndael.Dispose();
        }
    }
}

答案 5 :(得分:8)

[编辑]多年以后,我回来说:不要这样做!有关详细信息,请参阅What's wrong with XOR encryption?

非常简单,容易的双向加密是XOR加密。

  1. 拿出密码。让它为mypass
  2. 将密码转换为二进制(根据ASCII)。密码为01101101 01111001 01110000 01100001 01110011 01110011.
  3. 获取您要编码的信息。将其转换为二进制,也是。
  4. 查看邮件的长度。如果消息长度为400字节,则通过反复重复将密码转换为400字节的字符串。它将成为01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 ...(或mypassmypassmypass...
  5. 使用长密码对消息进行异或。
  6. 发送结果。
  7. 另一次,使用相同的密码(mypassmypassmypass...)对加密邮件进行XOR。。
  8. 有你的留言!

答案 6 :(得分:7)

我将几个答案和评论中最好的结合起来。

  • 随机初始化向量前置加密文本(@jbtule)
  • 使用TransformFinalBlock()代替MemoryStream(@RenniePet)
  • 没有预先填好的钥匙,以避免任何人复制&amp;粘贴灾难
  • 妥善处置和使用模式

代码:

/// <summary>
/// Simple encryption/decryption using a random initialization vector
/// and prepending it to the crypto text.
/// </summary>
/// <remarks>Based on multiple answers in http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp </remarks>
public class SimpleAes : IDisposable
{
    /// <summary>
    ///     Initialization vector length in bytes.
    /// </summary>
    private const int IvBytes = 16;

    /// <summary>
    ///     Must be exactly 16, 24 or 32 bytes long.
    /// </summary>
    private static readonly byte[] Key = Convert.FromBase64String("FILL ME WITH 24 (2 pad chars), 32 OR 44 (1 pad char) RANDOM CHARS"); // Base64 has a blowup of four-thirds (33%)

    private readonly UTF8Encoding _encoder;
    private readonly ICryptoTransform _encryptor;
    private readonly RijndaelManaged _rijndael;

    public SimpleAes()
    {
        _rijndael = new RijndaelManaged {Key = Key};
        _rijndael.GenerateIV();
        _encryptor = _rijndael.CreateEncryptor();
        _encoder = new UTF8Encoding();
    }

    public string Decrypt(string encrypted)
    {
        return _encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
    }

    public void Dispose()
    {
        _rijndael.Dispose();
        _encryptor.Dispose();
    }

    public string Encrypt(string unencrypted)
    {
        return Convert.ToBase64String(Encrypt(_encoder.GetBytes(unencrypted)));
    }

    private byte[] Decrypt(byte[] buffer)
    {
        // IV is prepended to cryptotext
        byte[] iv = buffer.Take(IvBytes).ToArray();
        using (ICryptoTransform decryptor = _rijndael.CreateDecryptor(_rijndael.Key, iv))
        {
            return decryptor.TransformFinalBlock(buffer, IvBytes, buffer.Length - IvBytes);
        }
    }

    private byte[] Encrypt(byte[] buffer)
    {
        // Prepend cryptotext with IV
        byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); 
        return _rijndael.IV.Concat(inputBuffer).ToArray();
    }
}

更新2015-07-18:通过@bpsilver和@Evereq的注释修复了私有Encrypt()方法中的错误。 IV被意外加密,现在以Decrypt()预期的明文前缀。

答案 7 :(得分:6)

如果您只是想要简单的加密(即,确定的破解者可能会破坏,但锁定大多数临时用户),只需选择两个相等长度的密码,例如:

deoxyribonucleicacid
while (x>0) { x-- };

和你的数据xor(如有必要,循环密码)(a)。例如:

1111-2222-3333-4444-5555-6666-7777
deoxyribonucleicaciddeoxyribonucle
while (x>0) { x-- };while (x>0) { 

搜索你的二进制文件的人可能会认为DNA字符串是一个关键字,但他们不太可能认为C代码不是用你的二进制文件保存的未初始化的内存。


(a)请记住,这是非常简单加密,并且根据某些定义,可能根本不被视为加密(因为加密的目的是< em>阻止未经授权的访问,而不仅仅是让它变得更加困难)。当然,当有人用钢管架住钥匙扣时,即使是最强大的加密也是不安全的。

如第一句中所述,这是一种让偶然攻击者难以继续前进的手段。它类似于防止家里的盗窃 - 你不需要让它变得坚不可摧,你只需要让它比隔壁的房子更难以预防: - )

答案 8 :(得分:5)

加密很容易:正如其他人所指出的那样,System.Security.Cryptography命名空间中有一些类可以为您完成所有工作。使用它们而不是任何本土解决方案。

但解密也很容易。您遇到的问题不是加密算法,而是保护对用于解密的密钥的访问。

我会使用以下解决方案之一:

  • 使用带有CurrentUser范围的ProtectedData类的DPAPI。这很简单,因为您不必担心密钥。数据只能由同一个用户解密,因此无法在用户或计算机之间共享数据。

  • 使用带有LocalMachine范围的ProtectedData类的DPAPI。适用于例如保护单个安全服务器上的配置数据。但是任何可以登录机器的人都可以加密它,所以除非服务器是安全的,否则没有好处。

  • 任何对称算法。如果我不关心使用什么算法(实际上它默认是Rijndael),我通常使用静态SymmetricAlgorithm.Create()方法。在这种情况下,您需要以某种方式保护您的密钥。例如。你可以用某种方式对它进行模糊处理并将其隐藏在代码中。但要注意,任何聪明到足以反编译代码的人都可能找到密钥。

答案 9 :(得分:5)

我想发布我的解决方案,因为以上解决方案都不像我的那么简单。让我知道你的想法:

 // This will return an encrypted string based on the unencrypted parameter
 public static string Encrypt(this string DecryptedValue)
 {
      HttpServerUtility.UrlTokenEncode(MachineKey.Protect(Encoding.UTF8.GetBytes(DecryptedValue.Trim())));
 }

 // This will return an unencrypted string based on the parameter
 public static string Decrypt(this string EncryptedValue)
 {
      Encoding.UTF8.GetString(MachineKey.Unprotect(HttpServerUtility.UrlTokenDecode(EncryptedValue)));
 }

可选

这假定用于加密该值的服务器的MachineKey与用于解密该值的服务器的MachineKey相同。如果需要,您可以在Web.config中指定静态MachineKey,以便您的应用程序可以解密/加密数据,无论数据在何处运行(例如开发与生产服务器)。你可以generate a static machine key following these instructions

答案 10 :(得分:2)

System.Security.Cryptography 中使用TripleDESCryptoServiceProvider:

public void BackgroundColourEntry()
    {
        while (true)
        {
            if (Name.Text != "" && ClientName.Text != null)
            {
                Name.BackgroundColor = Color.FromHex("#2c3e50");
            }
        }
    }

答案 11 :(得分:1)

我改变了this

public string ByteArrToString(byte[] byteArr)
{
    byte val;
    string tempStr = "";
    for (int i = 0; i <= byteArr.GetUpperBound(0); i++)
    {
        val = byteArr[i];
        if (val < (byte)10)
            tempStr += "00" + val.ToString();
        else if (val < (byte)100)
            tempStr += "0" + val.ToString();
        else
            tempStr += val.ToString();
    }
    return tempStr;
}

到此:

    public string ByteArrToString(byte[] byteArr)
    {
        string temp = "";
        foreach (byte b in byteArr)
            temp += b.ToString().PadLeft(3, '0');
        return temp;
    }

答案 12 :(得分:1)

命名空间System.Security.Cryptography包含TripleDESCryptoServiceProviderRijndaelManaged

不要忘记添加对System.Security程序集的引用。

答案 13 :(得分:1)

使用内置的.Net Cryptography库,此示例显示了如何使用高级加密标准(AES)。

using System;
using System.IO;
using System.Security.Cryptography;

namespace Aes_Example
{
    class AesExample
    {
        public static void Main()
        {
            try
            {

                string original = "Here is some data to encrypt!";

                // Create a new instance of the Aes
                // class.  This generates a new key and initialization 
                // vector (IV).
                using (Aes myAes = Aes.Create())
                {

                    // Encrypt the string to an array of bytes.
                    byte[] encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);

                    // Decrypt the bytes to a string.
                    string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);

                    //Display the original data and the decrypted data.
                    Console.WriteLine("Original:   {0}", original);
                    Console.WriteLine("Round Trip: {0}", roundtrip);
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
        }
        static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key,byte[] IV)
        {
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");
            byte[] encrypted;
            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }


            // Return the encrypted bytes from the memory stream.
            return encrypted;

        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;

        }
    }
}

答案 14 :(得分:0)

我知道你说你并不关心它的安全性,但如果你选择DES,你也可以选择AES,这是更新的加密方法。< / p>

答案 15 :(得分:0)

我一直在使用Mark Brittingham接受的答案,这对我帮助很大。最近我不得不将加密文本发送到另一个组织,这就是出现问题的地方。 OP不需要这些选项,但由于这是一个很受欢迎的问题,我发布了我的修改(EncryptDecrypt来自here的函数):

  1. 每条消息的不同IV - 在获取十六进制之前将IV字节连接到密码字节。 当然,这是一项需要传达给接收密文的各方的惯例。
  2. 允许两个构造函数 - 一个用于默认RijndaelManaged值,另一个可以指定属性值(基于加密和解密方之间的相互协议)
  3. 这是课程(最后的测试样本):

    /// <summary>
    /// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
    /// Uses UTF8 Encoding
    ///  http://security.stackexchange.com/a/90850
    /// </summary>
    public class AnotherAES : IDisposable
    {
        private RijndaelManaged rijn;
    
        /// <summary>
        /// Initialize algo with key, block size, key size, padding mode and cipher mode to be known.
        /// </summary>
        /// <param name="key">ASCII key to be used for encryption or decryption</param>
        /// <param name="blockSize">block size to use for AES algorithm. 128, 192 or 256 bits</param>
        /// <param name="keySize">key length to use for AES algorithm. 128, 192, or 256 bits</param>
        /// <param name="paddingMode"></param>
        /// <param name="cipherMode"></param>
        public AnotherAES(string key, int blockSize, int keySize, PaddingMode paddingMode, CipherMode cipherMode)
        {
            rijn = new RijndaelManaged();
            rijn.Key = Encoding.UTF8.GetBytes(key);
            rijn.BlockSize = blockSize;
            rijn.KeySize = keySize;
            rijn.Padding = paddingMode;
            rijn.Mode = cipherMode;
        }
    
        /// <summary>
        /// Initialize algo just with key
        /// Defaults for RijndaelManaged class: 
        /// Block Size: 256 bits (32 bytes)
        /// Key Size: 128 bits (16 bytes)
        /// Padding Mode: PKCS7
        /// Cipher Mode: CBC
        /// </summary>
        /// <param name="key"></param>
        public AnotherAES(string key)
        {
            rijn = new RijndaelManaged();
            byte[] keyArray = Encoding.UTF8.GetBytes(key);
            rijn.Key = keyArray;
        }
    
        /// <summary>
        /// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
        /// Encrypt a string using RijndaelManaged encryptor.
        /// </summary>
        /// <param name="plainText">string to be encrypted</param>
        /// <param name="IV">initialization vector to be used by crypto algorithm</param>
        /// <returns></returns>
        public byte[] Encrypt(string plainText, byte[] IV)
        {
            if (rijn == null)
                throw new ArgumentNullException("Provider not initialized");
    
            // Check arguments.
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText cannot be null or empty");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV cannot be null or empty");
            byte[] encrypted;
    
            // Create a decrytor to perform the stream transform.
            using (ICryptoTransform encryptor = rijn.CreateEncryptor(rijn.Key, IV))
            {
                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }
            // Return the encrypted bytes from the memory stream.
            return encrypted;
        }//end EncryptStringToBytes
    
        /// <summary>
        /// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
        /// </summary>
        /// <param name="cipherText">bytes to be decrypted back to plaintext</param>
        /// <param name="IV">initialization vector used to encrypt the bytes</param>
        /// <returns></returns>
        public string Decrypt(byte[] cipherText, byte[] IV)
        {
            if (rijn == null)
                throw new ArgumentNullException("Provider not initialized");
    
            // Check arguments.
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText cannot be null or empty");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("IV cannot be null or empty");
    
            // Declare the string used to hold the decrypted text.
            string plaintext = null;
    
            // Create a decrytor to perform the stream transform.
            using (ICryptoTransform decryptor = rijn.CreateDecryptor(rijn.Key, IV))
            {
                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {
                            // Read the decrypted bytes from the decrypting stream and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }
            }
    
            return plaintext;
        }//end DecryptStringFromBytes
    
        /// <summary>
        /// Generates a unique encryption vector using RijndaelManaged.GenerateIV() method
        /// </summary>
        /// <returns></returns>
        public byte[] GenerateEncryptionVector()
        {
            if (rijn == null)
                throw new ArgumentNullException("Provider not initialized");
    
            //Generate a Vector
            rijn.GenerateIV();
            return rijn.IV;
        }//end GenerateEncryptionVector
    
    
        /// <summary>
        /// Based on https://stackoverflow.com/a/1344255
        /// Generate a unique string given number of bytes required.
        /// This string can be used as IV. IV byte size should be equal to cipher-block byte size. 
        /// Allows seeing IV in plaintext so it can be passed along a url or some message.
        /// </summary>
        /// <param name="numBytes"></param>
        /// <returns></returns>
        public static string GetUniqueString(int numBytes)
        {
            char[] chars = new char[62];
            chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
            byte[] data = new byte[1];
            using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
            {
                data = new byte[numBytes];
                crypto.GetBytes(data);
            }
            StringBuilder result = new StringBuilder(numBytes);
            foreach (byte b in data)
            {
                result.Append(chars[b % (chars.Length)]);
            }
            return result.ToString();
        }//end GetUniqueKey()
    
        /// <summary>
        /// Converts a string to byte array. Useful when converting back hex string which was originally formed from bytes.
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public static byte[] StringToByteArray(String hex)
        {
            int NumberChars = hex.Length;
            byte[] bytes = new byte[NumberChars / 2];
            for (int i = 0; i < NumberChars; i += 2)
                bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            return bytes;
        }//end StringToByteArray
    
        /// <summary>
        /// Dispose RijndaelManaged object initialized in the constructor
        /// </summary>
        public void Dispose()
        {
            if (rijn != null)
                rijn.Dispose();
        }//end Dispose()
    }//end class
    

    和..

    以下为测试样本:

    class Program
    {
        string key;
        static void Main(string[] args)
        {
            Program p = new Program();
    
            //get 16 byte key (just demo - typically you will have a predetermined key)
            p.key = AnotherAES.GetUniqueString(16);
    
            string plainText = "Hello World!";
    
            //encrypt
            string hex = p.Encrypt(plainText);
    
            //decrypt
            string roundTrip = p.Decrypt(hex);
    
            Console.WriteLine("Round Trip: {0}", roundTrip);
        }
    
        string Encrypt(string plainText)
        {
            Console.WriteLine("\nSending (encrypt side)...");
            Console.WriteLine("Plain Text: {0}", plainText);
            Console.WriteLine("Key: {0}", key);
            string hex = string.Empty;
            string ivString = AnotherAES.GetUniqueString(16);
            Console.WriteLine("IV: {0}", ivString);
            using (AnotherAES aes = new AnotherAES(key))
            {
                //encrypting side
                byte[] IV = Encoding.UTF8.GetBytes(ivString);
    
                //get encrypted bytes (IV bytes prepended to cipher bytes)
                byte[] encryptedBytes = aes.Encrypt(plainText, IV);
                byte[] encryptedBytesWithIV = IV.Concat(encryptedBytes).ToArray();
    
                //get hex string to send with url
                //this hex has both IV and ciphertext
                hex = BitConverter.ToString(encryptedBytesWithIV).Replace("-", "");
                Console.WriteLine("sending hex: {0}", hex);
            }
    
            return hex;
        }
    
        string Decrypt(string hex)
        {
            Console.WriteLine("\nReceiving (decrypt side)...");
            Console.WriteLine("received hex: {0}", hex);
            string roundTrip = string.Empty;
            Console.WriteLine("Key " + key);
            using (AnotherAES aes = new AnotherAES(key))
            {
                //get bytes from url
                byte[] encryptedBytesWithIV = AnotherAES.StringToByteArray(hex);
    
                byte[] IV = encryptedBytesWithIV.Take(16).ToArray();
    
                Console.WriteLine("IV: {0}", System.Text.Encoding.Default.GetString(IV));
    
                byte[] cipher = encryptedBytesWithIV.Skip(16).ToArray();
    
                roundTrip = aes.Decrypt(cipher, IV);
            }
            return roundTrip;
        }
    }
    

    enter image description here

答案 16 :(得分:-2)

我认为这是世界上最简单的一个!

string encrypted = "Text".Aggregate("", (c, a) => c + (char) (a + 2));

测试

 Console.WriteLine(("Hello").Aggregate("", (c, a) => c + (char) (a + 1)));
            //Output is Ifmmp
 Console.WriteLine(("Ifmmp").Aggregate("", (c, a) => c + (char)(a - 1)));
            //Output is Hello