CryptoJS的AES加密有两种方式
1. 密码password是string类型的:
CryptoJS.AES.encrypt("123456","123456")//(data,password)
这种方式使用指定的iv也无效,默认使用"AES/CBC/PKCS7Padding"
加密过程:
先生产8字节的salt,再使用 EvpKDF函数传入salt(字节码形式)和password(字节码形式)参数生成Iv和Key
再使用该Iv和Key进行AES加密,加密结果为
Base64("Salted__"(固定字符串:字节码形式)+Salt(字节码形式)+密文 (字节码形式))
所以每次加密的结果前几个字符都是一样的
EvpKDF函数的Java代码
byte[] kBuff = password.getBytes();
byte[] saltBuff = new byte[8];
byte[] keyBuff = new byte[32];
byte[] ivBuff = new byte[16];
EvpKDF(kBuff, 256, 128, saltBuff, keyBuff, ivBuff);
/**
*
* @param password
* @param keySize
* 单位 比特
* @param ivSize
* 单位 比特
* @param salt 盐
* @param resultKey 生成的key
* @param resultIv 生成的iv
* @return
* @throws NoSuchAlgorithmException
*/
public static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, byte[] resultKey,
byte[] resultIv) throws NoSuchAlgorithmException {
return EvpKDF(password, keySize, ivSize, salt, 1, "MD5", resultKey, resultIv);
}
/**
*
* @param password
* @param keySize
* 单位 比特
* @param ivSize
* 单位 比特
* @param salt
* 盐
* @param iterations
* 循环次数
* @param hashAlgorithm
* 摘要算法
* @param resultKey
* @param resultIv
* @return
* @throws NoSuchAlgorithmException
*/
public static byte[] EvpKDF(byte[] password, int keySize, int ivSize, byte[] salt, int iterations,
String hashAlgorithm, byte[] resultKey, byte[] resultIv) throws NoSuchAlgorithmException {
keySize = keySize / 32;
ivSize = ivSize / 32;
int targetKeySize = keySize + ivSize;// =8+4=12块
byte[] derivedBytes = new byte[targetKeySize * 4];// 所需字节
int numberOfDerivedWords = 0;// 4字节计数
byte[] block = null;
MessageDigest hasher = MessageDigest.getInstance(hashAlgorithm);
while (numberOfDerivedWords < targetKeySize) {
if (block != null) {
hasher.update(block);
}
hasher.update(password);
hasher.update(salt);
block = hasher.digest();
hasher.reset();
// Iterations
for (int i = 1; i < iterations; i++) {
block = hasher.digest(block);
hasher.reset();
}
System.arraycopy(block, 0, derivedBytes, numberOfDerivedWords * 4,
Math.min(block.length, (targetKeySize - numberOfDerivedWords) * 4));
numberOfDerivedWords += block.length / 4;
}
System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4);
System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4);
return derivedBytes; // key + iv
}
2 如果password是二进制形式
则按照传统的AES方式进行加密,加密结果只有密文,不带其他信息
var key= CryptoJS.enc.Hex.parse("0102030405060708000000000000000000000000000000000000000000000000");
var iv=CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var content=CryptoJS.enc.Hex.parse("010203040506070809");
var ciphertext = CryptoJS.AES.encrypt(content, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding:CryptoJS.pad.Pkcs7
});
加密结果 M9GSRWldlsYMy3Pbfg+x6Q==
至于如何解密,知道了加密方式,解密也就迎刃而解了。
第一种方法的js解密,比较简单
CryptoJS.AES.decrypt($("密文(字符串形式)","123456")
第二种方法的解密方法,逆过来就可以了。
至于使用Java C# 如果解密 CryptoJS生成的密文,分析上面的过程,
很容易就可以写出相关的代码,就不在这里献丑了。需要强调的是
CryptoJS 密文默认是使用Base64编码,明文先将字符串转成utf-8的字节码
password直接转成utf-8的字节码即可。