[英]RC4 Algorithm: Unable to Encrypt / Decrypt data where client uses Javascript and Server c#
我需要在IIS(basicHttpBinding)托管的.NET 4.0 WCF应用程序和使用JavaScript RC4算法实现来加密/解密数据的内部客户端应用程序系统之间传递加密(和base64编码)的字符串数据。
到目前为止,我还没有成功将客户端加密的数据发送到服务器,然后在服务器上解密(或者相反,客户端解密从服务器响应接收的数据)。 我们尝试了Internet(以及AES)的JavaScript文件中提供的RC4算法的几种变体。
我已将客户端使用的RC4算法版本转换为C#(JavaScript文件位于: https : //gist.github.com/2185197 )。 我创建了一个html页面,以纯客户端方式测试JavaScript加密/解密功能。 这可行。 同样,通过单元测试,我确定c#加密/解密也可以在.NET WCF服务中使用。 通过这些测试,没有base64编码/解码。
使用c#RC4算法,我可以成功处理通过有线发送的数据的加密/解密,其中加密数据是base64编码的,而客户端是.NET应用程序(使用与服务器相同的C#算法实现类)
我逐行浏览了客户端JavaScript(Firebug)和C#(Visual Studio)算法,验证变量值是否匹配。 一切都匹配,除了代码将整数值转换为String(通过Char)的地方。 这里的结果不一致。 下面是问题所在。
下面是每个实现的代码行。
C#:var charX = Convert.ToChar(26).ToString();
JavaScript:
Var charX = String.fromCharCode(26);
某些视觉差异可能仅是由于Firebug和Visual Studio的渲染功能所致。 [我的理解是它们都应呈现UTF8编码的字符串]。 我已经读过JavaScript引擎和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 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);
}
}
我认为您只需要对要发送给代码的值进行URL编码。 我直接运行它,发现FF和IE发送两个不同的值。 因此我在发送值之前使用了encodeURICompontent,它工作得很好。 无需更改RC4算法
<script>
$(function () {
var value = encodeURIComponent(rc4('9F32B12B2D34FD5FB6B9F372DE67D5C38FC8BF862DB3486C52E5211589B50AB0', 'Welcome to ASP.NET MVC!'));
$('#encrypted').val(value);
$.get('/Home/Test?value=' + value, function (d) {
$('#decrypted').val(d);
});
});
</script>
<textarea id="encrypted">
</textarea>
<textarea id="decrypted">
</textarea>
这是我在服务器端(ASP.NET MVC)所拥有的:
public string Test(string value)
{
string test = RC4.Decrypt("9F32B12B2D34FD5FB6B9F372DE67D5C38FC8BF862DB3486C52E5211589B50AB0", value);
return test;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.