Search code examples
c#url-shortener

c# shorten query string parameter


I need to pass a URL as a parameter into my querystring, since the URLs can be long I need to shorten the URL while passing and then be able to decrypt them on server side.

The URL that I am trying to pass does not contain sensitive information so string encryption techniques are not required, I am just looking to convert a long string to a short string and be able to reconstruct it back to a string.

I have tried AES encryption and it works but the resulting string is sometimes longer than the URL value itself.

Example of what I've tried so far :

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();
}

Example TEST :

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" 

The actual string is 112 charachters long and the result is 165 charahcters long.


Solution

  • The following code is taken verbatim from here. I duplicated this because the question is not a duplicate but the answer solves the problem this question poses. When you call Zip you will need to base64 encode the result to make it friendly for a browser if you plan to include it in a URL or something.

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