Comment crypter les paramètres d'une Querystring - ASP.NET/C#

Publié le 04 décembre 2007 par Olivier Duval

Pourquoi encrypter une URL ?

Il peut être intéressant lorsqu’on passe des valeurs en GET dans l’URL , où celle-ci pourrait être de la forme http://monsupersite.com/monscript.aspx?user=12&motdepasse=monsuperpasse&droit=2 de ne pas donner accès ou du moins la visibilité des paramètres que l’on passe au script de traitement. Ceci principalement pour des raisons de sécurité : tout internaute a dans l’absolu le moyen de modifier à la main la chaine passée dans la Querystring.

Aussi, pour éviter ça, on va tenter de transformer notre Querystring en une chaîne encryptée, de la forme : http://monsupersite.com/monscript.aspx?qs=YnZEUjZmb0QyY292NnlyQzZQTUo0ek…, ce qui est déjà moins compréhensible par l’être humain. qs contient l’ensemble des paramètres passés à l’origine.

Comment faire ?

Ce dont nous avons besoin :

  • de méthodes qui cryptent et décryptent une chaine, nous utiliserons une classe nommée Crypto (fournie par Obviex, la RijndaelSimple renommée en Crypto) qui encapsule l’algorithme (imprononçable) symétrique Rijndael. La clé utilisée pour le calcul est stockée dans un fichier de configuration (dans notre cas, dans le web.config).
  • de méthodes statiques cryptQ(string qs) et decryptQ(string qs) qui appellent Crypto et renvoient une chaine fonctionnelle pour le querystring au format Base64.

   using System.Configuration;

   public class QueryStringHelper 
   {
        /// <summary>
        ///     cryptage d'un valeur (querystring)+ convertion base64
        ///     Avec l'objectif de protéger une querystring (paras/valeurs)
        /// </summary>
        /// <param name="val"></param>
        /// <returns>la valeur base64</returns>
        public static string cryptQ(string val)
        {
            // la clé cryptKey est sotckée dans le web.config
            Crypto crypt = new Crypto(ConfigurationSettings.AppSettings["cryptKey"]);

            byte[] b = Encoding.Default.GetBytes(crypt.Encrypt(val));
            string bstring = Convert.ToBase64String(b);
            // les caractères spéciaux à protéger pour la querystring 
            // http://www.blooberry.com/indexdot/html/topics/urlencoding.htm
            bstring = bstring.Replace("/", "_");
            bstring = bstring.Replace("+", "-");

            return bstring;
        }

        /// <summary>
        ///     désérialisation base64 + décryptage d'une valeur
        /// </summary>
        /// <param name="val"></param>
        /// <returns>la valeur base64</returns>
        public static string decryptQ(string val)
        {
            // on remet en place les caractères protégés dans CryptQ()
            val = val.Replace("_", "/");
            val = val.Replace("-", "+");

            // la clé cryptKey est sotckée dans le web.config
            Crypto crypt = new Crypto(ConfigurationSettings.AppSettings["cryptKey"]);
            byte[] b = Convert.FromBase64String(val);
            return crypt.Decrypt(Encoding.Default.GetString(b));
        }
   } 

On peut dès lors utiliser ces 2 méthodes pour sécuriser nos URLs :

Pour l’appel :


  string myQS = "user=12&motdepasse";
   Response.Redirect(string.Format("monscript.aspx?qs={0}",QueryStringHelper.cryptQ(myQS)));

Pour la réception, dans monscript.aspx :


  if(! String.IsNullOrEmpty(Request.QueryString["qs"]) )  
      string myQSdec = QueryStringHelper.decryptQ(Request.QueryString["qs"]);  

myQSdec contiendra la chaine origine. Ce qui serait bien, c’est d’avoir une méthode qui me sépare les clés des valeurs, comme on peut l’avoir avec Request.QueryString, ajoutons une méthode à notre classe :


        /// <summary>
        ///     découpage d'une chaine querystring
        /// </summary>
        /// <param name="query">chaine de la forme para1=val1&para2=val2&...&paran=valn</param>
        /// <returns>un dictionnaire paras/valeurs</returns>        
        public static IDictionary deFoldQS(string query)
        {
            IDictionary myparams = new Hashtable();

            if (String.IsNullOrEmpty(query))
                return myparams;

            string[] pairs = query.Split(new char[] { '&' });

            foreach (string s in pairs)
            {
                string[] pair = s.Split(new char[] { '=' });
                myparams[pair[0]] = (pair.Length > 1) ? pair[1] : string.Empty;                
            }

            return myparams;
        }

On peut alors utiliser nos paramètres simplement lors de la réception dans le script monscript.aspx :


   if(! String.IsNullOrEmpty(Request.QueryString["qs"]) ) 
   { 
      string myQSdec = QueryStringHelper.decryptQ(Request.QueryString["qs"]);
      IDictionnary querystring = QueryStringHelper.deFoldQS(myQSdec);

      // on utilise les valeurs de nos paramètres
      string user = querystring["user"] as string ?? "";
      string pwd = querystring["motdepasse"] as string ?? "";
      int droit;
      if (!int.TryParse((string)p["droit"], out droit))
          droit = -1;
   }

Ce type de méthode d’encryptage de paramètres d’URL peut s’avérer utile lors de la manipulation critique de valeurs qui ne peuvent être transmises qu’en GET. Bien entendu, on ne s’amusera pas à tout crypter (performances), mais que lorsque cela s’avère nécessaire.

1 passées en Querystring, c’est à dire par l’appel d’un script où les paramètres et leur valeur sont visibles dans l’URL