Мне нужно передать зашифрованные (и закодированные в base64) строковые данные между приложением .NET 4.0 WCF, размещенным в IIS (basicHttpBinding), и внутренней системой клиентских приложений, которая использует реализацию алгоритма JavaScript RC4 для шифрования/дешифрования данных.
Пока мне не удалось отправить данные, зашифрованные клиентом, на сервер, а затем расшифровать их на сервере (или наоборот — когда клиент расшифровывает данные, полученные из ответа сервера). Мы попробовали несколько вариантов алгоритмов RC4, найденных в файлах JavaScript в Интернете (а также AES).
Я преобразовал версию алгоритма RC4, которую использует клиент, в C# (файл JavaScript, расположенный по адресу: https://gist.github.com/2185197). Я создал html-страницу, чтобы протестировать функциональность шифрования/дешифрования JavaScript исключительно на стороне клиента. Это работает. Точно так же с помощью модульного тестирования я установил, что c# Encrypt/Decrypt также работает в службе .NET WCF. С этими тестами не было кодирования/декодирования base64.
Используя алгоритм С# RC4, я могу успешно обрабатывать шифрование/дешифрование данных, отправляемых по сети, где зашифрованные данные закодированы в base64 И где клиент является приложением .NET (используя тот же класс реализации алгоритма С#, что и сервер)
Я шаг за шагом прошел через клиентский алгоритм JavaScript (Firebug) и C# (Visual Studio), проверяя, совпадают ли значения переменных. Все совпадает, за исключением того, где код преобразует целочисленное значение в строку (через Char). Результат здесь неоднозначный. Ниже находится проблемная строка.
Ниже приведена строка кода для каждой реализации.
C#: var charX = Convert.ToChar(26).ToString();
JavaScript:
Var charX = String.fromCharCode(26);
Некоторые визуальные различия могут быть просто связаны с возможностями рендеринга Firebug и Visual Studio. [Насколько я понимаю, они оба должны отображать строки в кодировке UTF8]. Я читал, что JavaScript Engine и язык JavaScript различаются по своей кодировке. Таким образом, Microsoft внедрила исправление [https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/fromCharCode], которое я безуспешно пытался внедрить. Может быть какая-то кодировка, которую мне нужно реализовать в коде C#; но пока не идентифицированы
Как и в приведенном выше примере для целочисленного значения 26, код C# показывает стрелку влево при проверке значения переменной. JavaScript показывает пробел. Для JavaScript это согласуется с тестами, проведенными через W3Shools (http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_fromcharcode).
Нужно ли мне выполнять какое-то кодирование в приложении .NET, чтобы обеспечить согласованность обработки символов в JavaScript и C#?
Заранее спасибо.
Ниже приведен код JavaScript:
function rc4(key, str) {
var s = [], j = 0, x, res = '';
for (var i = 0; i < 256; i++) {
s[i] = i;
}
for (i = 0; i < 256; i++) {
j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
x = s[i];
s[i] = s[j];
s[j] = x;
}
i = 0;
j = 0;
for (var y = 0; y < str.length; y++) {
i = (i + 1) % 256;
j = (j + s[i]) % 256;
x = s[i];
s[i] = s[j];
s[j] = x;
//res += String.fromCharCode(str.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
var sx = s[i] + s[j];
var ssx = s[sx % 256];
var fromChar1 =str.charCodeAt(y);
var fromChar2 = (fromChar1 ^ ssx);
var fromChar3 = String.fromCharCode(fromChar2); //****** PROBLEM LINE *******
//var fromChar3 = fixedFromCharCode(fromChar2);
res += fromChar3;
}
return res;
}
//Fix as per Microsoft
//https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/fromCharCode
function fixedFromCharCode(codePt) {
if (codePt > 0xFFFF) {
codePt -= 0x10000;
return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
}
else {
return String.fromCharCode(codePt);
}
}
Ниже приведен код С#:
public class RC4
{
public static string Encrypt(string key, string data)
{
var s = new List<int>();
var j = 0;
var x = 0;
var res = string.Empty;
for (var i = 0; i < 256; i++)
{
s.Add(i);
}
for (var i = 0; i < 256; i++)
{
var unicodeInt01 = ConvertedCharacterToItsUnicodeNumberic(key, i);
j = (j + s[i] + unicodeInt01) % 256;
x = s[i];
s[i] = s[j];
s[j] = x;
}
var f = 0;
j = 0;
for (var y = 0; y < data.Length; y++)
{
f = (f + 1) % 256;
j = (j + s[f]) % 256;
x = s[f];
s[f] = s[j];
s[j] = x;
var unicodInt02 = ConvertedCharacterToItsUnicodeNumberic(data, y);
var convStringOperationApplied = unicodInt02 ^ s[(s[f] + s[j]) % 256];
var charX = Convert.ToChar(convStringOperationApplied); //****** PROBLEM LINE *******
var val = new string(charX, 1);
res += val;
}
return res;
}
private static int ConvertedCharacterToItsUnicodeNumberic(string key, int i)
{
return key.ElementAt(i % key.Length);
}
public static string Decrypt(string key, string data)
{
return Encrypt(key, data);
}
}