在C#中将字符串加密为URL

时间:2011-06-15 16:39:50

标签: c# encryption

现在,我一直在寻找将字符串加密到URL的完美方法。这是我找到的方法

Best method I found and it's on stackoverflow

    using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web;

public class SimplerAES
{
   private static byte[] key = { 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 };
   private static byte[] vector = { 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 string EncryptToUrl(string unencrypted)
   { 
      return HttpUtility.UrlEncode(Encrypt(unencrypted));
   }

   public string DecryptFromUrl(string encrypted)
   {
      return Decrypt(HttpUtility.UrlDecode(encrypted));
   }

   public byte[] Encrypt(byte[] buffer)
   {
      MemoryStream encryptStream = new MemoryStream();
      using (CryptoStream cs = new CryptoStream(encryptStream, encryptor, CryptoStreamMode.Write))
      {
         cs.Write(buffer, 0, buffer.Length);
      }
      return encryptStream.ToArray();
   }

   public byte[] Decrypt(byte[] buffer)
   {
      MemoryStream decryptStream = new MemoryStream();
      using (CryptoStream cs = new CryptoStream(decryptStream, decryptor, CryptoStreamMode.Write))
      {
         cs.Write(buffer, 0, buffer.Length);
      }
      return decryptStream.ToArray();
   }
}

现在,当我查看使用

生成的加密字符串时
    var a1 = _aes.EncryptToUrl("aaa");
    var a2 = _aes.EncryptToUrl("aaaa");
    var a3 = _aes.EncryptToUrl("aaaaa");
    var a4 = _aes.EncryptToUrl("aaaaaa");
    var a5 = _aes.EncryptToUrl("aaaaaaa");
    var a6 = _aes.EncryptToUrl("aaaaaaaa");
    var a7 = _aes.EncryptToUrl("aaaaaaaaa");
    var a8 = _aes.EncryptToUrl("aaaaaaaaaa");
    var a9 = _aes.EncryptToUrl("aaaaaaaaaaa");
    var a10 = _aes.EncryptToUrl("aaaaaaaaaaa");
    var a11 = _aes.EncryptToUrl("aaaaaaaaaaaa");
    var a12 = _aes.EncryptToUrl("aaaaaaaaaaaaa");
    var a13 = _aes.EncryptToUrl("aaaaaaaaaaaaaa");

所有字符串(var a1至a13)以“%3d%3d”

结尾

由于节省存储空间对于此应用程序非常重要,我想知道我是否可以删除“%3d%3d”并在解码之前添加它以返回到原始URL。

任何人都可以就此提出一些建议。

谢谢,

2 个答案:

答案 0 :(得分:6)

正如安德鲁所说,这是在base64末尾的填充。但是,我不同意他的结论。

我们知道格式良好的base64字符串总是4个字符的倍数。因此,只要我们可以信任我们一次性获得所有数据(即我们相信我们的URL没有被截断),我们可以在编码之前从base64字符串中删除任何尾随的'='字符。 URL。但是,在我们稍后调用Convert.FromBase64String之前,我们需要将这些字符放回。幸运的是,我们可以这样做,因为我们知道根据我们得到的字符串的长度将有多少。你可以这样做,即使原始长度不是不变,即使在你的情况下也是如此。

另一个小问题 - “普通”base64字母对于网址来说不是很好;您可能希望使用替代版本,如described in Wikipedia

  

在URL中使用标准Base64需要将'+','/'和'='字符编码为特殊的百分比编码十六进制序列('+'='%2B','/'='%2F'和' ='='%3D'),这使得字符串不必要地更长。   出于这个原因,存在修改后的Base64 for URL变体,其中不使用填充'=',标准Base64的'+'和'/'字符分别被' - '和'_'替换,因此使用URL编码器/解码器不再是必需的,并且对编码值的长度没有影响,保留相同的编码形式,通常用于关系数据库,Web表单和对象标识符。

知道 .NET中的任何内容,这使得这样做很容易。最简单的方法是执行正常的base64转换,将+替换为 - ,/替换为_,然后使用string.TrimEnd从末尾删除=符号,并使用相反的解码操作。这比手动编码版本效率低得多,但考虑到你将使用的数据大小,它可能无关紧要。

答案 1 :(得分:1)

加密字符串末尾的数据是padding的示例。您必须保持字符串不变。