PHP在做api开发中,RSA加密签名算法如何使用 ?

RSA 加密是什么

RSA(Rivest-Shamir-Adleman)是最早的公钥密码系统之一,广泛用于安全数据传输。3 位数学家 Rivest、Shamir 和 Adleman 的名字来命名的。

是非对称加密的一种 这种算法非常可靠,密钥越长,它就越难破解。

在这样的密码系统中,加密密钥是公共的,并且它与保密(私有)的解密密钥不同

加密

RSA 密码体制是一种公钥密码体制,加密算法公开,以分配的密钥作为加密解密的关键

一般来说,在一对公私钥中,公钥和私钥都可以用来加密和解密,即公钥加密能且只能被对应的私钥进行解密

私钥加密能且只能被对应的公钥进行解密。

一般我们都是把公钥公开出去 如果我们是服务方 一般我们是拿私钥加密 接收方来拿公钥进行验签等

为了保证加密安全 建议 RSA 密钥的长度为 2048

签名

签名就是在这份资料后面增加一段强而有力的证明,以此证明这段信息的发布者和这段信息的有效性完整性。

简单来说,签名主要包含两个过程:摘要 和 非对称加密,首先对需要签名的数据做摘要(类似于常见的 MD5)后得到摘要结果。

然后通过签名者的私钥对摘要结果进行非对称加密即可得到签名结果

支付中签名的套路

来说下对接的支付中的签名,拿 支付宝 举例

生成签名

  1. 生成参数并进行 url_encode 然后按照字典排序,组成字符串 等到待签名字符串。

  2. 获取私钥 然后使用各自语音的加密方法 对待签名字符串进行加密

  3. 得到签名 (sign) 后并进行 base64 转码

  4. 把加密字符串的的数组 和 签名 一并发给接受方

验证签名

  1. 在通知返回参数列表中,除去 签名参数 (sign ) 以及空的参数 其他的全部都是待签名的参数。

  2. 将剩下参数进行 url_decode, 然后进行字典排序, 使用 & = 组成字符串,得到待签名字符串。

  3. 将签名参数(sign)使用 base64 解码为字节码串。

  4. 使用 RSA 的验签方法,通过签名字符串、签名参数(经过 base64 解码)及支付宝公钥验证签名,根据返回结果判定是否验签通过

PHP 中 OpenSSL 的使用

php 的扩展中有 OpenSSL 库 可以用来操作 对称/非对称的加密 算法

下面贴段大概的 PHP 示例代码

生成待 签名 / 验签 的字符串

php 复制代码
/**
 * 生成待签名的字符串
 * @param $data 参与签名的参数数组
 * @return string 待签名的字符串
 */
function getSignStr($data)
{
    //排序
    ksort($data);
    //剔除sign 如果对方的签名叫sign 或者可以在调用方法的时候剔除
    //unset($data['sign']);

    $stringToBeSigned = '';

    $i = 0;

    foreach ($data as $k => $v) {
        if ($i == 0) {
            $stringToBeSigned .= "$k" . "=" . "$v";
        } else {
            $stringToBeSigned .= "&" . "$k" . "=" . "$v";
        }

        $i++;
    }

    return $stringToBeSigned;
}
复制代码
生成签名,返回签名字符串sign
php 复制代码
/**
 * 生成签名
 * @param array $params 待签名的所有参数
 * @return string 生成的签名
 */
function getSignGenerator($params)
{
    //生成待验签的字符串
    $data = $this->getSignStr($params);
    //私钥的内容 一行的格式
    $privateKey = 'xxx';

    $pem = "-----BEGIN RSA PRIVATE KEY-----\n" .
        wordwrap($privateKey, 64, "\n", true) .
        "\n-----END RSA PRIVATE KEY-----";

    //openssl_private_encrypt($data, $crypted, $pem);
    openssl_sign($data, $sign, $pem, OPENSSL_ALGO_SHA256);

    $sign = base64_encode($sign);

    return $sign;
}

验证签名

php 复制代码
/**
 * 验证签名
 * @param array $params 待签名的所有参数
 * @param string $sign 生成的签名
 * @return boolean 校验的结果
 */
function signCheck($params, $sign)
{
    //生成待验签的字符串
    $data = $this->getSignStr($params);
    //对方的公钥内容 一行的形式
    $publicKey = 'xxx';

    $pem = "-----BEGIN PUBLIC KEY-----\n" .
        wordwrap($publicKey, 64, "\n", true) .
        "\n-----END PUBLIC KEY-----";

    $checkResult = (bool)openssl_verify($data, base64_decode($sign), $pem, OPENSSL_ALGO_SHA256);

    return $checkResult;
}

自己的加密方法

php 复制代码
/**
 * 我们自己的加密
 * @param $str 待加密的字段
 * @return string
 */
function encrypt($string)
{
    //公钥内容 一行的形式
    $pubKey = 'xxxx';

    $res = "-----BEGIN PUBLIC KEY-----\n" .
        wordwrap($pubKey, 64, "\n", true) .
        "\n-----END PUBLIC KEY-----";

    openssl_public_encrypt($string, $encrypt, $res);

    return base64_encode($encrypt);
}

自己的解密方法

php 复制代码
/**
 * 我们自己的解密
 * @param $secret 加密后的base64字段
 * @return string
 */
function decrypt($secret)
{
    //私钥内容 一行的形式
    $privateKey = 'xx';

    $res = "-----BEGIN RSA PRIVATE KEY-----\n" .
        wordwrap($privateKey, 64, "\n", true) .
        "\n-----END RSA PRIVATE KEY-----";

    openssl_private_decrypt(base64_decode($secret), $oldData, $res);

    return $oldData;
}

注意:主要使用到下面几个函数 分别都是对应的

私钥加密 openssl_private_encrypt => 公钥解密 openssl_public_decrypt

公钥加密 openssl_public_encrypt => 私钥解密 openssl_private_decrypt

使用的时候分别使用对应的公钥 / 私钥的文件内容即可,我是把公钥和私钥都配置了一行形式 (也就是没有换行符等 方便配置吧)。

相关推荐
一匹电信狗15 分钟前
浅谈Linux中的Shell及其原理
linux·服务器·c语言·开发语言·c++·ssh·unix
每次的天空43 分钟前
kotlin与MVVM的结合使用总结(二)
android·开发语言·kotlin
Imagine Miracle1 小时前
【Rust】枚举和模式匹配——Rust语言基础14
开发语言·后端·rust
无名之逆1 小时前
探索 Rust 高效 Web 开发:Hyperlane 框架深度解析
开发语言·后端·算法·面试·rust
轩宇^_^1 小时前
C++ 布尔类型(bool)深度解析
开发语言·c++
byxdaz1 小时前
QT编程之OSG
开发语言·qt
阿_星_1 小时前
解决pip install 出现error: subprocess-exited-with-error的问题
开发语言·python·pip
Hum8le1 小时前
CTF题目《SSRFMe》(网鼎杯 2020 玄武组)WriteUp
redis·python·安全·web安全·php
alicema11112 小时前
Python+Django网页前后端rsp云端摄像头人数监控系统
开发语言·网络·后端·python·神经网络·算法·django
StevenLdh2 小时前
Java Spring Boot 常用技术及核心注解
java·开发语言·spring boot