fengketrade/test_ccb_decrypt_demo.php
2025-10-22 11:34:32 +08:00

122 lines
6.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 验证能否解密建行提供的demo加密串
* 这是最直接的验证方法!
*/
// 定义应用目录
define('APP_PATH', __DIR__ . '/application/');
// 加载框架引导文件
require __DIR__ . '/thinkphp/base.php';
// 手动引入需要的类文件
require __DIR__ . '/addons/shopro/library/ccblife/CcbRSA.php';
require __DIR__ . '/addons/shopro/library/ccblife/CcbMD5.php';
use addons\shopro\library\ccblife\CcbRSA;
use addons\shopro\library\ccblife\CcbMD5;
echo "\n========== 验证能否解密建行demo加密串 ==========\n\n";
// 建行提供的demo数据来自doc/demo/服务方上送报文样例.txt
$demoPublicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDC+8V1Or6R6H3a7TjuvoDa5k0W/niEGg4N+0Nni+KfwHVX05pI7Qdq1J5+q31yORAoiSSNZNW4uWykmeSltC2mHGkQXClU4JmMXnWFyRCENw1iDIIIEsNax4jFBZUaDCn69PxWgp5wwk+d0V7QRYZ9jkgUaJK+BSYa0KMraxVfJwIDAQAB';
$demoPrivateKey = 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAML7xXU6vpHofdrtOO6+gNrmTRb+eIQaDg37Q2eL4p/AdVfTmkjtB2rUnn6rfXI5ECiJJI1k1bi5bKSZ5KW0LaYcaRBcKVTgmYxedYXJEIQ3DWIMgggSw1rHiMUFlRoMKfr0/FaCnnDCT53RXtBFhn2OSBRokr4FJhrQoytrFV8nAgMBAAECgYEAizhN0thw/altQ4YiIoWvZ50M6iAkWN5prp37kNGWrM40etNB1FQ5+ZN636L+3THVUbwqdzLKTy1GX3jqg05VUIf0sKYYepp+skwZmHVprz4EUKsZXRa+3MnMChJcyHdlyuUNs6HriMq6Qc1+fFEOtZFAf3lo2wYNFw5vIKHGQRECQQDxVKa+6m4y7LmWgiGLYghuL/SGXySFhwBh5+zMNl8V7aAbTX/tH6A0s8JXsSI4iChjWPXthKFTrd7h62vJBjeFAkEAztXpNehF18g3e6JEhtjbTmMsgyj13gdSZSRwjO0Y+IsDI1afnZXzwv96OlukGK8185z0bsbhTCOd6rkcRTnduwJBAOqGknlMh4VTylO66PB0d67lSaPgCDT/al67LcOTPzqnMAX4fc6qAl3VJ5Ni39fCckWB6ZVGZCVW/hfdWmUEdqUCQFFWNXuJd82/YnIwAZq1tKhCv8JkXSuO3YwApHIG2wcCQ52l9ubVjSJlrP8+Am3imOjQFB9r/jUe3H7thHyEoPkCQCay3waa0ll2DY+epkrrF/QO7aMa6NIUArRgWUmqw+1/45csBiWPMUrAD/CPDUr9Jvte92NjoAlz649csbgMM3w=';
// 建行提供的原始报文(明文)
$expectedPlaintext = '{"CLD_HEADER":{"CLD_TX_CHNL":"YSTEST","CLD_TX_TIME":"20191112145911","CLD_TX_CODE":"A3341O031","CLD_TX_SEQ":"1010114131620697023913271"},"CLD_BODY":{"USER_ID":"user123","ORDER_ID":"order123","ORDER_DT":"20191112145811","TOTAL_AMT":"100.00","PAY_AMT":"90.00","DISCOUNT_AMT":"10.00","ORDER_STATUS":"1","REFUND_STATUS":"0","MCT_NM":"XXX商户"}}';
// 建行提供的加密报文密文cnt字段
$demoCiphertext = 'Y2tFMDFJd2RGMGg5aFdXUGtjVVdaSmo4NHBKQzNNZE1wQTRRSXZVRlhBSWhqVEdXNE1LcE9MOXdxY0hhNUlIZndUU0RLK3NrZ1hpTytJUitpREEwSUp0bktRcWMxRG5hN1R0OEtjcUkxTUFDVE5FY2Z0b3lCeTVTaEo3cmNjSnBOUVFsSjRBR2htSzRheEhNb0p6N215eFViK1ZjeGd5WjVTTjJQcHUxQlBnZXJsQXE2Q1lrQ2VuSmZEYUxVSks5RGx2Yk9YWDlDczJiVVllYjlHSHQrUkFuYTljc2hucGhqVWNwNDgrcThNcGhQOElBL20xNVk5NG9lZEV4SXpmc0pDcDExZjFvQ0E5YkwwOWJOZjM4VHR3TkJkTmhqM3lKSVpWeWVpT0FucGhjS3JpOEs5RnlZbXlNVHF1UER3UjhmQ0p5dk5vYkNMS1BPRmQ3WFdXTVczZ29kSWpLaG5OUnhnaFA3N2txdDU3K2Rkd3hGbDgxUEdYbXJWN1ZKWDFOeXRVUFg2dWp3ZzdsUU1OSTlubU1kVE9nbHZJUHRoS205aEludFc2ZFBVTG1DUlNLNzZDc05qTUIyb1hTR2M2cHBNazMxNDJSa05KR0hvY1ZBNFUzcmc4SVk4ZFlYaTUzZmF3cHRES3pHY2JZVFI0SldRVzRNU2ZmSUxvNFpxTkY=';
// 建行提供的MAC签名
$demoMac = '947CAB4DFEBE59265DD28246E4465157';
echo "【步骤1】验证MAC签名\n";
echo "----------------------------------------\n";
try {
$calculatedMac = CcbMD5::signApiMessage($expectedPlaintext, $demoPrivateKey);
echo "原始明文(前100字符):\n" . substr($expectedPlaintext, 0, 100) . "...\n\n";
echo "建行提供的MAC: $demoMac\n";
echo "我们计算的MAC: $calculatedMac\n";
echo "MAC验证结果: " . ($calculatedMac === $demoMac ? "✓ 完全一致" : "✗ 不匹配") . "\n\n";
if ($calculatedMac !== $demoMac) {
echo "⚠️ MAC签名不一致可能原因:\n";
echo " 1. MD5签名算法实现有误\n";
echo " 2. 私钥格式处理有问题\n";
echo " 3. 明文中有特殊字符编码问题\n\n";
}
} catch (Exception $e) {
echo "✗ MAC签名失败: " . $e->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";