我需要在 IIS(basicHttpBinding)中托管的 .NET 4.0 WCF 应用程序和使用 JavaScript RC4 算法实现加密/解密数据的内部客户端应用程序系统之间传递加密(和 base64 编码)字符串数据。
到目前为止,我还没有成功地将客户端加密的数据发送到服务器,然后在服务器上对其进行解密(或相反——客户端解密从服务器响应接收到的数据)。我们已经尝试了互联网上 JavaScript 文件(以及 AES)中的一些 RC4 算法变体。
我已将客户端使用的 RC4 算法版本转换为 C#(JavaScript 文件位于:https ://gist.github.com/2185197 )。我创建了一个 html 页面,以纯客户端方式测试 JavaScript 加密/解密功能。这行得通。同样,通过单元测试,我已经确定 c# Encrypt / Decrypt 也适用于 .NET WCF 服务。通过这些测试,没有 base64 编码/解码。
使用 c# RC4 算法,我可以成功处理通过线路发送的数据的加密/解密,其中加密数据是 base64 编码并且客户端是 .NET 应用程序(使用与服务器相同的 C# 算法实现类)
我逐行检查了客户端 JavaScript (Firebug) 和 C# (Visual Studio) 算法,验证变量值是否匹配。一切都匹配,除了代码将整数值转换为字符串(通过字符)。这里的结果是不一致的。下面是问题线。
下面是每个实现的代码行。
C#: var charX = Convert.ToChar(26).ToString();
JavaScript:
Var charX = String.fromCharCode(26);
一些视觉差异可能仅仅是由于 Firebug 和 Visual Studio 的渲染能力。[我的理解是它们都应该呈现 UTF8 编码的字符串]。我读过 JavaScript 引擎和 JavaScript 语言的编码不同。因此,微软已经实施了一个修复 [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 v 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);
}
}
下面是c#代码:
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);
}
}