簡體   English   中英

在 Angular 加密,在 C# 解密

[英]Encrypting in Angular and Decrypt on C#

我有加密 Angular 數據的代碼,但我不知道如何在服務器端解密

  var panno = CryptoJS.AES.encrypt("FEAPS8905Q", "myPassword").toString();

在 angular 中加密為U2FsdGVkX19mi5mXlJ14Lj0XcJBbqMPDzi/UeNXK4Cw= ,在使用 Http.post 方法發送加密后,我沒有得到確切的數據,而是得到楀뢖᷈鍩ԏ건뫨샞일䜍鈈䁞

我也在C# 上使用了這個參考解密,但我得到了一些數據,如壓섢⻫捼箋ﵑ戛ꔉ됒퍿誁累♟꘶콒ꚦ

public string Decrypt(string cipherText)
    {
        string EncryptionKey = "myPassword";
        cipherText = cipherText.Replace(" ", "+");
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        using (Aes encryptor = Aes.Create())
        {
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] {  
            0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76  });
            encryptor.Key = pdb.GetBytes(32);
            encryptor.Padding = PaddingMode.None;
            encryptor.IV = pdb.GetBytes(16);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(cipherBytes, 0, cipherBytes.Length);
                    cs.Close();
                }
                cipherText = Encoding.Unicode.GetString(ms.ToArray());
            }
        }
        return cipherText;
    }

CryptoJS.AES.encrypt(text, password)使用派生算法從你的密碼中隱式派生出加密密鑰和 iv,這種算法不是 C# 原生的。 與其依賴於隱式推導,不如自己使用眾所周知的算法(如 PBKDF2)顯式地執行此操作。

需要密鑰派生,因為您的密碼可以具有任意大小,但給定算法 (AES) 需要特定大小的密鑰,例如 256 位。 所以我們需要從任意長度的密碼到固定大小的密鑰(以不可逆的方式)。

示例 JavaScript 代碼:

function encrypt (msg, pass) {
  // random salt for derivation
  var keySize = 256;
  var salt = CryptoJS.lib.WordArray.random(16);
  // well known algorithm to generate key
  var key = CryptoJS.PBKDF2(pass, salt, {
      keySize: keySize/32,
      iterations: 100
    });
  // random IV
  var iv = CryptoJS.lib.WordArray.random(128/8);      
  // specify everything explicitly
  var encrypted = CryptoJS.AES.encrypt(msg, key, { 
    iv: iv, 
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC        
  });
  // combine everything together in base64 string
  var result = CryptoJS.enc.Base64.stringify(salt.concat(iv).concat(encrypted.ciphertext));
  return result;
}

在 C# 中解密它現在很容易:

public static string Decrypt(string cipherText, string password) {
    byte[] cipherBytes = Convert.FromBase64String(cipherText);
    using (Aes encryptor = Aes.Create()) {
        // extract salt (first 16 bytes)
        var salt = cipherBytes.Take(16).ToArray();
        // extract iv (next 16 bytes)
        var iv = cipherBytes.Skip(16).Take(16).ToArray();
        // the rest is encrypted data
        var encrypted = cipherBytes.Skip(32).ToArray();
        Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, salt, 100);
        encryptor.Key = pdb.GetBytes(32);
        encryptor.Padding = PaddingMode.PKCS7;
        encryptor.Mode = CipherMode.CBC;
        encryptor.IV = iv;
        // you need to decrypt this way, not the way in your question
        using (MemoryStream ms = new MemoryStream(encrypted)) {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Read)) {
                using (var reader = new StreamReader(cs, Encoding.UTF8)) {
                    return reader.ReadToEnd();
                }
            }
        }
    }
}    

如果您了解后果,您可以使用固定鹽(或例如在您的應用程序中為每個用戶使用固定鹽),並減少 PB​​KDF2 中的迭代次數。 不要使用固定的 IV,也不要使用部分密鑰作為 IV。

在 node.js 中加密:

    var crypto = require('crypto');
var key = '00000000000000000000000000000000'; //replace with your key
var iv = '0000000000000000'; //replace with your IV
var cipher = crypto.createCipheriv('aes256', key, iv)
var crypted = cipher.update(authorizationKey, 'utf8', 'base64')
crypted += cipher.final('base64');
console.log(crypted);

解密c#

    string keyString = "00000000000000000000000000000000"; //replace with your key
string ivString = "0000000000000000"; //replace with your iv

byte[] key = Encoding.ASCII.GetBytes(keyString);
byte[] iv = Encoding.ASCII.GetBytes(ivString);

using (var rijndaelManaged =
        new RijndaelManaged { Key = key, IV = iv, Mode = CipherMode.CBC })
        {
            rijndaelManaged.BlockSize = 128;
            rijndaelManaged.KeySize = 256;
            using (var memoryStream =
                   new MemoryStream(Convert.FromBase64String(AuthorizationCode)))
            using (var cryptoStream =
                   new CryptoStream(memoryStream,
                       rijndaelManaged.CreateDecryptor(key, iv),
                       CryptoStreamMode.Read))
            {
                return new StreamReader(cryptoStream).ReadToEnd();
            }
        }

來源: https : //gsferreira.com/archive/2015/02/how-to-encrypt-in-nodejs-and-decrypt-in-c-sharp/

為我工作!

找到 Angular 和 C# 的匹配算法來加密和解密文本 cipherPhrase 文本包含密鑰和 IV,由分號管道分隔

角打字稿代碼

import * as CryptoJS from 'crypto-js';
 
 encrypt(plainText: string): string {    
let cipherPhrase = environment.angularCipherKeyIvPhrase;
// separate the key and Iv from the cipher phrase string

var key = CryptoJS.enc.Utf8.parse(cipherPhrase.split("|")[0]);
var iv = CryptoJS.enc.Utf8.parse(cipherPhrase.split("|")[1]);

var encrypted = CryptoJS.AES.encrypt(CryptoJS.enc.Utf8.parse(plainText), key,
  {
    keySize: 128 / 8,
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
console.log(encrypted.toString());
return encrypted;
  }

解密打字稿功能

decrypt(encryptedText: string): string {

let cipherPhrase = environment.angularCipherKeyIvPhrase;

// separate the key and Iv from the cipher phrase string
var key = CryptoJS.enc.Utf8.parse(cipherPhrase.split("|")[0]);
var iv = CryptoJS.enc.Utf8.parse(cipherPhrase.split("|")[1]);

var decrypted = CryptoJS.AES.decrypt(encryptedText, key,
  {
    keySize: 128 / 8,
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });

return decrypted.toString(CryptoJS.enc.Utf8);
}

C#函數加密/解密

        // encryption function similar to Angular cryptoJs
    public static string NgEncrypt(string plainText, string ngCipherKeyIvPhrase)
    {
        var cipherTextArray = ngCipherKeyIvPhrase.Split("|");
        string cipherPhrase = cipherTextArray[0];
        string salt  = cipherTextArray[1];

        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 = Encoding.UTF8.GetBytes(cipherPhrase);
            rijAlg.IV = Encoding.UTF8.GetBytes(salt);

            // 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 Convert.ToBase64String(encrypted);
    }

    // decryption function similar to Angular cryptoJs
    public static string NgDecrypt(string encryptedText,string ngCipherKeyIvPhrase)
    {
        string plainText = string.Empty;
        var cipherTextArray = ngCipherKeyIvPhrase.Split("|");
        string cipherPhrase = cipherTextArray[0];
        string salt = cipherTextArray[1];

        byte[] cipherText = Convert.FromBase64String(encryptedText); 
        // 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 = Encoding.UTF8.GetBytes(cipherPhrase);
            rijAlg.IV = Encoding.UTF8.GetBytes(salt);

            // Create a decryptor to perform the stream transform.  
            var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
            
                // 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();

                        }

                    }
                }

                return plainText;
         
        }

    }

加密c#中的數據

參考https://www.c-sharpcorner.com/article/encryption-and-decryption-using-a-symmetric-key-in-c-sharp/加密數據

解密angular中的數據

https://www.npmjs.com/package/crypto-js安裝 crypto-js

//install crypto-js from https://www.npmjs.com/package/crypto-js and import it   

import * as CryptoJS from 'crypto-js';

encrypedcode="Awt%2FgsVGXoQc3sasAkDqbVoXbXlmc2xZzu14cpHxmu1J0pvGYjGCm1uGz0qcpF07"

decryptData(encryptedText:any) {

    try {
      let cipherPhrase = 'decryptkey';

var key = CryptoJS.enc.Utf8.parse(cipherPhrase);
var iv = CryptoJS.enc.Utf8.parse('');

      var decrypted = CryptoJS.AES.decrypt(encryptedText.trim(), key,
        {
          keySize: 128/8,
          iv: iv,
          mode: CryptoJS.mode.CBC,
          padding: CryptoJS.pad.Pkcs7
        });

      return decrypted.toString(CryptoJS.enc.Utf8);


    } catch (e) {
      console.log(e);
    }
  }

 let data=this.decryptData(this.encrypedcode);
console.log(data);

對於加密,基本思想是

  • 使用 PBKDF2 生成密鑰。
  • 使用 AES 密碼進行加密。

您可以在以下位置閱讀有關此加密的更多信息: CrytoJs 官方文檔

由於解密是在服務器(C#)代碼中,我們需要為它提供值,例如-Salt、iv、我們的密碼中的加密文本。 為了傳遞它,我們將所有信息編碼為 base64 字符串並將其傳遞給服務器。

對於 Angular 中的加密-(我的項目在 TS 中)如果有人有錯誤,例如

  • “wordArray 不包含 concat()”
  • 類型 'WordArray' 不能分配給類型 'string'

我能夠瀏覽一些文檔,並能夠找到能夠組合鹽、iv 和密文的解決方案。

問題在於類型,我們需要有所有這 3 種的 WordArray 格式來編碼。

我的方法很牽強,但它有效

  • 將所有 LIb.WordArray 轉換為 ByteArray,以便將所有 3 個字符串合並為一個。
  • 在編碼為 Base64 之前將組合轉換為 WordArray。
  • 現在將此編碼字符串發送到服務器以在服務器端提取鹽,iv,加密文本以對其進行解密。

確保您的項目中有 @types/crypto-js 和 crypto-js。 我的版本(“crypto-js”:“^4.0.0”,“@types/crypto-js”:“^3.1.47”)。

Angular 端 TypeScript 的加密

encrypt(msg: string) {
//will have this at C# as well.
var pass = "secret";
var keySize = 256;
//random salt
var salt = CryptoJS.lib.WordArray.random(16);
// to generate key
var key = CryptoJS.PBKDF2(pass, salt, {
  keySize: keySize / 32,
  iterations: 1000,
});
// random IV
var iv = CryptoJS.lib.WordArray.random(128 / 8);
//will attach link where you can find these
var encrypted = CryptoJS.AES.encrypt(msg, key, {
  iv: iv,
  padding: CryptoJS.pad.Pkcs7,
  mode: CryptoJS.mode.CBC,
});

//Convert Lib.WordArray to ByteArray so we can combine them like Concat
var saltwords = this.wordArrayToByteArray(salt);
var ivwords = this.wordArrayToByteArray(iv);
var cryptedText = this.wordArrayToByteArray(encrypted.ciphertext);
// combine everything together in ByteArray.
var header = saltwords.concat(ivwords).concat(cryptedText);
//Now convert to WordArray.
var headerWords = this.byteArrayToWordArray(header);
//Encode this to sent to server
var encodedString = CryptoJS.enc.Base64.stringify(headerWords);
return encodedString;  
}

類型轉換

wordArrayToByteArray(wordArray) {
if (
  wordArray.hasOwnProperty("sigBytes") &&
  wordArray.hasOwnProperty("words")
) {
  length = wordArray.sigBytes;
  wordArray = wordArray.words;
}

var result = [],
  bytes,
  i = 0;
while (length > 0) {
  bytes = this.wordToByteArray(wordArray[i], Math.min(4, length));
  length -= bytes.length;
  result.push(bytes);
  i++;
 }
 return [].concat.apply([], result);
 }
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);
}
wordToByteArray(word, length) {
 var ba = [],
  xFF = 0xff;
 if (length > 0) ba.push(word >>> 24);
 if (length > 1) ba.push((word >>> 16) & xFF);
 if (length > 2) ba.push((word >>> 8) & xFF);
 if (length > 3) ba.push(word & xFF);

return ba;
}

C# 的解密與 EVK 給出的答案中提到的相同。

 public static string Decrypt(string cipherText)
    {
        var password = "secret";
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        using (Aes encryptor = Aes.Create())
        {
            // extract salt (first 16 bytes)
            var salt = cipherBytes.Take(16).ToArray();
            // extract iv (next 16 bytes)
            var iv = cipherBytes.Skip(16).Take(16).ToArray();
            // the rest is encrypted data
            var encrypted = cipherBytes.Skip(32).ToArray();
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(password, salt, 1000);
            encryptor.Key = pdb.GetBytes(32);
            encryptor.Padding = PaddingMode.PKCS7;
            encryptor.Mode = CipherMode.CBC;
            encryptor.IV = iv;

            using (MemoryStream ms = new MemoryStream(encrypted))
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    using (var reader = new StreamReader(cs, Encoding.UTF8))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM