将 Java 的 PBEWithMD5AndDES 转换为 JavaScript

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

I'm trying to replicate the Java code in JavaScript. below is my Java code:

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("
", "%0A");
        LOGGER.info("String Encrypted Successfully");
        return res;

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


    return "";

}

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

and the JavaScript code, so far hammed up is below:

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);
}

但是使用两种加密方式,我得到的编码字符串是不同的.

but with both the encryption the encoded string I'm getting is different.

推荐答案

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

PBEwithMD5andDES is obsolete technology and should not be used nowadays. This answer is only provided for demonstration purposes.

PBEwithMD5andDES 在 PKCS#5 v1.5 中定义这无非是使用 PBKDF1(使用 MD5)导出密钥 + IV 并使用 DES 加密.

PBEwithMD5andDES is defined in PKCS#5 v1.5 which is nothing more than deriving key+IV using PBKDF1 (with MD5) and encrypting with 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>

这里是一个 jsFiddle 来试验,这里是 Java 代码示例.两者都产生相同的十六进制结果:aa8101a7d63093c6.

Here is a jsFiddle to experiment with and here is the example Java code. Both produce the same result in Hex: aa8101a7d63093c6.

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

PBEwithMD5andDES should not be used and there are better alternatives like PBEWithHmacSHA256AndAES_128 which require a slightly different approach.

迭代次数必须很大(一千到一百万),以便难以暴力破解密码.DES 仅提供 56 位的安全性,因此甚至可以使用当今的手段直接暴力破解密钥.

The number of iterations must be large (a thousand to a million) in order to make it hard to brute-force the password. DES only provides 56 bits of security, so it is even possible to brute-force the key directly with today's means.

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

The salt must be randomly generated in order to achieve semantic security. The salt itself doesn't need to be secret. Since it has a known length it can be simply prepended to the ciphertext and sliced off before decryption.

相关文章