Есть ли что-нибудь не так с этим кодом шифрования RC4 в C#
Я пытаюсь слушать 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±:„Qp"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Âø
Код выглядит правильно:
- шифрование
- кодировать
- декодировать
- расшифровать
Но это, кажется, не работает. Любые предложения о том, что может быть наверху что-то не так?
2 ответов:
Я немного удивлен кодом в классе 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.
Хотя это больше стрельба в темноте... Я довольно уверен, что реализация алгоритма RC4 класс, похоже, приобретает все ASCII или кодовая страница 1252 - как это неправильно, потому что я предполагаю, что предоставленный XML-это UTF-8 и .Чистая строка represantion в памяти формате UTF16...
Если мое предположение верно, то данные уже скремблированы, когда вы получаете их обратно из шифрования...
EDIT-некоторые ссылки на рабочий код RC4 в С#:
Comments