2

我需要将 URL 作为参数传递到我的查询字符串中,因为 URL 可能很长,我需要在传递时缩短 URL,然后能够在服务器端解密它们。

我尝试传递的 URL包含敏感信息,因此不需要字符串加密技术,我只是希望将长字符串转换为短字符串并能够将其重建回字符串。

我尝试过 AES 加密,它可以工作,但结果字符串有时比 URL 值本身长。

到目前为止我尝试过的示例:

private static byte[] key = { 252, 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 = { 152, 64, 191, 111, 23, 3, 113, 119, 231, 121, 221, 112, 79, 32, 114, 156 };
private ICryptoTransform encryptor, decryptor;
private UTF8Encoding encoder;

public SimpleAES()
{
    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)
{
    return Transform(buffer, encryptor);
}

public byte[] Decrypt(byte[] buffer)
{
    return Transform(buffer, decryptor);
}

protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
{
    MemoryStream stream = new MemoryStream();
    using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
    {
        cs.Write(buffer, 0, buffer.Length);
    }
    return stream.ToArray();
}

示例测试:

string unencrypted = "/exampleurl/this_is_a_long_string_the_length_of_this_url_is_112_charachters_/this_string_needs_to_be-shortened/"; 

var result = EncryptToUrl(unencrypted);    
"MHMyQdwbJpw8ah%2fbhAr2eJwTFa%2fyupemjuOVcBJmxTIdzcR0PZKCNSa5Fvi7kNrY3Kxlk5KWqAAEspWVtJfNjwwPs%2bCDGpC9Fn8CeGezWhXEbLT6CST2v%2fKpvptHVi3fBYSk1w3q1FYMx3C5DdKueQ%3d%3d" 

实际字符串为 112 个字符长,结果为 165 个字符长。

4

2 回答 2

3

以下代码是从这里逐字获取的。我重复了这个,因为问题不是重复的,但答案解决了这个问题带来的问题。当您打电话时Zip,如果您打算将结果包含在 URL 或其他内容中,则需要对结果进行 base64 编码以使其对浏览器友好。

public static void CopyTo(Stream src, Stream dest) {
    byte[] bytes = new byte[4096];

    int cnt;

    while ((cnt = src.Read(bytes, 0, bytes.Length)) != 0) {
        dest.Write(bytes, 0, cnt);
    }
}

public static byte[] Zip(string str) {
    var bytes = Encoding.UTF8.GetBytes(str);

    using (var msi = new MemoryStream(bytes))
    using (var mso = new MemoryStream()) {
        using (var gs = new GZipStream(mso, CompressionMode.Compress)) {
            //msi.CopyTo(gs);
            CopyTo(msi, gs);
        }

        return mso.ToArray();
    }
}

public static string Unzip(byte[] bytes) {
    using (var msi = new MemoryStream(bytes))
    using (var mso = new MemoryStream()) {
        using (var gs = new GZipStream(msi, CompressionMode.Decompress)) {
            //gs.CopyTo(mso);
            CopyTo(gs, mso);
        }

        return Encoding.UTF8.GetString(mso.ToArray());
    }
}

static void Main(string[] args) {
    byte[] r1 = Zip("StringStringStringStringStringStringStringStringStringStringStringStringStringString");
    string r2 = Unzip(r1);
}
于 2013-11-07T16:23:10.217 回答
1

这听起来可能很奇怪,但是您可以将查询字符串存储在数据库中并通过某个主键引用它吗?这可能类似于使用某些第三方 URL 缩短服务。

于 2013-11-07T16:26:52.337 回答