几个小时以来,我一直在寻找将字符串加密到URL的完美方法.这是我找到的方法
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.
任何人都可以给我一些建议.
谢谢,
正如安德鲁所说,这是在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删除=符号,使用反向操作进行解码.这比手动编码版本效率低得多,但考虑到你将使用的数据大小,它可能无关紧要.