0

我需要在 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);
    }
}
4

1 回答 1

3

我认为您只需要对发送到代码的值进行 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;
}
于 2012-10-25T20:04:09.547 回答