mirror of
https://gitee.com/liuxioabin/fengketrade.git
synced 2026-04-17 21:03:17 +08:00
153 lines
5.3 KiB
PHP
153 lines
5.3 KiB
PHP
|
|
<?php
|
|||
|
|
/**
|
|||
|
|
* 诊断建行加密方式
|
|||
|
|
* 尝试不同的解密方法
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
require_once __DIR__ . '/../library/ccblife/CcbRSA.php';
|
|||
|
|
|
|||
|
|
use addons\shopro\library\ccblife\CcbRSA;
|
|||
|
|
|
|||
|
|
echo "========================================\n";
|
|||
|
|
echo " 建行加密方式诊断\n";
|
|||
|
|
echo "========================================\n\n";
|
|||
|
|
|
|||
|
|
// 从.env读取密钥
|
|||
|
|
$envFile = __DIR__ . '/../../../.env';
|
|||
|
|
$envLines = file($envFile, FILE_IGNORE_NEW_LINES);
|
|||
|
|
|
|||
|
|
$privateKey = '';
|
|||
|
|
$publicKey = '';
|
|||
|
|
|
|||
|
|
foreach ($envLines as $line) {
|
|||
|
|
if (stripos($line, 'private_key=') === 0) {
|
|||
|
|
$privateKey = trim(substr($line, 12));
|
|||
|
|
}
|
|||
|
|
if (stripos($line, 'public_key=') === 0) {
|
|||
|
|
$publicKey = trim(substr($line, 11));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
echo "1. 密钥信息\n";
|
|||
|
|
echo " 私钥长度: " . strlen($privateKey) . "\n";
|
|||
|
|
echo " 公钥长度: " . strlen($publicKey) . "\n\n";
|
|||
|
|
|
|||
|
|
// 步骤1: 验证密钥对是否配对
|
|||
|
|
echo "2. 验证密钥对是否配对\n";
|
|||
|
|
try {
|
|||
|
|
$testData = "test=123&name=hello";
|
|||
|
|
$encrypted = CcbRSA::encrypt($testData, $publicKey);
|
|||
|
|
$decrypted = CcbRSA::decrypt($encrypted, $privateKey);
|
|||
|
|
|
|||
|
|
if ($decrypted === $testData) {
|
|||
|
|
echo " ✅ 密钥对配对正确\n\n";
|
|||
|
|
} else {
|
|||
|
|
echo " ❌ 密钥对不匹配\n\n";
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
} catch (\Exception $e) {
|
|||
|
|
echo " ❌ 密钥验证失败: " . $e->getMessage() . "\n\n";
|
|||
|
|
exit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 建行的加密参数
|
|||
|
|
$ccbParamSJ = 'cURYdUJxQ2pJTlVWQUltSW9DQWN1T2xJeFI4WjR2ZVY0NENTVmxPQW9RUVJ1bnJ2Ync5MkwzS2dXdDF1TTVSd3NvUFlsZWFURlYvK243aFNGaWRNeTJsZXRxM1VJR2k0VFdqNnU0Z2JXRnVxMnVIcjhzSVcrRW4xOGxaWDA4Snk0VW1hcFllZ05pekxmc2h6dGFCOTloTUtnVXh2ekJNbDFXZzdwT3lOcDBHZGx5N0FidW1FY1NudmlhNGcxZFAwM09BRk5sUE9USkM4QlJNNWtGTzRKVjFqTWx6RlhrblNwWG0rYmxpS2kyOFpYLy91OGZCR1NPNGp2dHN6b3N1TGxNZnUzd2JNeVUyOVpFTzYxWDRyNm0yb2c0ekZCQWpjc1VLdU9Kcmh1VjVwVDdQZlBlQ0MwRWhLQXFWWXBOdi9uS0FQNkZkZ2JER0ljN2tlUXNHdlFMTWlDeU9rVzdFU2phdG5jYjhZOUNaWkVEb29OdGVLdmlscXg4eHRFS1VtWHljU2ZNeUlDbk5yRW5nR3VXS1AvN3NacTNISE5BWSt2azBHdU1IaG5UWkl6bTdXUmhVYnNRclRYb0ljNy9UTnZVT3lmSVFIcTZ0KzZpZGdtc1NDejBkajVsSjkzVXNSM0NWZExCUk85NHQxZGNEOWorUnFhV2hrWmpiYUE4SlY=';
|
|||
|
|
|
|||
|
|
echo "3. 尝试不同的解密方法\n\n";
|
|||
|
|
|
|||
|
|
// 方法1: 标准RSA解密(用商户私钥)
|
|||
|
|
echo "方法1: 使用商户私钥解密(标准方式)\n";
|
|||
|
|
try {
|
|||
|
|
$urlDecoded = urldecode($ccbParamSJ);
|
|||
|
|
$decrypted = CcbRSA::decrypt($urlDecoded, $privateKey);
|
|||
|
|
|
|||
|
|
echo " 解密成功,长度: " . strlen($decrypted) . "\n";
|
|||
|
|
|
|||
|
|
// 检查是否是可打印字符
|
|||
|
|
$isPrintable = ctype_print($decrypted);
|
|||
|
|
echo " 是否为可打印字符: " . ($isPrintable ? '是' : '否') . "\n";
|
|||
|
|
|
|||
|
|
if ($isPrintable) {
|
|||
|
|
echo " 解密内容: {$decrypted}\n";
|
|||
|
|
parse_str($decrypted, $params);
|
|||
|
|
if (!empty($params)) {
|
|||
|
|
echo " ✅ 解析成功!参数:\n";
|
|||
|
|
foreach ($params as $k => $v) {
|
|||
|
|
echo " {$k} = {$v}\n";
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
echo " 内容预览(十六进制): " . bin2hex(substr($decrypted, 0, 50)) . "...\n";
|
|||
|
|
echo " ❌ 解密结果不是有效文本\n";
|
|||
|
|
}
|
|||
|
|
} catch (\Exception $e) {
|
|||
|
|
echo " ❌ 解密失败: " . $e->getMessage() . "\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
echo "\n";
|
|||
|
|
|
|||
|
|
// 方法2: 尝试用公钥解密(建行可能用建行私钥加密)
|
|||
|
|
echo "方法2: 尝试用商户公钥解密(反向,测试建行是否用私钥加密)\n";
|
|||
|
|
try {
|
|||
|
|
$urlDecoded = urldecode($ccbParamSJ);
|
|||
|
|
|
|||
|
|
// 格式化公钥为PEM
|
|||
|
|
$pemPublicKey = "-----BEGIN PUBLIC KEY-----\n";
|
|||
|
|
$pemPublicKey .= chunk_split($publicKey, 64, "\n");
|
|||
|
|
$pemPublicKey .= "-----END PUBLIC KEY-----\n";
|
|||
|
|
|
|||
|
|
$pubKeyResource = openssl_pkey_get_public($pemPublicKey);
|
|||
|
|
if (!$pubKeyResource) {
|
|||
|
|
throw new \Exception('公钥格式错误');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// BASE64解码
|
|||
|
|
$encryptedData = base64_decode($urlDecoded);
|
|||
|
|
|
|||
|
|
// 获取密钥大小
|
|||
|
|
$keyDetails = openssl_pkey_get_details($pubKeyResource);
|
|||
|
|
$keySize = $keyDetails['bits'] / 8;
|
|||
|
|
|
|||
|
|
// 分块解密
|
|||
|
|
$dataBlocks = str_split($encryptedData, $keySize);
|
|||
|
|
$decrypted = '';
|
|||
|
|
|
|||
|
|
foreach ($dataBlocks as $block) {
|
|||
|
|
$decryptedBlock = '';
|
|||
|
|
// 尝试用公钥解密
|
|||
|
|
$success = @openssl_public_decrypt($block, $decryptedBlock, $pubKeyResource, OPENSSL_PKCS1_PADDING);
|
|||
|
|
if (!$success) {
|
|||
|
|
throw new \Exception('公钥解密失败');
|
|||
|
|
}
|
|||
|
|
$decrypted .= $decryptedBlock;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
openssl_free_key($pubKeyResource);
|
|||
|
|
|
|||
|
|
echo " 解密成功,长度: " . strlen($decrypted) . "\n";
|
|||
|
|
$isPrintable = ctype_print($decrypted);
|
|||
|
|
echo " 是否为可打印字符: " . ($isPrintable ? '是' : '否') . "\n";
|
|||
|
|
|
|||
|
|
if ($isPrintable) {
|
|||
|
|
echo " 解密内容: {$decrypted}\n";
|
|||
|
|
echo " ✅ 可能建行用的是建行私钥加密!\n";
|
|||
|
|
} else {
|
|||
|
|
echo " ❌ 解密结果不是有效文本\n";
|
|||
|
|
}
|
|||
|
|
} catch (\Exception $e) {
|
|||
|
|
echo " ❌ 解密失败: " . $e->getMessage() . "\n";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
echo "\n";
|
|||
|
|
|
|||
|
|
// 方法3: 检查是否需要建行公钥
|
|||
|
|
echo "方法3: 建议检查项\n";
|
|||
|
|
echo " - 确认建行后台配置的商户公钥是否为:\n";
|
|||
|
|
echo " " . substr($publicKey, 0, 50) . "...\n";
|
|||
|
|
echo " - 检查建行是否提供了建行平台公钥(用于解密建行发来的数据)\n";
|
|||
|
|
echo " - 联系建行技术支持确认ccbParamSJ的加密方式\n";
|
|||
|
|
|
|||
|
|
echo "\n========================================\n";
|
|||
|
|
echo "诊断完成\n";
|
|||
|
|
echo "========================================\n";
|