0

I am using a below encryption technique to encryot a query string value in MVC application.

So the url will be something like controller/details/rlSRlRZwzbU%3d

But when param =2 and KEY=mcbgp23njwmcinu0tij05vc2 this function returns UhMZc7/MNK8=.

So the formatted url will be controller/details/UhMZc7/MNK8%3d and giving 404 Error

public static string Encrypt(string dataStr)
    {
        Byte[] inputByteArray = Encoding.ASCII.GetBytes(dataStr);
        var mstr = new MemoryStream();

        string KEY = HttpContext.Current.Session.SessionID;
        var key = Encoding.ASCII.GetBytes(KEY.Substring(0, 8));

        var des = new DESCryptoServiceProvider();           
        var cstr = new CryptoStream(mstr, des.CreateEncryptor(key, key), CryptoStreamMode.Write);
        cstr.Write(inputByteArray, 0, inputByteArray.Length);
        cstr.FlushFinalBlock();
        return Convert.ToBase64String(ms.ToArray());
    }

How can I make this function to be MVC URL safe? Is there any other good technique to produce the url-safe encrypted format?

Edit:

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

         routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );
    }
Billa
  • 5,226
  • 23
  • 61
  • 105
  • Show your route mappings – Carlos Landeras Jun 12 '14 at 15:59
  • @CarlosLanderas, Added route mapping – Billa Jun 12 '14 at 16:09
  • I'd use url safe Base64 encoding as described at [Need an Encryption/decryption method does not have a '/' in the encrypted string](http://stackoverflow.com/questions/15109313/need-an-encryption-decryption-method-does-not-have-a-in-the-encrypted-string) – CodesInChaos Jun 12 '14 at 16:38
  • I also want to note that your crypto sucks. Barely stronger than Caesar encryption. 1) DES has far too small keys (use AES) 2) the lack of MAC enables padding oracles (use authenticated encryption) 3) You silently corrupt non ASCII input (Use UTF8) 4) You use the same value as key and IV. You should use a new random IV for each message you encrypt. 5) You use an ASCII string as key. Keys are binary, use Base64 encoded random values instead. 6) No need for the streams. Just call `encryptor.TransformFinalBlock` instead. – CodesInChaos Jun 12 '14 at 16:43
  • @CodesInChaos, your steps are sounds good. Can you provide me a code/article for the implementation? I will follow that as I am new to development and not much aware of the encryption techniques :( – Billa Jun 12 '14 at 16:46
  • For the encryption part [jbtule's answer to *Encrypt and decrypt a string*](http://stackoverflow.com/a/10366194/445517) for the url safe base64 encoding the question I linked. – CodesInChaos Jun 12 '14 at 16:57
  • @CodesInChaos, what about using the answer http://stackoverflow.com/a/2791259/1909604 – Billa Jun 12 '14 at 17:09
  • Still lacks the MAC. jbtule's answer is one of the few decent answers. Most others have severe flaws. – CodesInChaos Jun 12 '14 at 17:11

1 Answers1

3

The problem is that Base64 encoding uses the / and + characters, which are special characters in URLs. The typical way to fix this is to use a modified Base64 encoding that converts / to _ and '+' to '-'. This is called "base64url" encoding. See the variants summary table in the Wikipedia article.

You can do this with two simple methods:

static string ToBase64Url(string base64)
{
    return base64.Replace("/", "_").Replace("+", "-");
}

static string FromBase64Url(string base64Url)
{
    return base64Url.Replace("_", "/").Replace("-", "+");
}

In your code, then, you would replace this line:

return Convert.ToBase64String(ms.ToArray());

with:

return ToBase64Url(Convert.ToBase64String(ms.ToArray()));

And, of course, you'd have to decode it correctly on the other side: convert from Base64Url to standard Base64, and then convert that to a byte array.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • Thanks Jim. Do you have any idea about @CodesInChaos comment about AES technique? – Billa Jun 12 '14 at 16:49
  • @Billa: I don't know enough about crypto to comment on that. Regardless of the crypto you use, you still need to base64 encode the binary result, and that means you'll have to use this technique or something similar to map the offending characters. I suppose you could write your own base62 encoder/decoder, but that seems like overkill. – Jim Mischel Jun 12 '14 at 16:52