Typescript(Angular)中的加密和Java中的解密

时间:2018-12-19 06:49:37

标签: angular encryption aes cryptojs

我当前正在使用Angular7。 我有Java加密,由客户端提供的解密代码,与Angular一样。

下面是Java代码。

import java.security.SecureRandom;
import java.security.spec.KeySpec;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

我有内部舱位

class EnDc(String passPhrase)
{
    private static final byte[] SALT = { 8 random numbers between -127 to 127 };
    private static final int ITERATION_COUNT = 1000;
    private static final int KEY_LENGTH = 256;
    private static final int IV_LENGTH = 16;
    private Cipher eCipher;
    private Cipher dCipher;
    private byte[] encrypt;
    private byte[] iv;

散列键和iv的生成如下:

    SecretKeyFactory secretKeyFactory = 
            SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    KeySpec keySpec = new PBEKeySpec(passPhrase.toCharArray(), SALT, 
            1000, 256);

他们已生成具有keyspec的临时秘密密钥,如下所示:

    secretKeyTemp = secretKeyFactory.generateSecret(keySpec);

使用临时密钥和“ AES”生成新的秘密密钥

    secretKey = new SecretKeySpec(secretKeyTemp.getEncoded(), //encode 
            "AES");

后续步骤:

    this.eCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    this.eCipher.init(1, secretKey);
    // 1 - ENCRYPT_MODE, 2 - DECRYPT_MODE

IV代:

    this.iv = ((IvParameterSpec)this.eCipher.getParameters().getParameterSpec(IvParameterSpec.class)).getIV();

}

实际加密功能如下

public String encrypt(String encrypt)
      {
        String encStr = null;
        try
        {
          byte[] bytes = encrypt.getBytes("UTF8");
          byte[] encrypted = encrypt(bytes);
          byte[] cipherText = new byte[encrypted.length + this.iv.length];
          System.arraycopy(this.iv, 0, cipherText, 0, this.iv.length);
          System.arraycopy(encrypted, 0, cipherText, this.iv.length, encrypted.length);
          encStr = new String(Base64.getEncoder().encode(cipherText));
        }
        catch (Exception ex)
        {
          ex.printStackTrace();
        }
        return encStr;
      }

我正在尝试在Angular的Service文件中实现此功能,根据我的理解,此处SALT字节数组是预定义的,IV是随机的,它是在加密字符串之前附加并在解密时提取的,

所以我尝试的JS方式如下

import * as CryptoJS from 'crypto-js';

encrypt (msg, pass) {
  const salt = CryptoJS.lib.WordArray.random(128 / 8);

  const key = CryptoJS.PBKDF2( pass, salt, {
      keySize: this.keySize / 32,
      iterations: this.iterations
  });

  const iv =  CryptoJS.lib.WordArray.random(128 / 8);
  const encrypted = CryptoJS.AES.encrypt(msg, key, {
    iv: iv,
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC
  });

  const transitmessage = salt.toString() + iv.toString() + encrypted.toString();
  return transitmessage;
}

因此,我已经从链接http://www.adonespitogo.com/articles/encrypting-data-with-cryptojs-aes/中完成了这段代码,所以现在的问题是如何实现在JAVA中进行硬编码的SALT,并且在JAVA代码中,他们还没有发送附加有Encrypted String的salt密钥,但IV仅作为前16位。我该如何实现呢?

我试图这样做

salt = CryptoJS.lib.WordArray.create([-67, -85, 13, -28, 75, 112, -126, 103]);

但是生成的密钥是对象,解密时也会出错

编辑1:我希望每次生成的盐都一样,这是随机生成并附加到加密的字符串上的。

我不知道是否有一些SecretKeyFactory和Keyspec for Javascript实现

感谢您的帮助,在此先感谢。

2 个答案:

答案 0 :(得分:1)

当您执行以下操作时,WordArray.create方法会将数字用作32位整数:

salt = CryptoJS.lib.WordArray.create([-67, -85, 13, -28, 75, 112, -126, 103]);

在这种情况下,您的十六进制盐为:

ffffffbdffffffab0000000dffffffe40000004b00000070ffffff8200000067

如果将javascript Array对象转换为Int8Array,则CryptoJS将创建与Java中相同的盐:

salt = CryptoJS.lib.WordArray.create(new Int8Array([-67, -85, 13, -28, 75, 112, -126, 103]));

结果:

bdab0de44b708267

答案 1 :(得分:1)

如果适合您,请找到以下解决方案。

encrypt (msg, pass) {
    const key = CryptoJS.PBKDF2(pass, this.salt, {
        keySize: this.keySize / 32,
        iterations: this.iterations
    });

    const iv =  CryptoJS.lib.WordArray.random(128 / 8);

    const encrypted = CryptoJS.AES.encrypt(msg, key, {
          iv: iv,
          padding: CryptoJS.pad.Pkcs7,
          mode: CryptoJS.mode.CBC
    });

    const transitmessage = iv + encrypted.ciphertext;
    var tm=CryptoJS.enc.Hex.parse(transitmessage); // This converts to Type Word which is required for below function as input
    return CryptoJS.enc.Base64.stringify(tm); // Encoding
}