Зашифровать в javascript и расшифровать в C# с помощью алгоритма AES

Я попытался зашифровать в angular с помощью библиотеки AES из AES.

Я зашифровал строку, используя метод CryptoJS.AES.encrypt() из AES.

Вот мой код:

  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.

Я не знаю, как отправить этот объект на мой веб-сервер WCF в С#.

Когда я попытался отправить весь объект (и определить метод веб-службы для получения объекта C#), я получил следующую ошибку:

«Преобразование круговой структуры в JSON»


person Lea    schedule 07.04.2016    source источник
comment
Для этого и нужен протокол https.   -  person dbugger    schedule 07.04.2016
comment
Есть ли проблемы с моим ответом? Если нет, и это решило вашу проблему, вы можете принять это.   -  person Artjom B.    schedule 11.04.2016


Ответы (5)


У меня тоже было требование отправить зашифрованный объект JSON в .Net CORE API 2.0, и я искал в Интернете, чтобы найти помощь. Я знаю, что к настоящему времени вы бы решили эту проблему, но чтобы помочь всем заинтересованным, я предлагаю свое решение, чтобы помочь им.

С примерами кода, которые я нашел здесь, в stackoverflow, мне удалось реализовать решение. Хитрый бит — это ключ, и IV должен иметь длину 16, чтобы код работал.

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;
        }
    }

Затем мой собственный decryptmodelbinder выглядит следующим образом:

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;
        }
    }
person coolcake    schedule 21.06.2018

Использование ядра Dot net и Type Script.

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;
    }
}
person Ankitkumar Singh    schedule 18.09.2020

Вам нужно будет сериализовать зашифрованный текст самостоятельно. Есть много способов сделать это.

Если ключ является не строкой, а 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 считается вредной

person Artjom B.    schedule 07.04.2016

Используйте зашифрованныйLogin.cipherText из возвращенного объекта

person ashley rodrigues    schedule 07.10.2020
comment
Ответ должен содержать более подробную информацию - person Mulli; 07.10.2020

Проверьте, пожалуйста, 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/

Таким образом, используя приведенную выше информацию, вы можете кодировать на стороне С# и декодировать ее на js. или наоборот.

person Nigrimmist    schedule 05.12.2016