繁体   English   中英

RC4算法:在客户端使用Javascript和服务器c#的情况下无法加密/解密数据

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM