如何在PHP中解密Webhook接收的加密数据?
Webhook加密数据解密失败解决指导
问题背景
通过Webhook收到返回数据如下,其中data字段为加密字符串,尝试PHP解密未成功:
{"success":true,"status":200,"error":null,"data":"33c396e22d255a2edbf6b7538190e52295add20b74fbf1500ee360cba5c284783793d113d6cc735271b25804138e1d3b965a2adaa78eddgb17040382a9aa346344606d097317c90c3909649975b1abeca9e201514ffac32c3f34636b5900cd64596691b1c2b82ad2acb3464346dasdas63dasd36asdsf3634adsad34634663asasda70424dc4ba"}
原尝试的解密代码:
<?php // Encrypted data $encrypted_data = "33c396e22d255a2edbf6b7538190e52295add20b74fbf1500ee360cba5c284783793d113d6cc735271b25804138e1d3b965a2adaa78eddgb17040382a9aa346344606d097317c90c3909649975b1abeca9e201514ffac32c3f34636b5900cd64596691b1c2b82ad2acb3464346dasdas63dasd36asdsf3634adsad34634663asasda70424dc4ba"; // Client secret used for encryption $client_secret = "client_secret"; // Attempt decryption $decrypted_data = openssl_decrypt(base64_decode($encrypted_data), 'aes-256-cbc', $client_secret, OPENSSL_RAW_DATA); if ($decrypted_data === false) { echo "Decryption failed: " . openssl_error_string(); } else { echo $decrypted_data; }
问题分析与修正方案
根据AES-256-CBC加密规范,原代码存在以下核心问题:
1. 加密数据编码错误
data字段是十六进制字符串,而非Base64编码,原代码用base64_decode处理完全错误,应替换为hex2bin转换。另外你的加密字符串包含无效十六进制字符(如g、非十六进制字母组合),需先清理或确认原始数据正确性。
2. 密钥长度不符合要求
AES-256要求32字节密钥,直接使用字符串client_secret长度不足,需对密钥做SHA-256哈希生成符合要求的32字节密钥。
3. 缺失初始化向量(IV)
CBC模式必须指定IV,多数场景下IV会附加在密文头部(前16字节),解密时需拆分IV和实际密文。
修正后的解密代码
<?php $encrypted_hex = "33c396e22d255a2edbf6b7538190e52295add20b74fbf1500ee360cba5c284783793d113d6cc735271b25804138e1d3b965a2adaa78eddgb17040382a9aa346344606d097317c90c3909649975b1abeca9e201514ffac32c3f34636b5900cd64596691b1c2b82ad2acb3464346dasdas63dasd36asdsf3634adsad34634663asasda70424dc4ba"; // 清理无效十六进制字符(若原始数据无误可跳过此步) $encrypted_hex = preg_replace('/[^a-fA-F0-9]/', '', $encrypted_hex); $client_secret = "client_secret"; // 生成32字节AES-256密钥 $key = hash('sha256', $client_secret, true); // 十六进制转二进制 $encrypted_bin = hex2bin($encrypted_hex); // 拆分IV(前16字节)和密文 $iv_length = 16; $iv = substr($encrypted_bin, 0, $iv_length); $ciphertext = substr($encrypted_bin, $iv_length); // AES-256-CBC解密 $decrypted = openssl_decrypt($ciphertext, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv); if ($decrypted === false) { echo "解密失败: " . openssl_error_string(); } else { // 去除PKCS7填充(部分场景下openssl_decrypt会自动处理,可根据实际情况调整) $decrypted = rtrim($decrypted, "\x00..\x10"); echo $decrypted; }
额外说明
- 若IV的获取方式与上述不同(如固定值、从其他字段获取),需对应调整IV的来源
- 确保
client_secret是API提供的真实密钥,而非示例中的占位符 - 若清理无效字符后仍解密失败,需确认Webhook返回的
data字段是否完整、无传输错误
内容的提问来源于stack exchange,提问作者KAATIL SUKRAT
相关产品推荐
相关产品推荐

