Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 简单不安全的双向数据”;混淆;?_C#_Obfuscation - Fatal编程技术网

C# 简单不安全的双向数据”;混淆;?

C# 简单不安全的双向数据”;混淆;?,c#,obfuscation,C#,Obfuscation,我正在寻找一些数据的非常简单的模糊处理(如加密和解密,但不一定是安全的)功能。这不是关键任务。我需要一些能让诚实的人保持诚实的东西,但要比或强一点 我更喜欢框架2.0中已经包含的东西,所以我不必担心任何外部依赖 我真的不想乱搞公钥/私钥等。我对加密知之甚少,但我知道我写的任何东西都毫无价值。。。事实上,我可能会把数学搞砸,让它变得微不足道。名称空间System.Security.Cryptography包含TripledScryptoServiceProvider和RijndaelManaged

我正在寻找一些数据的非常简单的模糊处理(如加密和解密,但不一定是安全的)功能。这不是关键任务。我需要一些能让诚实的人保持诚实的东西,但要比或强一点

我更喜欢框架2.0中已经包含的东西,所以我不必担心任何外部依赖


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

名称空间
System.Security.Cryptography
包含
TripledScryptoServiceProvider
RijndaelManaged


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

是的,添加
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);

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

deoxyribonucleicacid
while (x>0) { x-- };
并将您的数据与它们进行异或(必要时循环密码短语)(a)。例如:

1111-2222-3333-4444-5555-6666-7777
deoxyribonucleicaciddeoxyribonucle
while (x>0) { x-- };while (x>0) { 
搜索二进制文件的人可能会认为DNA字符串是一个键,但他们不太可能认为C代码不是二进制文件保存的未初始化内存


(a) 请记住,这是一种非常简单的加密,根据某些定义,可能根本不被视为加密(因为加密的目的是防止未经授权的访问,而不仅仅是增加访问的难度)。当然,当有人拿着钢管站在密钥持有者上方时,即使是最强大的加密也是不安全的


如第一句所述,这是一种使偶然的攻击者难以继续前进的手段。这类似于防止你家的入室盗窃-你不需要让它牢不可破,你只需要让它比隔壁的房子更不容易怀孕:-)

我知道你说过你不在乎它有多安全,但是,如果您选择了,您也可以采用更为最新的加密方法。

加密很简单:正如其他人所指出的,System.Security.Cryptography命名空间中的类为您完成了所有工作。使用它们,而不是任何国产解决方案

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

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

  • DPAPI使用具有CurrentUser作用域的ProtectedData类。这很容易,因为您不需要担心钥匙。数据只能由同一用户解密,因此不利于在用户或机器之间共享数据

  • DPAPI使用具有LocalMachine作用域的ProtectedData类。适用于保护单个安全服务器上的配置数据。但是任何可以登录到这台机器的人都可以对它进行加密,因此,除非服务器是安全的,否则没有任何好处

  • 任何对称算法。如果我不在乎使用什么算法(事实上,默认情况下它是Rijndael),我通常会使用静态Symmetrialgorithm.Create()方法。在这种情况下,您需要以某种方式保护您的密钥。例如,您可以以某种方式混淆它,并将其隐藏在代码中。但是请注意,任何足够聪明的人,只要能够反编译您的代码,都有可能找到密钥


这里的其他答案很好,但AES是一种更安全和最新的加密算法。这是我几年前获得的一个类,用于执行AES加密,随着时间的推移,我对该类进行了修改,使其对web应用程序更加友好(例如,我构建了使用URL友好字符串的加密/解密方法)。它还有处理字节数组的方法


注意:您应该在键(32字节)和向量(16字节)数组中使用不同的值!你不会希望有人通过假设你按原样使用这段代码来找出你的密钥!您所要做的就是更改一些数字(必须是[EDIT]年后,我回来告诉您:不要这样做!有关详细信息,请参阅

一个非常简单、简单的双向加密是XOR加密

  • 想出一个密码。让它成为
    mypass

  • 将密码转换为二进制(根据ASCII)。密码将变为011011101011110000 01100001 011110011 011110011。
  • 把你想编码的信息也转换成二进制。
  • 查看消息的长度。如果消息长度为400字节,则通过反复重复将密码转换为400字节字符串。它将变成011011110001 011110000 0111000001 011110011 011110011 011010101101 011110001 011110001 011110000 0111000001 011110011 011010101101 011110011 011101101 011110001 011110000 011110011 011110011 011110011。。。(或
    mypassmypass…

  • 用长密码对消息执行XOR操作。
  • 发送结果。
  • 另一次,使用相同的密码对加密邮件进行异或操作(
    mypassmypass…
    )。
  • 这是你的留言
  • 我改变了:

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

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

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

    分数的变体(优秀)答案

    • 添加“使用”s
    • 使类IDisposable
    • 删除URL编码代码以简化示例
    • 将一个简单的测试夹具添加到
      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;
          }
      
      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();
          }
      }
      
      [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();
              }
          }
      }
      
      /// <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();
          }
      }
      
      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
      
       // 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)));
       }
      
      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;
      
              }
          }
      }
      
      /// <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;
          }
      }
      
      public static class CryptoHelper
      {
          private const string Key = "MyHashString";
          private static TripleDESCryptoServiceProvider GetCryproProvider()
          {
              var md5 = new MD5CryptoServiceProvider();
              var key = md5.ComputeHash(Encoding.UTF8.GetBytes(Key));
              return new TripleDESCryptoServiceProvider() { Key = key, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
          }
      
          public static string Encrypt(string plainString)
          {
              var data = Encoding.UTF8.GetBytes(plainString);
              var tripleDes = GetCryproProvider();
              var transform = tripleDes.CreateEncryptor();
              var resultsByteArray = transform.TransformFinalBlock(data, 0, data.Length);
              return Convert.ToBase64String(resultsByteArray);
          }
      
          public static string Decrypt(string encryptedString)
          {
              var data = Convert.FromBase64String(encryptedString);
              var tripleDes = GetCryproProvider();
              var transform = tripleDes.CreateDecryptor();
              var resultsByteArray = transform.TransformFinalBlock(data, 0, data.Length);
              return Encoding.UTF8.GetString(resultsByteArray);
          }
      }