使用AES算法在javascript中加密并在C#中解密

时间:2016-04-07 11:30:57

标签: javascript encryption aes cryptojs

我尝试使用来自AES的AES librery进行角度加密。

我使用AES中的CryptoJS.AES.encrypt()方法加密字符串。

这里是我的代码:

  var txtloginKod = 'Some String...';   
  var key = CryptoJS.enc.Utf8.parse('8080808080808080');
  var iv = CryptoJS.enc.Utf8.parse('8080808080808080');
  var  encryptedlogin = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(txtloginKod), key,
  {
      keySize: 128 / 8,
      iv: iv,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
  });

方法CryptoJS.AES.encrypt()将对象返回到我的encryptedlogin变量。

我不知道如何将此对象发送到C#

中的WCF Web服务器

当我尝试发送hole对象(并定义Web服务方法以期望获取C#Object)时 - 我收到此错误:

“将循环结构转换为JSON”

5 个答案:

答案 0 :(得分:2)

使用点网核心和类型脚本。

npm instal crypto-js

//Inside imports of your TS file include 
import * as CryptoJS from 'crypto-js';

// Declare this key and iv values in declaration
private key = CryptoJS.enc.Utf8.parse('4512631236589784');
private iv = CryptoJS.enc.Utf8.parse('4512631236589784');

// Methods for the encrypt and decrypt Using AES
encryptUsingAES256() {
    var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(JSON.stringify("Your Json Object data or string")), this.key, {
        keySize: 128 / 8,
        iv: this.iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    console.log('Encrypted :' + encrypted);
    this.decryptUsingAES256(encrypted);
    return encrypted;
}

decryptUsingAES256(decString) {
    var decrypted = CryptoJS.AES.decrypt(decString, this.key, {
        keySize: 128 / 8,
        iv: this.iv,
        mode: CryptoJS.mode.CBC,
        padding: CryptoJS.pad.Pkcs7
    });
    console.log('Decrypted : ' + decrypted);
    console.log('utf8 = ' + decrypted.toString(CryptoJS.enc.Utf8));

}

要编码或解码的C#代码在这里。

public class encr {
    public static string DecryptStringAES(string cipherText) {
        var keybytes = Encoding.UTF8.GetBytes("4512631236589784");
        var iv = Encoding.UTF8.GetBytes("4512631236589784");

        var encrypted = Convert.FromBase64String(cipherText);
        var decriptedFromJavascript = DecryptStringFromBytes(encrypted, keybytes, iv);
        return decriptedFromJavascript;
    }
    private static string DecryptStringFromBytes(byte[] cipherText, byte[] key, byte[] iv) {
        // Check arguments.
        if (cipherText == null || cipherText.Length <= 0) {
            throw new ArgumentNullException("cipherText");
        }
        if (key == null || key.Length <= 0) {
            throw new ArgumentNullException("key");
        }
        if (iv == null || iv.Length <= 0) {
            throw new ArgumentNullException("key");
        }

        // Declare the string used to hold
        // the decrypted text.
        string plaintext = null;

        // Create an RijndaelManaged object
        // with the specified key and IV.
        using(var rijAlg = new RijndaelManaged()) {
            //Settings
            rijAlg.Mode = CipherMode.CBC;
            rijAlg.Padding = PaddingMode.PKCS7;
            rijAlg.FeedbackSize = 128;

            rijAlg.Key = key;
            rijAlg.IV = iv;

            // Create a decrytor to perform the stream transform.
            var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

            try {
                // Create the streams used for decryption.
                using(var msDecrypt = new MemoryStream(cipherText)) {
                    using(var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {

                        using(var srDecrypt = new StreamReader(csDecrypt)) {
                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();

                        }

                    }
                }
            } catch {
                plaintext = "keyError";
            }
        }

        return plaintext;
    }

    public static string EncryptStringAES(string plainText) {
        var keybytes = Encoding.UTF8.GetBytes("4512631236589784");
        var iv = Encoding.UTF8.GetBytes("4512631236589784");

        var encryoFromJavascript = EncryptStringToBytes(plainText, keybytes, iv);
        return Convert.ToBase64String(encryoFromJavascript);
    }

    private static byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] iv) {
        // Check arguments.
        if (plainText == null || plainText.Length <= 0) {
            throw new ArgumentNullException("plainText");
        }
        if (key == null || key.Length <= 0) {
            throw new ArgumentNullException("key");
        }
        if (iv == null || iv.Length <= 0) {
            throw new ArgumentNullException("key");
        }
        byte[] encrypted;
        // Create a RijndaelManaged object
        // with the specified key and IV.
        using(var rijAlg = new RijndaelManaged()) {
            rijAlg.Mode = CipherMode.CBC;
            rijAlg.Padding = PaddingMode.PKCS7;
            rijAlg.FeedbackSize = 128;

            rijAlg.Key = key;
            rijAlg.IV = iv;

            // Create a decrytor to perform the stream transform.
            var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

            // Create the streams used for encryption.
            using(var msEncrypt = new MemoryStream()) {
                using(var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
                    using(var swEncrypt = new StreamWriter(csEncrypt)) {
                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }
        // Return the encrypted bytes from the memory stream.
        return encrypted;
    }
}

答案 1 :(得分:1)

您需要自己序列化密文。有很多方法可以做到。

如果密钥不是字符串,而是WordArray(如您的情况),则简单的encryptedlogin.toString()将生成仅包含密文的Base64编码字符串。请记住,您需要包含enc-base64.js源文件。

如果“密钥”(实际密码)是字符串,则应用与OpenSSL兼容的密钥派生。在这种情况下,encryptedlogin.toString()将是一个Base64编码的字符串,其中包含“Salted__”字符串,8字节随机盐和密文。

如果您只想获得密文,那么encryptedlogin.ciphertext.toString()将为您提供仅包含密文的十六进制编码字符串,encryptedlogin.iv.toString()将为您提供十六进制编码的IV。您可以通过这种方式生成Base64编码的字符串encryptedlogin.ciphertext.toString(CryptoJS.enc.Base64)

请记住,必须为每次加密随机选择IV,以提供语义安全性。它不必是秘密的,因此您可以将其与密文一起发送。

在服务器端,您将解码值(Base64或Hex取决于您在加密期间使用的内容),并将它们与AesCryptoServiceProvider类(或类似)一起使用来解密密文。

请记住,您还需要对密文进行身份验证,以便检测(恶意)操纵。这可以通过加密然后MAC方案来完成,该方案具有强大的MAC,如HMAC-SHA256。

此外,如果密钥与密文一起传输或通过不安全的信道传输,那么这基本上只是数据混淆,并且不提供真正的安全性。查看更多:Javascript Cryptography Considered Harmful

答案 2 :(得分:1)

我也有要求将加密的JSON对象发送到.Net CORE API 2.0,并在Internet上进行搜索以查找是否有帮助。我知道现在您已经解决了这个问题,但是为了帮助有兴趣的人,我提供了解决方案来帮助他们。

利用在stackoverflow上找到的示例代码,我设法实现了解决方案。棘手的位是关键,代码的长度必须为16,IV才能正常工作。

public static encrypt(model: any) {
        const key = CryptoJS.enc.Utf8.parse('TestMyOwnKeyForI');
        const iv = CryptoJS.enc.Utf8.parse('TestMyOwnIV1ForI');
        // padding and truncating
        const encryptedMessage = CryptoJS.AES.encrypt(JSON.stringify(model), key, {            
            keySize: 128 / 8,
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }).toString();

        return encryptedMessage;
}

在CORE中,我实现了如下的客户模型绑定提供程序:

public class DecryptModelBinderProvider : IModelBinderProvider
    {
        public IModelBinder GetBinder(ModelBinderProviderContext context)
        {
            if (context.Metadata.ModelType == typeof(MyModel))
                return new DecryptModelBinder();

            return null;
        }
    }

然后我自己的解密模型绑定器如下:

public class DecryptModelBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            if (bindingContext == null)
                throw new ArgumentNullException(nameof(bindingContext));
            using (var sr = new StreamReader(bindingContext.HttpContext.Request.Body))
            {
                string valueFromBody = sr.ReadToEnd();

                if (valueFromBody != null && valueFromBody.Length > 0)
                {
                    var decrypted = Encryption.DecryptString(valueFromBody, "TestMyOwnKeyForI");

                    var model = JsonConvert.DeserializeObject(decrypted, bindingContext.ModelType);

                    bindingContext.Result = ModelBindingResult.Success(model);
                    bindingContext.Model = model;        
                }

            }

            return Task.CompletedTask;
        }
    }

答案 3 :(得分:0)

使用返回的对象中的encryptionLogin.cipherText

答案 4 :(得分:-1)

检查https://social.msdn.microsoft.com/Forums/vstudio/en-US/47800a60-4461-4f8e-a8d1-751fa62c7884/aes-encrypt-in-javascript-and-decrypt-in-c?forum=csharpgeneral

此外,您应该使用CryptoJS v3.1.2 AES实现来使用它。您可以在此处下载:https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/crypto-js/CryptoJS%20v3.1.2.zip

你可以在这里找到Js边码:jsfiddle.net/aEKw5/22 /

因此,使用上面的信息,您可以在C#侧进行编码,并在js上对其进行解码。反之亦然。