Что-то не так с этим кодом шифрования RC4 в C # - PullRequest
3 голосов
/ 28 августа 2011

Я пытаюсь прослушать Foxycart XML Datafeed в C # и сталкиваюсь с проблемой, которая сводится к шифрованию.

Короче говоря, они отправляют свои данные в виде закодированного и зашифрованного XML с использованием RC4 шифрования .

Для проверки у них есть некоторый (отправленный пользователем) пример кода для проверки этого с C # . Я попытался использовать этот пример кода дешифрования RC4, предоставленного одним из пользователей, но, похоже, он не работает, и его служба поддержки считает, что он не соответствует алгоритму C # RC4. Поскольку они не являются экспертами по C #, я решил спросить здесь. Вот сообщение на форуме FoxyCart

В любом случае, вот код, который (пытается) имитировать ответ, зашифровывая файл XML и публикуя его по URL (обратите внимание, что DataFeedKey - это строка, которую я сохранил как переменную-член):

public ActionResult TestDataFeed()
{
    string transactionData = (new StreamReader(@"D:\SampleFeed.xml")).ReadToEnd();
    string encryptedTransactionData = RC4.Encrypt(DataFeedKey, transactionData, false);
    string encodedTransactionData = HttpUtility.UrlEncode(encryptedTransactionData,     Encoding.GetEncoding(1252));
    string postData = "FoxyData=" + encodedTransactionData;
    var req = (HttpWebRequest)WebRequest.Create("http://localhost:3396/FoxyCart/RecieveDataFeed");
    req.Method = "POST";
    req.ContentType = "application/x-www-form-urlencoded";
    var sw = new StreamWriter(req.GetRequestStream(), Encoding.ASCII);
    sw.Write(postData);
    sw.Close();
    HttpWebResponse resp = null;
    try
    {
        resp = (HttpWebResponse)req.GetResponse();
        string r = new StreamReader(resp.GetResponseStream()).ReadToEnd();
    }
    catch (WebException ex)
    {
        string err = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
    }
    return null;
}

и вот метод обратного вызова, который получает ответ.

[ValidateInput(false)]
public ActionResult RecieveDataFeed(FormCollection collection)
{
    string unencodedFeed = HttpUtility.UrlDecode(collection["FoxyData"],     Encoding.GetEncoding(1252));
    string transaction = RC4.Decrypt(DataFeedKey, unencodedFeed, false);
    return Content("foxy");
}

Вместо публикации всего встроенного класса RC4 в этом вопросе, здесь есть ссылка на код этого класса RC4 .

Как я уже писал в приведенной выше ссылке в верхней части вопроса, проблема возникает, когда я проверяю переменную транзакцию внутри

 RecieveDataFeed()

метод, у меня должен быть обычный XML обратно, но вместо этого я вижу это:

É?xø´ v´“Û·8êUŸí¥MïSÅJÖó5Cå7ã…ÄlÞ&þòG·¶ÝÙ3<ÍÖ¡«úüF¿¿ßìNµ>4¦Äu÷¼Â;£-w¤ƒûÊyL¹®½èíYö½’é(µJŒ~»»=3¼]F‡•=±Ùí]'鳫"øPç{Ù^yyéå–°ñ…5ðWF$zÉnÄ^_”Xë’ï%œ-5á
ÒÛ€jŠt`Â9œÇÞLU&¼~ç2îžúo/¢¶5,º*öOqÝ—‘.ó®šuf™å5G—õC®‰ÁéiÇúW®¦ÝÚ•Z±:„Q\p"p
ôÔiÛ!\D"ÉÂX3]ƒ°è€Œ«DQE‡kÝ@àö`gpöŽ÷nÛ={µÏßKQKüå(ö%¯¯Ü–9}¨¬°£7yo,«”ÜëCÍ/+…†ÕËî‘‹‰AÚmÇÙå©&©¡xÙkŒföX¯ÃX&×°S|kÜ6Ô°Üú\Ätóü-äUƆÈáÅ\ ’E8‚¤âÈ4Ž¾«ãΚ_Sï£y‰xJº•bm*jo›‰ÜW–[ô†ÆJÐà$½…9½šžˆ_ÙÜù/®öÁVhzŠ¥ú(ñ£²6ˆb6¢ëße¤oáIðZuK}ÆÙ]"T¼*åZêñß5K—½òQSåRN Çë'Å¡
ÕyiÈX •bØðIk¿WxwNàäx®‹?cv+X™¥E!gd4â¤nÔ‹¢½Ð”ªÊ­Q!‚.e8s
Gyª4¼ò,}Yœ‚¹”±E‡Jy}Sæ
ƒ¦ýK'Ð}~B¦E3!0°ú´A–5Þ³£9$–8äÏ©?
 œ‡8GÂø

Код выглядит правильно:

  1. Шифрование
  2. Encode
  3. Decode
  4. Расшифровать

но, похоже, это не работает. Любые предложения о том, что может быть не так?

Ответы [ 2 ]

13 голосов
/ 28 августа 2011

Я немного удивлен кодом в классе CR4. Я не вижу, как это будет работать надежно.

Код использует кодировку windows-1252 для кодирования символов в байты, затем шифрует байты и пытается декодировать байты в символы. Это не сработает надежно, поскольку вы можете декодировать только байты, полученные из кодирующих символов.

Метод берет строку и возвращает строку, но он должен взять байтовый массив и вернуть байтовый массив, подобно тому, как это делают все классы шифрования в платформе.

Вот версия, которая работает так:

public class RC4 {

  public static byte[] Encrypt(byte[] pwd, byte[] data) {
    int a, i, j, k, tmp;
    int[] key, box;
    byte[] cipher;

    key = new int[256];
    box = new int[256];
    cipher = new byte[data.Length];

    for (i = 0; i < 256; i++) {
      key[i] = pwd[i % pwd.Length];
      box[i] = i;
    }
    for (j = i = 0; i < 256; i++) {
      j = (j + box[i] + key[i]) % 256;
      tmp = box[i];
      box[i] = box[j];
      box[j] = tmp;
    }
    for (a = j = i = 0; i < data.Length; i++) {
      a++;
      a %= 256;
      j += box[a];
      j %= 256;
      tmp = box[a];
      box[a] = box[j];
      box[j] = tmp;
      k = box[((box[a] + box[j]) % 256)];
      cipher[i] = (byte)(data[i] ^ k);
    }
    return cipher;
  }

  public static byte[] Decrypt(byte[] pwd, byte[] data) {
    return Encrypt(pwd, data);
  }

}

Пример:

string data = "This is a test.";
byte[] key = { 1, 2, 3, 4, 5 };

// encrypt
byte[] enc = RC4.Encrypt(key, Encoding.UTF8.GetBytes(data));

// turn into base64 for convenient transport as form data
string base64 = Convert.ToBase64String(enc);

Console.WriteLine(base64);

// turn back into byte array
byte[] code = Convert.FromBase64String(base64);

// decrypt
string dec = Encoding.UTF8.GetString(RC4.Decrypt(key, code));

Console.WriteLine(dec);

Выход:

5lEKdtBUswet4yYveWU2
This is a test.
1 голос
/ 28 августа 2011

Хотя это больше стрельба в темноте ... Я скорее уверен, что класс, реализующий RC4, выглядит так, как будто он предполагает, что все являются ASCII или CodePage 1252 - оба неверны, потому что я предполагаю, что предоставленный XML - UTF-8 и .NET строка represantion в памяти UTF16 ...

Если мое предположение верно, данные уже шифруются, когда вы возвращаете их из шифрования ...

РЕДАКТИРОВАТЬ - некоторые ссылки на рабочий код RC4 в C #:

...