问题描述
|
许多小时以来,我一直在寻找将字符串加密为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,175,144,173,53,196,29,17,218,131,236,209 };
private static byte[] vector = { 146,64,191,111,23,3,113,119,231,121,221,79,32,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,buffer.Length);
}
return encryptStream.ToArray();
}
public byte[] Decrypt(byte[] buffer)
{
MemoryStream decryptStream = new MemoryStream();
using (CryptoStream cs = new CryptoStream(decryptStream,decryptor,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。
谁能给我一些建议。
谢谢,
解决方法
正如安德鲁所说,这是在base64末尾填充的。但是,我不同意他的结论。
我们知道,格式正确的base64字符串始终是4个字符的倍数。因此,只要我们可以相信一次就能获得所有数据(即我们相信URL不会被截断),我们就可以在base64字符串中去除任何尾随\'= \'字符,然后再执行操作将其编码为网址。但是,我们需要放回这些字符,然后再调用call2ѭ。幸运的是,我们能够做到这一点,因为我们根据所拥有的字符串的长度知道会有多少个字符串。即使原始长度不是恒定的,也可以执行此操作,即使您的情况是这样。
另一个要点-URL的\“ normal \” base64字母不是很好。您可能要使用替代版本,如Wikipedia中所述:
在URL中使用标准Base64要求将\'+ \',\'/ \'和\'= \'字符编码为特殊的百分比编码十六进制序列(\'+ \'= \'%2B \',\'/ \'= \'%2F \'和\'= \'= \'%3D \'),这会使字符串不必要地变长。
因此,存在针对URL变体的修改的Base64,其中不使用填充\'= \',标准Base64的\'+ \'和\'/ \'字符分别替换为\'-\'和\'_ \',因此不再需要使用URL编码器/解码器,并且对编码值的长度没有影响,从而使相同的编码形式完整地保留在关系数据库,Web表单和对象标识符中。
我对.NET中的任何内容一无所知,这使得高效地做到这一点变得容易。最简单的方法是执行常规的base64转换,用-替换+,用_替换/,然后使用
string.TrimEnd
从末尾删除=
符号,并进行相反的解码操作。这比手工编码的版本效率要低得多,但是鉴于要使用的数据量,这可能并不重要。
, 加密字符串末尾的数据就是填充的示例。您必须保留字符串原样。