作者 admin 发布的文章

php实现SHA1WithRSA加解密

RSA(SHA1WithRSA)签名逻辑
A.签名字符串为除了sign之外的其他非空字段组成键值对
B.所有参与签名的字段,按字段名的ASCII码从小到大排序后,使用URL的键值对的格式(即key1=value1&key2=value2)拼接成字符串
C.用商户的RSA私钥进行签名
D.请求接口成功后,把系统返回的JSON字符串数据除sign之外的其他所有非空字段组成键值对,进行同样的排序和组装处理,并用公钥进行验签

// 签名
public static function sign($params)
{
    $signString = self::getSignData($params);
    // 私钥加密
    $privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" .
        wordwrap(self::$privateKey, 64, "\n", true) .
        "\n-----END RSA PRIVATE KEY-----";
    $key        = openssl_pkey_get_private($privateKey);
    if ($key === false) {
        throw new Exception('非法的PKCS8 Private Key格式');
    }
    $signature = '';
    $success   = openssl_sign($signString, $signature, $key, OPENSSL_ALGO_SHA1);
    if (!$success) {
        throw new Exception('生成签名失败');
    }
    return base64_encode($signature);
}
// 验签
public static function verifyData($data, $sign)
{
    $signStr = self::getSignData($data);
    $pubKey  = "-----BEGIN PUBLIC KEY-----\n" .
        wordwrap(self::$publicKey, 64, "\n", true) .
        "\n-----END PUBLIC KEY-----";
    if (!$pubKey) {
        throw new Exception('RSA公钥错误。请检查公钥文件格式是否正确');
    }
    $res = (bool)openssl_verify($signStr, base64_decode($sign), $pubKey);
    if (!$res) {
        throw new Exception('签名验证失败');
    }
    return true;
}
// 组装数据
private static function getSignData($params)
{
    unset($params['sign']);
    // 按照ASCII码递增排序
    ksort($params);
    // 组合成 参数=参数值 的格式,并且用 & 字符连接
    $signString = '';
    $i          = 0;
    foreach ($params as $k => $value) {
        if ($i == 0) {
            $signString .= $k . '=' . $value;
        } else {
            $signString .= '&' . $k . '=' . $value;
        }
        $i++;
    }
    return $signString;
}
2026-03-12