将Java的PBEWithMD5AndDES转换为JavaScript

时间:2016-08-17 07:32:06

标签: javascript java encryption passwords cryptojs

我正在尝试用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);
}

但是对于加密,我得到的编码字符串是不同的。

1 个答案:

答案 0 :(得分:3)

PBEwithMD5andDES是过时的技术,现在不应该使用。 此答案仅用于演示目的。

PBEwithMD5andDES在PKCS#5 v1.5中定义,它只不过是使用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);
&#13;
<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>
&#13;
&#13;
&#13;

Here is a jsFiddle要试验,这里是example Java code。两者在Hex中产生相同的结果:aa8101a7d63093c6。

安全注意事项:

不应该使用PBEwithMD5andDES,并且有更好的替代方案,如PBEWithHmacSHA256AndAES_128,这需要稍微不同的方法。

迭代次数必须很大(一千到一百万)才能使密码暴力破解变得困难。 DES只提供56位安全性,因此甚至可以用今天的方式直接强制关键。

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