如何使用C#在服务器上加密jpeg,并使用Crypt-JS在浏览器上解密

时间:2019-06-08 11:10:20

标签: c# cryptojs

我正在尝试在服务器上加密jpeg并在浏览器上将其解密,如下所示,但是在步骤3中失败了。

  1. 在服务器上通过C#加密jpeg
  2. 在客户端浏览器上获取加密的数据,向量和密码短语
  3. 在客户端浏览器上解密

我尝试了以下操作,但无济于事。

  1. 在服务器上使用RijndaelManaged而不是AesManaged。
  2. 使用“ CryptoJS.enc.Utf16.parse”而不是“ CryptoJS.enc.Utf8.parse” 在客户端上。

服务器上的加密

public byte[] Encrypt(byte[] bytes, string password, string vector)
{
    AesManaged aes = new AesManaged();
    aes.KeySize = _keySize;
    aes.BlockSize = _blockSize;
    aes.Mode = CipherMode.CBC;
    aes.IV = Encoding.UTF8.GetBytes(vector);
    aes.Key = Encoding.UTF8.GetBytes(password);
    aes.Padding = PaddingMode.PKCS7;

    byte[] encrypted = aes.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length);

    return encrypted;
}

客户端解密

// These values are same as above
var encrypted = ... //  byte[]
var vector = ... // string
var password = ... // string

var cipherParams = CryptoJS.lib.CipherParams.create({
    iv: CryptoJS.enc.Utf8.parse(vector),
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});
var cipherText = CryptoJS.lib.WordArray.create(encrypted);
var passwordWordArray = CryptoJS.enc.Utf8.parse(password);
var decrypted = CryptoJS.AES.decrypt(cipherText, passwordWordArray, cipherParams);
// decrypted.words is empty here

请告知。

我在Windows 10上使用.Net Core MVC 2.1,Crypto-JS 3.1.9-1和Chrome74.0.3729.169。

此问题已解决

正如Topaco提到的那样,javascript中存在一个缺陷。更正后的代码如下。

var encrypted = ... //  byte[]
var vector = ... // string
var password = ... // string

var cipherParams = CryptoJS.lib.CipherParams.create({
    iv: CryptoJS.enc.Utf8.parse(vector),
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
});
var cipherText = CryptoJS.lib.WordArray.create(encrypted);
var cipherTextParam = CryptoJS.lib.CipherParams.create({
            ciphertext: cipherText
        });
var passwordWordArray = CryptoJS.enc.Utf8.parse(password);
var decrypted = CryptoJS.AES.decrypt(cipherTextParam, passwordWordArray, cipherParams);

谢谢您的帮助。

1 个答案:

答案 0 :(得分:1)

JavaScript代码中有两个缺陷,可以纠正如下:

  • 在JavaScript代码行中:

    var cipherText = CryptoJS.lib.WordArray.create(encrypted);
    

    必须替换为:

    var cipherText = byteArrayToWordArray(encrypted); 
    

    在这里,使用功能byteArrayToWordArray

    function byteArrayToWordArray(ba) {
        var wa = [], i;
        for (i = 0; i < ba.length; i++) 
            wa[(i / 4) | 0] |= ba[i] << (24 - 8 * i);
        return CryptoJS.lib.WordArray.create(wa, ba.length);
    }
    

    此函数通过从字节数组的4个字节生成一个字(4个字节)来从字节数组生成一个字数组。在旧的代码中,每个字节生成一个具有相同值的单词,即两个数组具有相同数量的元素,这是错误的。

    或者:

    var cipherTextHex = bytesToHex(encrypted);
    var cipherText = CryptoJS.enc.Hex.parse(cipherTextHex);
    

    也可以使用。在这里,使用功能bytesToHex

    function bytesToHex(bytes) {
        for (var hex = [], i = 0; i < bytes.length; i++) {
            var current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];
            hex.push((current >>> 4).toString(16));
            hex.push((current & 0xF).toString(16));
        }
        return hex.join("");
    }
    

    该函数从字节数组生成一个十六进制字符串。由此,使用适当的encoder得出单词数组。

  • 在JavaScript代码中,以下行:

    var decrypted = CryptoJS.AES.decrypt(cipherText, passwordWordArray, cipherParams);
    

    必须替换为:

    var cipherParamsCipherText = CryptoJS.lib.CipherParams.create({
        ciphertext: cipherText
    });
    var decrypted = CryptoJS.AES.decrypt(cipherParamsCipherText, passwordWordArray, cipherParams);
    

    因为decrypted函数期望CipherParams对象代替WordArray作为第一个参数。

    或者,也可以传递Base64编码的字符串:

    var cipherTextB64Enc = CryptoJS.enc.Base64.stringify(cipherText);   
    var decrypted = CryptoJS.AES.decrypt(cipherTextB64Enc, passwordWordArray, cipherParams);
    
  • 测试:C#代码提供以下输入:

    byte[] bytes = Encoding.UTF8.GetBytes("The quick brown fox jumps over the lazy dog");
    string password = "0123456789012345"; // 16 byte -> AES-128
    string vector = "5432109876543210";   // 16 byte
    

    以下字节数组为密文:

    170, 27, 161, 209, 42, 247, 234, 191, 38, 167, 22, 74, 34, 139, 115, 0, 75, 207, 119, 161, 97, 142, 179, 93, 41, 12, 177, 128, 52, 151, 75, 231, 76, 157, 14, 197, 59, 111, 63, 206, 136, 218, 189, 244, 116, 43, 25, 20
    

    如果修改后的JavaScript代码已与这些数据一起测试:

    var encrypted = [170,27,161,209,42,247,234,191,38,167,22,74,34,139,115,0,75,207,119,161,97,142,179,93,41,12,177,128,52,151,75,231,76,157,14,197,59,111,63,206,136,218,189,244,116,43,25,20]; // byte[]
    var vector = "5432109876543210"    // string
    var password = "0123456789012345"; // string
    

    它已正确解密。

    在测试中,使用了AES-128。只需使用32字节密钥而不是16字节密钥即可将其切换为AES-256。