将字符串加密到C#中的URL

本文关键字:中的 URL 字符串 加密 | 更新日期: 2023-09-27 17:59:17

几个小时以来,我一直在寻找将字符串加密到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();
   }
}

现在,当我看到产生的加密字符串时

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

所有字符串(变量a1到a13)都以"%3d%3d"结束

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

有人能给我一些建议吗。

谢谢,

将字符串加密到C#中的URL

正如Andrew所说,这是base64末尾的填充。然而,我不同意他的结论。

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

另一个小问题是,"正常"的base64字母表对URL来说不太好;你可能想使用一个替代版本,如维基百科所述:

在URL中使用标准Base64需要将"+"、"/"answers"="字符编码为特殊百分比编码的十六进制序列("+"="%2B"、"/'="%2F"answers"='="%3D"),这会使字符串不必要地变长。因此,存在针对URL变体的修改后的Base64,其中不会使用填充"=",标准Base64的"+"answers"/"字符分别替换为"-"answers"_",因此不再需要使用URL编码器/解码器,也不会对编码值的长度产生影响,使相同的编码形式保持不变,可用于关系数据库、web表单,以及一般的对象标识符。

我不知道.NET中有什么东西让这件事变得容易高效。最简单的方法是执行普通的base64转换,将+替换为-,/替换为_,然后使用string.TrimEnd从末尾移除=符号,并使用相反的操作进行解码。这比手工编码的版本效率低得多,但考虑到您将要处理的数据的大小,这可能无关紧要。

加密字符串末尾的数据就是填充的示例。您必须保持字符串原样。