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

如何在MySQL中解密Java生成的AES加密值?

Java AES+PBKDF2WithHmacSHA1加密内容的MySQL解密问题

Java端解密实现

以下是Java中基于AES-CBC/PKCS5Padding,通过PBKDF2WithHmacSHA1派生密钥的解密代码:

public String decryptAttr(String dbData, String key, String iv){
    
    try {
        String password = hash256(key);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
       
       // 分离盐值、IV和密文
        ByteBuffer buffer = ByteBuffer.wrap(new Base64().decode(dbData));
        byte[] saltBytes = new byte[saltLength];
        buffer.get(saltBytes, 0, saltBytes.length);
        
        byte[] ivBytes1 = new byte[cipher.getBlockSize()];
        buffer.get(ivBytes1, 0, ivBytes1.length);
        
        byte[] encryptedTextBytes = new byte[buffer.capacity() - saltBytes.length - ivBytes1.length];
        buffer.get(encryptedTextBytes);
        
        // 派生密钥
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        // 注意:此处疑似笔误,应为password.toCharArray(),否则密钥派生会不一致
        PBEKeySpec spec = new PBEKeySpec(hash256Password.toCharArray(), saltBytes, iterationCount, keyLength);
        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");

        cipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(ivBytes1));
        
        byte[] decryptedTextBytes = cipher.doFinal(encryptedTextBytes);
        return new String(decryptedTextBytes);

    } catch (Exception e) {
        e.printStackTrace();
    } 
    return null;
}

MySQL端解密尝试与问题

在MySQL 8.0.30中执行以下设置和解密语句:

SET session block_encryption_mode = 'aes-128-cbc';
SET @key_str = UNHEX(SHA2('4028c2ac696ba930016a2fc6765800e6',256));

-- 执行解密时触发错误
select AES_DECRYPT(SUBSTRING(HEX(FROM_BASE64('vzAXFDpaIRx0ctFWZ4hSl27c8vNApWgefBFVfj4wPYawFyrRkTPVJcjvKrheZR6UpwIArQ==')),73), @key_str, SUBSTRING(HEX(FROM_BASE64('vzAXFDpaIRx0ctFWZ4hSl27c8vNApWgefBFVfj4wPYawFyrRkTPVJcjvKrheZR6UpwIArQ==')),41,32), 'pbkdf2_hmac',SUBSTRING(HEX(FROM_BASE64('vzAXFDpaIRx0ctFWZ4hSl27c8vNApWgefBFVfj4wPYawFyrRkTPVJcjvKrheZR6UpwIArQ==')),1,40),2 );

遇到两个核心问题:

  1. 错误提示迭代次数小于1000不被允许:ERROR 3236 (HY000): For KDF method pbkdf2_hmac iterations value less than 1000 or more than 65535 is not allowed due to security reasons.
  2. 指定KDF方法为PBKDF2WithHmacSHA1时提示名称无效。

解决方案

1. 迭代次数限制问题

MySQL对PBKDF2的迭代次数强制要求在1000-65535区间内,处理方式分两种:

  • 若可修改Java代码:将iterationCount调整至1000以上(推荐≥10000),重新加密数据后再用MySQL解密。
  • 若需解密已有的低迭代次数数据:无法通过MySQL直接解密,建议直接使用Java代码解密,或自行在MySQL中实现PBKDF2WithHmacSHA1(复杂度高,不推荐)。

2. KDF方法名称与参数匹配问题

Java中使用的PBKDF2WithHmacSHA1对应MySQL的pbkdf2_hmac方法,需额外指定哈希算法为SHA1,而非直接使用Java的方法名。

3. 修正密文解析逻辑

之前的语句通过HEX字符串截取位置容易出错,建议直接对字节数组进行截取,匹配Java中[salt][iv][密文]的存储结构:

假设Java中saltLength=16(常见值)、iterationCount≥1000,正确的MySQL解密语句如下:

SET session block_encryption_mode = 'aes-128-cbc';

-- 生成与Java中hash256(key)一致的密码输入
SET @password_str = SHA2('4028c2ac696ba930016a2fc6765800e6', 256);

-- 解析Base64编码的加密数据
SET @encrypted_b64 = 'vzAXFDpaIRx0ctFWZ4hSl27c8vNApWgefBFVfj4wPYawFyrRkTPVJcjvKrheZR6UpwIArQ==';
SET @encrypted_bin = FROM_BASE64(@encrypted_b64);

-- 提取盐值(16字节,对应Java中的saltLength)
SET @salt_bin = SUBSTRING(@encrypted_bin, 1, 16);
-- 提取IV(AES块大小为16字节)
SET @iv_bin = SUBSTRING(@encrypted_bin, 17, 16);
-- 提取密文
SET @ciphertext_bin = SUBSTRING(@encrypted_bin, 33);

-- 执行解密:指定PBKDF2+HMAC-SHA1,迭代次数替换为Java中实际值
SELECT AES_DECRYPT(
    @ciphertext_bin,
    @password_str,
    @iv_bin,
    'pbkdf2_hmac',
    @salt_bin,
    1000, -- 替换为Java代码中实际的iterationCount,必须≥1000
    'SHA1'
) AS decrypted_text;

关键注意事项

  • 确保Java与MySQL的所有参数完全一致:盐值长度、迭代次数、密钥长度、PBKDF2的输入密码(Java中hash256(key)的结果必须和MySQL中@password_str一致)。
  • 若Java中iterationCount<1000,只能通过Java代码解密,无法绕过MySQL的安全限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:52:21