1

I am attempting to utilize the code from a tutorial and I keep getting a couple errors that I can't figure out how to solve.

The following line is failing to execute:

inputByte = Convert.FromBase64String(encryptedText);

It provides this error:

Invalid length for a Base-64 char array or string.

Next, this line is also failing to execute.

Dictionary decryptedParameters = new Dictionary();

And the error being returned is:

Index was outside the bounds of the array.

How can I go about fixing this?


Class EncryptedActionParameterAttribute:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Web.Mvc;
using WebMatrix.WebData;
using Medi.Models;
using System.Security.Cryptography;
using System.IO;

namespace Medi.Filters
  {

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class EncryptedActionParameterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {

        Dictionary<string, object> decryptedParameters = new Dictionary<string, object>();
        if (HttpContext.Current.Request.QueryString.Get("q") != null)
        {
            string encryptedQueryString = HttpContext.Current.Request.QueryString.Get("q");
            string decrptedString = Decrypt(encryptedQueryString.ToString());
            string[] paramsArrs = decrptedString.Split('?');

            for (int i = 0; i < paramsArrs.Length; i++)
            {
                string[] paramArr = paramsArrs[i].Split('=');
                decryptedParameters.Add(paramArr[0], Convert.ToInt32(paramArr[1]));
            }
        }
        for (int i = 0; i < decryptedParameters.Count; i++)
        {
            filterContext.ActionParameters[decryptedParameters.Keys.ElementAt(i)] = decryptedParameters.Values.ElementAt(i);
        }
        base.OnActionExecuting(filterContext);

    }

    private string Decrypt(string encryptedText)
    {
        string key = "jdsg432387#";
        byte[] DecryptKey = { };
        byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
        byte[] inputByte = new byte[encryptedText.Length];

        DecryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        inputByte = Convert.FromBase64String(encryptedText);
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(DecryptKey, IV), CryptoStreamMode.Write);
        cs.Write(inputByte, 0, inputByte.Length);
        cs.FlushFinalBlock();
        System.Text.Encoding encoding = System.Text.Encoding.UTF8;
        return encoding.GetString(ms.ToArray());
    }
}
}

MyExtensions Class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Text;
using System.Web.Routing;
using System.Security.Cryptography;
using System.IO;

namespace Medi.Models
{
public static class MyExtensions
{
    public static MvcHtmlString EncodedActionLink(this HtmlHelper htmlHelper, string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
    {
        string queryString = string.Empty;
        string htmlAttributesString = string.Empty;
        string AreaName = string.Empty;
        if (routeValues != null)
        {
            RouteValueDictionary d = new RouteValueDictionary(routeValues);
            for (int i = 0; i < d.Keys.Count; i++)
            {
                string elementName = d.Keys.ElementAt(i).ToLower();
                if (elementName == "area")
                {
                    AreaName = Convert.ToString(d.Values.ElementAt(i));
                    continue;
                }
                if (i > 0)
                {
                    queryString += "?";
                }
                queryString += d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
            }
        }

        if (htmlAttributes != null)
        {
            RouteValueDictionary d = new RouteValueDictionary(htmlAttributes);
            for (int i = 0; i < d.Keys.Count; i++)
            {
                htmlAttributesString += " " + d.Keys.ElementAt(i) + "=" + d.Values.ElementAt(i);
            }
        }

        //<a href="/Answer?questionId=14">What is Entity Framework??</a>
        StringBuilder ancor = new StringBuilder();
        ancor.Append("<a ");
        if (htmlAttributesString != string.Empty)
        {
            ancor.Append(htmlAttributesString);
        }
        ancor.Append(" href='");
        if (AreaName != string.Empty)
        {
            ancor.Append("/" + AreaName);
        }
        if (controllerName != string.Empty)
        {
            ancor.Append("/" + controllerName);
        }

        if (actionName != "Index")
        {
            ancor.Append("/" + actionName);
        }
        if (queryString != string.Empty)
        {
            ancor.Append("?q=" + Encrypt(queryString));
        }
        ancor.Append("'");
        ancor.Append(">");
        ancor.Append(linkText);
        ancor.Append("</a>");
        return new MvcHtmlString(ancor.ToString());
    }

    private static string Encrypt(string plainText)
    {
        string key = "jdsg432387#";
        byte[] EncryptKey = { };
        byte[] IV = { 55, 34, 87, 64, 87, 195, 54, 21 };
        EncryptKey = System.Text.Encoding.UTF8.GetBytes(key.Substring(0, 8));
        DESCryptoServiceProvider des = new DESCryptoServiceProvider();
        byte[] inputByte = Encoding.UTF8.GetBytes(plainText);
        MemoryStream mStream = new MemoryStream();
        CryptoStream cStream = new CryptoStream(mStream, des.CreateEncryptor(EncryptKey, IV), CryptoStreamMode.Write);
        cStream.Write(inputByte, 0, inputByte.Length);
        cStream.FlushFinalBlock();
        return Convert.ToBase64String(mStream.ToArray());
    }
}
}
matt.
  • 2,355
  • 5
  • 32
  • 43
Sam khan
  • 220
  • 4
  • 17

1 Answers1

1

I suspect the Invalid length error on the Base64 is caused from some of the '=' signs being dropped from the query string.

This answer explains it nicely.

The length of a base64 encoded string is always a multiple of 4. If it is not a multiple of 4, then = characters are appended until it is. A query string of the form ?name=value has problems when the value contains = charaters (some of them will be dropped, I don't recall the exact behavior). You may be able to get away with appending the right number of = characters before doing the base64 decode.

As far as your Dictionary goes, you haven't supplied any type parameters, the compiler doesn't know what you want..

Try supplying the types like this:

Dictionary<string, string> decryptedParameters = new Dictionary<string, string>();
Community
  • 1
  • 1
matt.
  • 2,355
  • 5
  • 32
  • 43