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

Django中用Fernet加密,PHP解密失败问题求助

PHP解密Django Fernet加密值失败的解决方法

问题描述

尝试在PHP中解密Django用Fernet加密的数据库值时,触发报错:

Decryption failed: error:0606508A:digital envelope routines:EVP_DecryptFinal_ex:data not multiple of block length

使用的代码如下:

$encryption_key = Using same key from django;

$ekyc = Wallet::find('1');
$value= $ekyc->address;

$decodedData = base64_decode(strtr($value, '-_', '+/'));

echo "Decoded Data: " . bin2hex($decodedData) . "<br>";

// Extract the initialization vector (IV) and ciphertext
$ivSize = openssl_cipher_iv_length('aes-128-cbc');
$iv = substr($decodedData, 0, $ivSize);
$ciphertext = substr($decodedData, $ivSize);

echo "IV: " . bin2hex($iv) . "<br>";

// Replace 'aes-128-cbc' with the appropriate cipher and mode if needed
$decrypted_data = openssl_decrypt($ciphertext, 'aes-128-cbc', $encryption_key, OPENSSL_RAW_DATA, $iv);

if ($decrypted_data === false) {
    die('Decryption failed: ' . openssl_error_string());
}
dd($decrypted_data);

问题原因

你的代码未遵循Fernet的规范格式,导致核心参数解析错误:

  1. Fernet结构解析错误:Fernet二进制格式为版本号(1字节) + 时间戳(8字节) + IV(16字节) + 密文 + HMAC(32字节),你直接从开头截取IV,会把版本号、时间戳混入IV,导致IV无效,密文位置错位。
  2. 密钥处理错误:Django的Fernet密钥是base64url编码的32字节数据,需解码后拆分出前16字节的AES密钥和后16字节的HMAC密钥,直接使用原始密钥字符串会导致加密密钥不匹配。
  3. 密文包含冗余数据:你截取的ciphertext包含了HMAC校验部分,这部分不属于AES解密的有效内容,会导致密文长度不符合AES块大小要求,触发报错。

解决方法

按照Fernet规范正确解析数据、处理密钥,可选添加HMAC验证确保数据完整性:

完整可运行代码

// 替换为你的Django Fernet密钥
$fernetKey = "your-django-fernet-key-here";
$ekyc = Wallet::find('1');
$encryptedValue = $ekyc->address;

// 1. 处理Fernet密钥:解码并拆分AES和HMAC密钥
$decodedKey = base64_decode(strtr($fernetKey, '-_', '+/'));
$aesKey = substr($decodedKey, 0, 16);
$hmacKey = substr($decodedKey, 16, 16);

// 2. 解析Fernet加密数据:拆分各组成部分
$decodedData = base64_decode(strtr($encryptedValue, '-_', '+/'));
$iv = substr($decodedData, 9, 16); // IV从第10字节开始(索引9),长度16
$ciphertext = substr($decodedData, 25, -32); // 密文从第26字节到倒数32字节前(排除HMAC)
$hmac = substr($decodedData, -32); // 最后32字节是HMAC校验值

// 3. 可选:验证HMAC,确保数据未被篡改
$expectedHmac = hash_hmac('sha256', substr($decodedData, 0, -32), $hmacKey, true);
if (!hash_equals($hmac, $expectedHmac)) {
    die('HMAC验证失败,数据可能被篡改');
}

// 4. AES-128-CBC解密并去除PKCS#7填充
$decrypted = openssl_decrypt(
    $ciphertext,
    'aes-128-cbc',
    $aesKey,
    OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
    $iv
);
$padding = ord(substr($decrypted, -1));
$decrypted = substr($decrypted, 0, -$padding);

dd($decrypted);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 23:05:09