使用PHP解密Twilio加密录音失败,openssl_decrypt返回false如何解决
常见错误点及修正方案
- RSA解密后的CEK处理错误:你使用
OPENSSL_NO_PADDING解密得到的$decryptedKeyData长度和你的RSA密钥长度一致(比如2048位RSA解密后得到256字节数据),但AES-256-GCM所需的密钥仅为32字节,需要取解密结果的最后32字节作为实际密钥,前面的字节都是无填充模式下的前导0,直接用完整解密结果会导致密钥长度不匹配。 - 密文与tag拆分逻辑错误:
openssl_decrypt的第一个参数需要传入剔除了tag的纯密文,你当前直接把包含tag的完整$data传入函数,同时单独传入tag,会导致密文内容错误。需要先拆分密文和tag:$ciphertext = substr($data, 0, -16);,再将$ciphertext作为解密函数的第一个参数。 - IV未做base64解码:你从加密参数中获取的IV是base64编码格式,需要先做base64解码得到原始二进制数据再传入解密函数,直接传入base64字符串会导致IV不匹配。
- 解密参数配置错误:
openssl_decrypt的第四个参数你传入了0,默认会认为输入的密文是base64编码格式,但你已经对录音数据做过base64解码,实际是原始二进制数据,需要将该参数改为OPENSSL_RAW_DATA,否则函数会对密文做二次解码导致内容错误。 - 缺少错误排查逻辑:每次
openssl_decrypt返回false后,调用openssl_error_string()可以拿到具体的错误信息,能快速定位是密钥、IV还是tag的问题。
修正后的参考代码
// 第一步修正:RSA解密后取最后32字节作为AES密钥 $privateKey = openssl_get_privatekey('-----BEGIN RSA PRIVATE KEY----- *****'); $result = openssl_private_decrypt( base64_decode('< encrypted_cek from EncryptionDetails >'), $decryptedKeyData, $privateKey, OPENSSL_NO_PADDING ); $aesKey = substr($decryptedKeyData, -32); // 取最后32字节作为实际密钥 // 第二步修正:拆分密文和tag,正确配置解密参数 $rawAudioData = base64_decode(file_get_contents('https://api.twilio.com/2010-04-01/Accounts/AC***/Recordings/RE***')); $tag = substr($rawAudioData, -16); $ciphertext = substr($rawAudioData, 0, -16); // IV要先做base64解码 $iv = base64_decode('< IV from EncryptionDetails >'); $decrypt = openssl_decrypt( $ciphertext, 'aes-256-gcm', $aesKey, OPENSSL_RAW_DATA, $iv, $tag ); // 排查错误用 if ($decrypt === false) { var_dump(openssl_error_string()); }
内容的提问来源于stack exchange,提问作者Oleksii Boiko
相关产品推荐
相关产品推荐

