AES用密钥和IV解密(涉及Cryptojs和C#)

时间:2017-04-12 07:36:38

标签: c# asp.net-core cryptography aes cryptojs

我有一个ASP.NET核心应用程序,它提供了SPA应用程序要使用的一些数据路由(没有涉及的UI框架,只有JavaScript和HTML5)。响应JSON中的某些值使用AES加密;客户端需要解密值以便向用户显示主题。在客户端,我使用CryptoJS,但我无法解密。如下,这就是我试过的......

首先,这是用于使用AES加密数据的功能(服务器端代码)。它使用SHA256对键和引脚进行哈希处理,并使用键和IV的计算值:

async Task<byte[]> Encrypt(string key, string pin, byte[] data)
{
    using (var sha = SHA256.Create())
    {
        byte[] keyData = sha.ComputeHash(Encoding.UTF8.GetBytes($"{key}"));
        byte[] rgbIv = sha.ComputeHash(Encoding.UTF8.GetBytes($"{pin}"));
        using (Aes aes = Aes.Create())
        {
            byte[] rgbKey = keyData.Slice(0, aes.Key.Length); // 32
            byte[] iv = rgbIv.Slice(0, aes.IV.Length); // 16
            using (ICryptoTransform transform = aes.CreateEncryptor(rgbKey, iv))
            using (var stream = new MemoryStream())
            using (var cryptStream = new CryptoStream(stream, transform, CryptoStreamMode.Write))
            {
                await cryptStream.WriteAsync(data, 0, data.Length);
                await cryptStream.FlushAsync();

                return stream.ToArray();
            }
        }
    }
}

加密数据在模型中存储为Base64编码的字符串,例如:

class Model 
{
    public string EncryptedValue { get; set; }
}

...

byte[] data = Encoding.Utf8.GetBytes("...");
byte[] encrypted = await Encrypt("api-key", "123456", data);
var model = new Model { EncryptedValue = Convert.ToBase64String(encrypted) };

我使用Bower安装了crypto-js 3.1.12:

bower install crypto-js

我从CryptoJS构建文件夹中选择了所需的JavaScript文件;这是我用来捆绑所有文件的捆绑配置(使用bundleconfig.json;通过反复试验找到了文件的工作顺序):

{
    "outputFileName": "Content/js/encryption.js",
    "minify": { "enabled": false },
    "inputFiles": [
        "bower_components/crypto-js/build/components/core.js",
        "bower_components/crypto-js/build/rollups/sha256.js",
        "bower_components/crypto-js/build/rollups/aes.js",
        "bower_components/crypto-js/build/components/cipher-core.js",
        "bower_components/crypto-js/build/components/enc-base64.js"
    ]
}

由于我在TypeScript中实现了所有客户端功能,因此我还使用以下用于crypto-js的TypeScript定义来获取Visual Studio中的Intellisense:

typings install dt~cryptojs --global

这是我的客户端代码:

import WordArray = CryptoJS.lib.WordArray;

...

decodeData(data: string): JQueryPromise<string> {

    let deferred: JQueryDeferred<string> = $.Deferred<string>();

    this.obtainPublicKey().done((publicKey: string) => {

        this.promptUserPinCode().done((pin: string) => {

            let cipherBuffer: WordArray = CryptoJS.enc.Base64.parse(data);

            let publicKeyHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(publicKey));
            let key: WordArray = CryptoJS.lib.WordArray.create(publicKeyHash.words.slice(0, 8), 32);

            let pinHash: WordArray = CryptoJS.SHA256(CryptoJS.enc.Utf8.parse(pin));
            let iv: WordArray = CryptoJS.lib.WordArray.create(pinHash.words.slice(0, 4), 16);

            let cfg: CryptoJS.lib.IBlockCipherCfg = {
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7,
                iv: iv
            };

            let params: CryptoJS.lib.CipherParamsData = {
                ciphertext: cipherBuffer,
                key: key,
                iv: iv,
                algorithm: CryptoJS.algo.AES,
                blockSize: 128,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7,
                salt: CryptoJS.lib.WordArray.create([], 0)
            };

            let decrypted: WordArray = CryptoJS.AES.decrypt(params, key, cfg);

            const s = CryptoJS.enc.Utf8.stringify(decrypted);
            console.log(s);

            deferred.resolve(s);
        });
    });

    return deferred.promise();
}

从C#中的params对象中挑选cfgAES的配置;我只是想确保CryptoJS使用与服务器完全相同的配置......

解密的数据总是空的,所以我认为解密失败了,但它并没有给我任何错误。我还检查过,如果客户端和服务器上的密钥和IV是相同的,那就是这种情况。我猜CryptoJS使用给定的密钥作为密码,然后从中获取新的密钥信息......如果是这种情况,我可以阻止它......我需要提供密钥和IV信息吗?

我怎样才能使这个工作?

0 个答案:

没有答案