我当前正在使用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实现
感谢您的帮助,在此先感谢。
答案 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
}