如何在PHP中用openssl_verify验证iOS Swift生成的RSA签名?
在PHP中验证iOS Swift生成的RSA签名
嘿,这个问题我之前也碰到过!你iOS端的签名流程没问题,现在PHP这边要做两个关键处理:把iOS导出的DER格式公钥转成PHP能识别的PEM格式,还有确保签名算法完全匹配,这样openssl_verify才能正常工作。
核心步骤说明
- 算法一致性检查:首先要确认iOS端
SecKeyCreateSignature使用的签名算法,比如你大概率用的是kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256(SHA256哈希+PKCS#1 v1.5填充),对应PHP中的OPENSSL_ALGO_SHA256。两者必须严格对应,否则验证一定会失败。 - 公钥格式转换:iOS通过
SecKeyCopyExternalRepresentation导出的公钥是ASN.1 DER格式的Base64字符串,而PHP的openssl_verify需要的是PEM格式的公钥,所以我们要给这个Base64字符串加上PEM头/尾,并按规范拆分每行64字符。 - 签名解码:iOS传递的签名是Base64编码的字符串,PHP需要先解码成二进制原始签名数据。
完整PHP代码示例
/** * 将iOS导出的DER格式Base64公钥转换为PEM格式 * @param string $base64PublicKey iOS端SecKeyCopyExternalRepresentation导出的Base64公钥字符串 * @return string PEM格式公钥 */ function iosRsaPublicKeyToPem(string $base64PublicKey): string { // 先移除Base64字符串中可能存在的空格、换行等冗余字符 $cleanedBase64 = trim(str_replace(["\n", "\r", " "], "", $base64PublicKey)); // 解码为DER二进制数据 $derData = base64_decode($cleanedBase64); // 重新编码为Base64并按每64字符拆分换行 $pemBody = chunk_split(base64_encode($derData), 64, "\n"); // 添加PEM格式的头尾 return "-----BEGIN PUBLIC KEY-----\n" . $pemBody . "-----END PUBLIC KEY-----\n"; } // 从POST请求中获取参数(根据你的实际参数名调整) $originalData = $_POST['data']; $signatureBase64 = $_POST['signature']; $iosPublicKeyBase64 = $_POST['public_key']; // 转换公钥为PEM格式 $pemPublicKey = iosRsaPublicKeyToPem($iosPublicKeyBase64); // 解码签名为二进制数据 $signature = base64_decode($signatureBase64); // 注意:这里的算法必须和iOS端一致! // 对应iOS的kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256 $verifyAlgorithm = OPENSSL_ALGO_SHA256; // 执行签名验证 $verifyResult = openssl_verify($originalData, $signature, $pemPublicKey, $verifyAlgorithm); // 处理验证结果 switch ($verifyResult) { case 1: echo "签名验证通过,数据未被篡改!"; break; case 0: echo "签名验证失败:数据或签名不匹配,可能已被篡改!"; break; default: echo "验证过程出错:" . openssl_error_string(); break; }
关键注意事项
- 算法匹配:如果iOS端用的是其他哈希算法(比如SHA1、SHA512),要对应修改PHP的算法常量:
- SHA1 →
OPENSSL_ALGO_SHA1 - SHA512 →
OPENSSL_ALGO_SHA512
- SHA1 →
- 原始数据一致性:PHP验证时使用的
$originalData必须和iOS端签名的原始数据完全一致,包括编码格式(比如UTF-8)、空格、换行等,任何细微差异都会导致验证失败。 - 公钥完整性:确保iOS传递的公钥Base64字符串没有被截断或修改,否则转换PEM格式时会出错。
内容的提问来源于stack exchange,提问作者julius patta
相关产品推荐
相关产品推荐

