You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CryptoJS与CryptoSwift的AES-CBC加密结果不一致问题求助

CryptoJS与CryptoSwift AES-CBC加密结果不一致问题

我在使用CryptoJS(JavaScript)和CryptoSwift(Swift)实现AES-CBC加密时,两端参数完全一致(密码、盐值、IV、迭代次数等),但加密输出结果不同,无法互相解密。以下是两端代码及输出:

JavaScript代码

var keySize = 256;
var ivSize = 128;
var iterations = 1000;

var message = "Hello World";
var password = "secret";
var ivSfmc = "4963b7334a46352623252955df21d7f3";
var saltSFmc = "e0cf1267f564b362";
var encryptedString = "";

function encrypt(msg, pass) {
    salt = CryptoJS.enc.Hex.parse(saltSFmc);
    iv = CryptoJS.enc.Hex.parse(ivSfmc);

    var key = CryptoJS.PBKDF2(pass, salt, {
        keySize: keySize / 32,
        padding: CryptoJS.pad.Pkcs7,
        iterations: iterations
    });

    var encrypted = CryptoJS.AES.encrypt(msg, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC
    });

    encryptedString = encrypted.toString();
    return encryptedString;
}

function decrypt(transitmessage, pass) {
    iv = CryptoJS.enc.Hex.parse(ivSfmc);
    salt = CryptoJS.enc.Hex.parse(saltSFmc);

    var key = CryptoJS.PBKDF2(pass, salt, {
        keySize: keySize / 32,
        iterations: iterations
    });

    var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
        iv: iv,
        padding: CryptoJS.pad.Pkcs7,
        mode: CryptoJS.mode.CBC
    })
    return decrypted;
}

var encrypted = encrypt(message, password);
var decrypted = decrypt(encryptedString, password);

JavaScript输出
Encrypted: ndLxNDM5BwSeqNfXAQ5P3g==
Decrypted: Hello World

Swift代码

import UIKit
import CryptoSwift

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            let password: [UInt8] = Array("secret".utf8)
            let salt = Array(hex: "e0cf1267f564b362")

            let key = try PKCS5.PBKDF2(
                password: password,
                salt: salt,
                iterations: 1000,
                keyLength: 32, /* AES-256 */
                variant: .sha256
            ).calculate()

            let iv = Array(hex: "4963b7334a46352623252955df21d7f3")

            let aes = try AES(key: key, blockMode: CBC(iv: iv), padding: .pkcs7)

            let inputData = Array("Hello World".utf8)
            let encryptedBytes = try aes.encrypt(inputData)
            let encryptedData = Data(encryptedBytes)
            print(encryptedData.base64EncodedString())

            let decryptedBytes = try aes.decrypt(encryptedData.bytes)
            let decryptedData = Data(decryptedBytes)
            print(String(bytes: decryptedData, encoding: .utf8)!)

        } catch ( let error) {
            print(error)
        }
    }
}

Swift输出
Encrypted: n05I/Ub/GC/mzQRmlNTl7w==
Decrypted: Hello World


问题原因与解决方案

核心原因

问题出在PBKDF2密钥派生时使用的哈希算法不一致:

  • CryptoJS的PBKDF2方法默认采用SHA-1作为伪随机函数(PRF)
  • Swift代码中明确指定了variant: .sha256,导致两端生成的密钥完全不同,最终加密结果无法匹配。

修正方案(二选一即可)

方案1:修改CryptoJS代码,指定PBKDF2使用SHA256

在PBKDF2的配置参数中添加hasher: CryptoJS.algo.SHA256,确保和Swift端算法一致:

// 加密和解密函数中的密钥生成部分都需要修改
var key = CryptoJS.PBKDF2(pass, salt, {
    keySize: keySize / 32,
    padding: CryptoJS.pad.Pkcs7,
    iterations: iterations,
    hasher: CryptoJS.algo.SHA256 // 新增该行指定SHA256
});

方案2:修改Swift代码,将PBKDF2的哈希算法改为SHA1

把PBKDF2的variant参数改为.sha1,匹配CryptoJS的默认行为:

let key = try PKCS5.PBKDF2(
    password: password,
    salt: salt,
    iterations: 1000,
    keyLength: 32, /* AES-256 */
    variant: .sha1 // 修改为SHA1
).calculate()

验证

任选一种方案修改后,两端生成的加密字符串会完全一致,即可实现互相解密。

内容的提问来源于stack exchange,提问作者mangesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:53:16