【问题标题】:How to achieve CryptoJS decryption using aes-128-cbc algorithm?如何使用 aes-128-cbc 算法实现 CryptoJS 解密?
【发布时间】:2015-07-28 15:35:35
【问题描述】:

我得到了一个使用 Java 生成的加密密钥。我需要使用 CryptoJS 在 AngularJS 应用程序中解密它。我曾使用节点做过类似的事情,但现在在 Angular 中我被卡住了。这个小提琴http://jsfiddle.net/s5g82rqh/ 是我迄今为止尝试过的,但它返回为空。

以下是我到目前为止所尝试的

 function decrypt_core_AES_CBC(password, ciphertext) {
   var iv  = CryptoJS.lib.WordArray.random(128/8);
   var message = CryptoJS.AES.decrypt(ciphertext, password, { mode:    CryptoJS.mode.CBC, iv: password });

  console.log("The current iv is: " + iv.toString() );
  return CryptoJS.enc.Utf8.stringify(message);
 }


var data = '6615702f2dd672f643fd57623d6362a510a98faf4b1c068fd468b525a5fa5471809852a0f9cb7936ce3d3892c233b8c48ce2608f16ce6fa66005b2d97689fbb4';
var key = '3426D38AB846B62B9C236D288778D997';
var dec = decrypt_core_AES_CBC(key, data);

console.log(dec);

下面是适合我的 node.js 代码。我在 CryptoJS 中没有成功实现类似的目标。根据我的理解,加密来自内置库,该节点在其之上有自己的包装器。

var crypto = require('crypto');
var defaultAlgorithm= 'aes-128-cbc';
var defaultFormat= 'hex';
var ivLength= 16;
function decode (data, key, algorithm, format) {

    // Make sure the data is a buffer object
    if (data instanceof Buffer) {
        data = data.toString();
    }

    // Get defaults if needed
    algorithm = algorithm || defaultAlgorithm;
    format = format || defaultFormat;

    ivLength = ivLength * 2;

    // Get the initialization vector
    var iv = new Buffer(data.substring(0, ivLength), 'hex');

    // Remove the iv from the data
    data = data.substring(ivLength);
    var decipher = crypto.createDecipheriv(algorithm, new Buffer(key, 'hex'), iv);
    var decrypted = decipher.update(data, format, 'utf8') + decipher.final('utf8');

    return decrypted;
}

var data ='6615702f2dd672f643fd57623d6362a510a98faf4b1c068fd468b525a5fa5471809852a0f9cb7936ce3d3892c233b8c48ce2608f16ce6fa66005b2d97689fbb4';
var key = '3426D38AB846B62B9C236D288778D997';
var dec = decode(data, key, defaultAlgorithm, defaultFormat);

console.log(dec);

【问题讨论】:

    标签: javascript node.js encryption aes cryptojs


    【解决方案1】:

    你有三个问题:

    • CryptoJS 支持两种类型的加密/解密:从密码派生的密钥和直接传递的密钥。您想从密钥执行此操作,因此您需要将十六进制编码的密钥字符串解析为 CryptoJS 的本机格式,然后再将其传递给 decrypt() 函数:

      key = CryptoJS.enc.Hex.parse(key);
      

      另外,不要将密钥与密码混淆。

    • 您忘记在解密之前从密文中切出 IV。

      var iv = CryptoJS.enc.Hex.parse(ciphertext.slice(0, 32));
      ciphertext = CryptoJS.enc.Hex.parse(ciphertext.slice(32));
      
    • CryptoJS' 需要一个 CipherParams 对象或一个 OpenSSL 格式的字符串来解密。由于您只有一个十六进制字符串,因此您必须在使用前对其进行解析并像这样使用它:

      var message = CryptoJS.AES.decrypt({
          ciphertext: ciphertext
      }, key, {
          iv: iv
      });
      

    【讨论】:

    • 感谢您的关注。我试过你的建议,似乎我太接近解决这个问题了。我控制台日志消息变量及其给定数组 words 但现在当我尝试使用 CryptoJS.enc.Utf8 对其进行字符串化时,它给了我空的结果。更新小提琴jsfiddle.net/5k1vtz77/1您的建议将不胜感激。再次感谢!
    • 对不起,我忘记解析密文了。输出为“1280c6dc-4a17-4b75-aa83-f4ce224cfbce”。
    • 这是一个可用的小提琴的更新版本:jsfiddle.net/fyodgw58/1
    【解决方案2】:

    我花了一周的时间才找到用 Java、PHP 和 Java Script 编写的 aes-128-cbc 的工作代码。我不得不在各种网站上搜索很多。最后通过多次点击和试用,下面的代码为我解决了。既加密又解密。用Java加密;在 PHP 或 JavaScript 中解密,在 PHP 中加密;用 Java 或 JavaScript 解密,用 JavaScript 加密 用 PHP 或 Java 解密。所有选项都会起作用

    Key 的长度为 16 位,包含字母数字值。使用相同的密钥来加密和解密数据。 IV 是加密时要传递的 16 位字母数字的随机值。

    加解密PHP代码:

      function encrypt($key, $iv, $data) {
      
        static $OPENSSL_CIPHER_NAME = "aes-128-cbc"; //Name of OpenSSL Cipher 
        static $CIPHER_KEY_LEN = 16; //128 bits
    
        if (strlen($key) < $CIPHER_KEY_LEN) {
            $key = str_pad("$key", $CIPHER_KEY_LEN, "0"); //0 pad to len 16
        } else if (strlen($key) > $CIPHER_KEY_LEN) {
            $key = substr($str, 0, $CIPHER_KEY_LEN); //truncate to 16 bytes
        }
        
        $encodedEncryptedData = base64_encode(openssl_encrypt($data, $OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv));
        $encodedIV = base64_encode($iv);
        $encryptedPayload = $encodedEncryptedData.":".$encodedIV;
        
        return $encryptedPayload;
    }
    
    function decrypt($key, $data) {
        // $key = $request['key'];
        // $data = $request['data'];
    
         static $OPENSSL_CIPHER_NAME = "aes-128-cbc"; //Name of OpenSSL Cipher 
         static $CIPHER_KEY_LEN = 16; //128 bits
    
        if (strlen($key) < $CIPHER_KEY_LEN) {
            $key = str_pad("$key", $CIPHER_KEY_LEN, "0"); //0 pad to len 16
        } else if (strlen($key) > $CIPHER_KEY_LEN) {
            $key = substr($str, 0, $CIPHER_KEY_LEN); //truncate to 16 bytes
        }
        
        $parts = explode(':', $data); //Separate Encrypted data from iv.
        $decryptedData = openssl_decrypt(base64_decode($parts[0]), $OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, base64_decode($parts[1]));
        
        return $decryptedData;
        }
    

    用于加密和解密的 Java 代码

      import android.util.Base64;
      import android.util.Log;
    
      import javax.crypto.Cipher;
      import javax.crypto.spec.IvParameterSpec;
      import javax.crypto.spec.SecretKeySpec;
    
    public class Java_AES_Cipher {
    
    private static String CIPHER_NAME = "AES/CBC/PKCS5PADDING";
    private static int CIPHER_KEY_LEN = 16; //128 bits
    
    /**
     * Encrypt data using AES Cipher (CBC) with 128 bit key
     *
     *
     * @param key  - key to use should be 16 bytes long (128 bits)
     * @param iv - initialization vector
     * @param data - data to encrypt
     * @return encryptedData data in base64 encoding with iv attached at end after a :
     */
    public static String encrypt(String key, String iv, String data) {
        try {
            if (key.length() < Java_AES_Cipher.CIPHER_KEY_LEN) {
                int numPad = Java_AES_Cipher.CIPHER_KEY_LEN - key.length();
    
                for(int i = 0; i < numPad; i++){
                    key += "0"; //0 pad to len 16 bytes
                }
    
            } else if (key.length() > Java_AES_Cipher.CIPHER_KEY_LEN) {
                key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
            }
    
    
            IvParameterSpec initVector = new IvParameterSpec(iv.getBytes("ISO-8859-1"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"), "AES");
    
            Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, initVector);
    
            byte[] encryptedData = cipher.doFinal((data.getBytes()));
    
            String base64_EncryptedData = Base64.encodeToString(encryptedData, Base64.DEFAULT);
            String base64_IV = Base64.encodeToString(iv.getBytes("ISO-8859-1"), Base64.DEFAULT);
    
            base64_EncryptedData = base64_EncryptedData.replaceAll(System.getProperty("line.separator"), "");
            base64_IV = base64_IV.replaceAll(System.getProperty("line.separator"), "");
    
            Log.i("Java_AES_Cipher","Encrypted data is "+ base64_EncryptedData + ":" + base64_IV);
    
            return base64_EncryptedData + ":" + base64_IV;
    
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    
        return null;
    }
    
    /**
     * Decrypt data using AES Cipher (CBC) with 128 bit key
     *
     * @param key - key to use should be 16 bytes long (128 bits)
     * @param data - encrypted data with iv at the end separate by :
     * @return decrypted data string
     */
    
    public static String decrypt(String key, String data) {
        try {
    
            if (key.length() < Java_AES_Cipher.CIPHER_KEY_LEN) {
                int numPad = Java_AES_Cipher.CIPHER_KEY_LEN - key.length();
    
                for(int i = 0; i < numPad; i++){
                    key += "0"; //0 pad to len 16 bytes
                }
    
            } else if (key.length() > Java_AES_Cipher.CIPHER_KEY_LEN) {
                key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
            }
    
            String[] parts = data.split(":");
    
            if (parts.length<2)
            {
                Log.i("Java_AES_Cipher","Length "+ parts.length);
                return data;
            }
    
            IvParameterSpec iv = new IvParameterSpec(Base64.decode(parts[1], Base64.DEFAULT));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("ISO-8859-1"), "AES");
    
            Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
    
            byte[] decodedEncryptedData = Base64.decode(parts[0], Base64.DEFAULT);
    
            byte[] original = cipher.doFinal(decodedEncryptedData);
    
            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    
        return null;
    }
    

    用于加密和解密的 Java 脚本代码

       <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.js"></script>
    
    
      function encrypt (messageText,key, iv){
        var message = messageText;
        var key = CryptoJS.enc.Utf8.parse(key);
        var iv  = CryptoJS.enc.Utf8.parse(iv);
    
    var encrypted = CryptoJS.AES.encrypt(
        message,key,
        {
            iv: iv,
            mode: CryptoJS.mode.CBC,
            padding: CryptoJS.pad.Pkcs7
        }
    );
    this.encrypted = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
    console.log('encrypted:'+encrypted);
    return encrypted;
       }
    
    
      function decrypt(keyBase64, messagebase64) {
            const digest = messagebase64.split(':');
    
            const crypttext = CryptoJS.enc.Base64.parse(digest[0])
            const ivBase64 = CryptoJS.enc.Base64.parse(digest[1])
    
            const decrypted = CryptoJS.AES.decrypt(
                {
                ciphertext: crypttext
                },
                CryptoJS.enc.Utf8.parse(keyBase64),
                {
                iv: ivBase64,
                mode: CryptoJS.mode.CBC,
                padding: CryptoJS.pad.Pkcs7
                }
            );
            console.log('decrypted: '+decrypted.toString(CryptoJS.enc.Utf8));
            return decrypted.toString(CryptoJS.enc.Utf8);
    }
    

    【讨论】:

      猜你喜欢
      • 2013-08-11
      • 2021-08-13
      • 1970-01-01
      • 2018-04-04
      • 2019-06-27
      • 2017-09-18
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多