getMessage() . "\n\n"; } echo "【步骤2】尝试解密建行提供的密文\n"; echo "----------------------------------------\n"; try { // 尝试用demo私钥解密 echo "密文(cnt字段,前100字符):\n" . substr($demoCiphertext, 0, 100) . "...\n\n"; echo "密文总长度: " . strlen($demoCiphertext) . " 字节\n"; echo "开始解密...\n\n"; $decrypted = CcbRSA::decrypt($demoCiphertext, $demoPrivateKey); echo "✓ 解密成功!\n\n"; echo "解密后的明文:\n"; echo $decrypted . "\n\n"; echo "========== 对比验证 ==========\n"; echo "原始明文长度: " . strlen($expectedPlaintext) . " 字节\n"; echo "解密明文长度: " . strlen($decrypted) . " 字节\n"; echo "内容完全一致: " . ($decrypted === $expectedPlaintext ? "✓ 是" : "✗ 否") . "\n\n"; if ($decrypted === $expectedPlaintext) { echo "========== 🎉 验证成功! ==========\n\n"; echo "【结论】\n"; echo "✓ 我们的RSA解密代码完全正确\n"; echo "✓ 我们的MD5签名代码完全正确\n"; echo "✓ 能够正确解密建行提供的标准密文\n\n"; echo "【这说明什么?】\n"; echo "1. 代码逻辑没有问题\n"; echo "2. 489错误不是代码问题,而是配置问题!\n"; echo "3. 最可能的原因:\n"; echo " - 你的公钥未在建行备案\n"; echo " - 服务方编号(YS44000009001853)与密钥不匹配\n"; echo " - 需要使用建行提供的平台公钥加密(而不是商户公钥)\n\n"; echo "【建议行动】\n"; echo "1. 联系建行确认你的公钥是否已备案\n"; echo "2. 确认服务方编号是否正确\n"; echo "3. 询问建行:API加密应该用商户公钥还是建行平台公钥\n\n"; } else { echo "⚠️ 解密内容与原始明文不一致\n\n"; echo "差异分析:\n"; echo "预期: " . substr($expectedPlaintext, 0, 100) . "...\n"; echo "实际: " . substr($decrypted, 0, 100) . "...\n\n"; // 逐字符对比找出差异位置 $len = min(strlen($expectedPlaintext), strlen($decrypted)); for ($i = 0; $i < $len; $i++) { if ($expectedPlaintext[$i] !== $decrypted[$i]) { echo "首个差异位置: 第 $i 个字符\n"; echo "预期字符: '" . $expectedPlaintext[$i] . "' (ASCII: " . ord($expectedPlaintext[$i]) . ")\n"; echo "实际字符: '" . $decrypted[$i] . "' (ASCII: " . ord($decrypted[$i]) . ")\n"; break; } } } } catch (Exception $e) { echo "✗ 解密失败: " . $e->getMessage() . "\n\n"; echo "【可能原因】\n"; echo "1. RSA解密算法实现有误\n"; echo "2. 密钥格式处理有问题\n"; echo "3. BASE64解码有问题\n"; echo "4. PKCS1 Padding处理有误\n\n"; echo "【调试信息】\n"; echo "PHP版本: " . PHP_VERSION . "\n"; echo "OpenSSL版本: " . OPENSSL_VERSION_TEXT . "\n\n"; } echo "========== 测试完成 ==========\n\n";