Шифрование строки в URL в C # - PullRequest
6 голосов
/ 15 июня 2011

В течение многих часов я искал идеальный способ зашифровать строку в URL. Вот метод, который я нашел

Лучший метод, который я нашел, и он находится в стеке

    using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web;

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

   public SimplerAES()
   {
      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)
   {
      MemoryStream encryptStream = new MemoryStream();
      using (CryptoStream cs = new CryptoStream(encryptStream, encryptor, CryptoStreamMode.Write))
      {
         cs.Write(buffer, 0, buffer.Length);
      }
      return encryptStream.ToArray();
   }

   public byte[] Decrypt(byte[] buffer)
   {
      MemoryStream decryptStream = new MemoryStream();
      using (CryptoStream cs = new CryptoStream(decryptStream, decryptor, CryptoStreamMode.Write))
      {
         cs.Write(buffer, 0, buffer.Length);
      }
      return decryptStream.ToArray();
   }
}

Теперь, когда я смотрю на зашифрованные строки, которые создаются с

    var a1 = _aes.EncryptToUrl("aaa");
    var a2 = _aes.EncryptToUrl("aaaa");
    var a3 = _aes.EncryptToUrl("aaaaa");
    var a4 = _aes.EncryptToUrl("aaaaaa");
    var a5 = _aes.EncryptToUrl("aaaaaaa");
    var a6 = _aes.EncryptToUrl("aaaaaaaa");
    var a7 = _aes.EncryptToUrl("aaaaaaaaa");
    var a8 = _aes.EncryptToUrl("aaaaaaaaaa");
    var a9 = _aes.EncryptToUrl("aaaaaaaaaaa");
    var a10 = _aes.EncryptToUrl("aaaaaaaaaaa");
    var a11 = _aes.EncryptToUrl("aaaaaaaaaaaa");
    var a12 = _aes.EncryptToUrl("aaaaaaaaaaaaa");
    var a13 = _aes.EncryptToUrl("aaaaaaaaaaaaaa");

Все строки (от a1 до a13) заканчиваются на "% 3d% 3d"

Поскольку экономия места на диске очень важна для этого приложения, мне интересно, могу ли я просто удалить «% 3d% 3d» и добавить его позже перед декодированием, чтобы вернуться к исходному URL.

Может кто-нибудь дать мне совет по этому поводу.

Спасибо

Ответы [ 2 ]

6 голосов
/ 15 июня 2011

Как говорит Эндрю, это отступ в конце base64. Однако я не согласен с его заключением.

Мы знаем, что правильно сформированная строка base64 всегда кратна 4 символам. Поэтому, пока мы можем доверять тому, что мы получили все данные за один раз (т.е. мы верим, что наш URL не урезан), мы можем убрать любые завершающие символы '=' из строки base64, прежде чем закодировать их для URL. Однако нам нужно поместить эти символы обратно , прежде чем мы позже вызовем Convert.FromBase64String. К счастью, мы можем сделать это, поскольку знаем, сколько их будет на основе длины полученной строки. Вы можете сделать это, даже если исходная длина не является постоянной, даже если в вашем случае она есть.

Еще один незначительный момент - «нормальный» алфавит base64 не подходит для URL; вы можете использовать альтернативную версию, как описано в Википедии :

Использование стандартного Base64 в URL-адресе требует кодирования символов «+», «/» и «=» в специальные шестнадцатеричные последовательности, закодированные в процентах («+» = «% 2B», «/ '=«% 2F »и« = '='% 3D '), что делает строку излишне длиннее. По этой причине существует модифицированный вариант Base64 для URL, в котором не будет использоваться заполнение '=', а символы '+' и '/' в стандартном Base64 соответственно заменяются на '-' и '_', так что использование Кодеры / декодеры URL больше не нужны и не влияют на длину кодированного значения, оставляя ту же самую кодированную форму без изменений для использования в реляционных базах данных, веб-формах и идентификаторах объектов в целом.

Я не знаю чего-либо в .NET, что делает это легко сделать эффективно. Самый простой подход - выполнить обычное преобразование base64, заменить + на -, / на _, а затем использовать string.TrimEnd, чтобы удалить знаки = с конца, с обратными операциями для декодирования. Это значительно менее эффективно, чем версия с ручным кодированием, но, учитывая размер данных, с которыми вы будете работать, это может не иметь значения.

1 голос
/ 15 июня 2011

Данные в конце вашей зашифрованной строки являются примером padding .Вы должны оставить строку как есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...