轶哥

妄图改变世界的全栈程序员。

CryptoJS PBKDF2 AES对称加密

CryptoJS提供了和OpenSSL加密命令一致的AES对称加密方法,此方法基于EvpKDFSecret Passphrase 进行计算(This key derivation function is meant to conform with EVP_BytesToKey.),确保进行AES加密计算的key符合长度标准并提升AES加密的安全性。CryptoJS没有直接提供基于PBKDF2的AES加密方法,但在OpenSSL中提供了-pbkdf2参数并将该参数作为AES加密的推荐选项。

CryptoJS:https://github.com/brix/crypto-js

基于 PBKDF2 的 OpenSSL AES加密命令

openssl enc -aes-256-cbc -md sha256 -pbkdf2 -in infile -out outfile -pass pass:"password" -e -base64

所得到的Base64编码后加密结果,进行Base64解码后,以Salted__开头([0x53616c74, 0x65645f5f],Hex: 53616c7465645f5f、Base64前缀:U2FsdGVkX1)。说明其格式遵循OpenSSL的加密定义。在不同后端语言中均可以较方便的找到遵循OpenSSL定义的实现方法,相比自定义的data-salt-iv结构通用性更好,亦可遵循Rfc2898DeriveBytes解密。

CryptoJS 对 PBKDF2 的拓展

CryptoJS.kdf.PBKDF2 = {
  /**
   * Derives a key and IV from a password.
   * @param {string} password The password to derive from.
   * @param {number} keySize The size in words of the key to generate.
   * @param {number} ivSize The size in words of the IV to generate.
   * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly.
   *
   * @return {CipherParams} A cipher params object with the key, IV, and salt.
   *
   * @static
   *
   * @example
   *
   *      var derivedParams = CryptoJS.kdf.PBKDF2.execute('Password', 256/32, 128/32);
   *      var derivedParams = CryptoJS.kdf.PBKDF2.execute('Password', 256/32, 128/32, 'saltsalt');
   */
  execute: function (password, keySize, ivSize, salt) {
    // Generate random salt
    if (!salt) {
      salt = CryptoJS.lib.WordArray.random(64 / 8);
    }

    // Derive key and IV
    var key = CryptoJS.algo.PBKDF2.create({ keySize: (keySize + ivSize) * 4, hasher: CryptoJS.algo.SHA256, iterations: 10000 }).compute(password, salt);

    // Separate key and IV
    var iv = CryptoJS.lib.WordArray.create(key.words.slice(keySize), ivSize * 4);
    key.sigBytes = keySize * 4;

    // Return params
    return CryptoJS.lib.CipherParams.create({ key: key, iv: iv, salt: salt });
  }
}

Format使用Crypto默认提供的方法即可。

JavaScript CryptoJS AES 加密解密测试

var encrypted = CryptoJS.AES.encrypt("MySecretData", "password", { kdf: CryptoJS.kdf.PBKDF2 }).toString();

console.log("Encrypted string:", encrypted); // Encrypted string: U2FsdGVkX1+y5zXrE41OFRQ/uA/m+XYYrAhOO9pts/A=

var decrypted = CryptoJS.AES.decrypt(encrypted, "password", { kdf: CryptoJS.kdf.PBKDF2 }).toString(CryptoJS.enc.Utf8);

console.log("Decrypted string:", decrypted); // Decrypted string: MySecretData

OpenSSL 解密测试

echo 'U2FsdGVkX1+y5zXrE41OFRQ/uA/m+XYYrAhOO9pts/A=' > outfile
openssl enc -aes-256-cbc -pbkdf2 -in outfile -out testfile -pass pass:"password" -d -base64

测试得到testfile文件内容为:

MySecretData%

解密成功。

打赏
交流区

暂无内容

尚未登陆
发布
  上一篇 (人为提升服务器CPU、内存、硬盘使用率)
下一篇 (Node.js调用FFmpeg)  

评论回复提醒