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

Emi*_*ily 6 c# encryption

几个小时以来,我一直在寻找将字符串加密到URL的完美方法.这是我找到的方法

我找到的最好的方法,它在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();
   }
}
Run Code Online (Sandbox Code Playgroud)

现在,当我查看生成的加密字符串时

    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");
Run Code Online (Sandbox Code Playgroud)

所有字符串(var a1到a13)以"%3d%3d"结尾

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

任何人都可以给我一些建议.

谢谢,

Jon*_*eet 6

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

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

另一个小问题 - "普通"base64字母对于URL来说不是很好; 您可能想要使用替代版本,如维基百科中所述:

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

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