我正在尝试在JavaScript中复制Java代码。
下面是我的Java代码:

public static String encrypt(String input)
final byte[] SALT= { (byte) 0x21, (byte) 0x21, (byte) 0xF0, (byte) 0x55, (byte) 0xC3, (byte) 0x9F, (byte) 0x5A, (byte) 0x75                     };
final int   ITERATION_COUNT = 31;
{
    if (input == null)
    {
        throw new IllegalArgumentException();
    }
    try
    {

        KeySpec keySpec = new PBEKeySpec(null, SALT, ITERATION_COUNT);
        AlgorithmParameterSpec paramSpec = new PBEParameterSpec(SALT, ITERATION_COUNT);

        SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);

        Cipher ecipher = Cipher.getInstance(key.getAlgorithm());
        ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);

        byte[] enc = ecipher.doFinal(input.getBytes());

        String res = new String(Base64.encodeBase64(enc));
        // escapes for url
        res = res.replace('+', '-').replace('/', '_').replace("%", "%25").replace("\n", "%0A");
        LOGGER.info("String Encrypted Successfully");
        return res;

    }
    catch (Exception e)
    {
        LOGGER.error("encrypt Exception: "+e.getMessage());
    }


    return "";

}


到目前为止,JavaScript代码如下:

var encrypt = function(){
    var iterations = 31;
    var key = CryptoJS.MD5("PBEWithMD5AndDES");
    var salt = CryptoJS.enc.Hex.parse('0021002100f0005500C3009F005A0075');
    var options = {
        mode: CryptoJS.mode.CBC,
        iv: salt
    };
    var hashedPassword = CryptoJS.MD5($scope.data.webPassword);
    var encryptedPassword = CryptoJS.DES.encrypt(hashedPassword, key,options).toString();
    var result = encryptedPassword.toString(CryptoJS.enc.Base64);
}


但是通过两种加密,我得到的编码字符串是不同的。

最佳答案

PBEwithMD5andDES是过时的技术,如今不应该使用。提供此答案仅用于演示目的。

PKCS#5 v1.5中定义了PBEwithMD5andDES,无非就是使用PBKDF1(带有MD5)导出密钥+ IV并使用DES加密。



var password = CryptoJS.enc.Utf8.parse("test");
var salt = CryptoJS.enc.Hex.parse("2121F055C39F5A75");
var iterations = 31;

// PBE according to PKCS#5 v1.5 (in other words: PBKDF1)
var md5 = CryptoJS.algo.MD5.create();
md5.update(password);
md5.update(salt);
var result = md5.finalize();
md5.reset();
for(var i = 1; i < iterations; i++) {
    md5.update(result);
    result = md5.finalize();
    md5.reset();
}

// splitting key and IV
var key = CryptoJS.lib.WordArray.create(result.words.slice(0, 2));
var iv = CryptoJS.lib.WordArray.create(result.words.slice(2, 4));

var encrypted = CryptoJS.DES.encrypt("test", key, {
    iv: iv
});

enchex.innerHTML = encrypted.ciphertext.toString();
encbase64.innerHTML = encrypted.ciphertext.toString(CryptoJS.enc.Base64);

<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/tripledes.js"></script>
<script src="https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/md5.js"></script>
<div>Hex: <span id="enchex"></span></div>
<div>Base64: <span id="encbase64"></span></div>





Here is a jsFiddle进行实验,这里是example Java code。两者在十六进制中产生相同的结果:aa8101a7d63093c6。



安全注意事项:

不应使用PBEwithMD5andDES,还有更好的替代方法,例如PBEWithHmacSHA256AndAES_128,它们需要稍有不同的方法。

为了使密码难以暴力破解,迭代次数必须很大(一千到一百万)。 DES仅提供56位安全性,因此甚至可以用当今的方法直接对密钥进行暴力破解。

必须随机生成盐才能实现语义安全。盐本身不需要保密。由于它具有已知的长度,因此可以简单地加在密文之前,并在解密之前将其切开。

07-28 00:22