zoukankan      html  css  js  c++  java
  • PHP RSA签名(公钥、私钥)

    签名算法:

       Setp.1 确定待签名参数

           在请求参数列表中,除去sign参数外,其他需要使用到的参数皆是要签名的参数。

           在通知返回参数列表中,除去sign参数外,凡是通知返回回来的参数皆是要签名的参数。

       Setp.2 对参数进行排序
           对于待签名的所有参数,需要根据参数名首字符字典顺序(ascii值大小)排序,若遇到相同首字符,则判断第二个字符,以此类推。

      Setp.3 生成待签名字符串
            将排序后的待签名参数以“&“符号拼接, 形如:“参数名1=参数值1&参数名2=参数值2&….&参数名N=参数值N”。

      Setp.4 生成签名/验证签名
            生成签名:把待签名字符串与商户的私钥一同放入RSA的签名函数中进行签名运算,从而得到签名结果字符串(sign值)。

            验证签名:把待签名字符串、平台提供的公钥、通知返回参数中的参数sign值三者一同放入RSA的签名函数中进行签名运算,来判断签名是否验证通过。

    1、公钥、私钥格式化(加上前后戳、每64位进行换行)

         /**********************************私钥格式化*************************************/

     1 function formatPriKey($priKey) {
     2     $fKey = "-----BEGIN PRIVATE KEY-----
    ";
     3     $len = strlen($priKey);
     4     for($i = 0; $i < $len; ) {
     5         $fKey = $fKey . substr($priKey, $i, 64) . "
    ";
     6         $i += 64;
     7     }
     8     $fKey .= "-----END PRIVATE KEY-----";
     9     return $fKey;
    10 }

         /**********************************公钥格式化*************************************/

     1 function formatPubKey($pubKey) {
     2     $fKey = "-----BEGIN PUBLIC KEY-----
    ";
     3     $len = strlen($pubKey);
     4     for($i = 0; $i < $len; ) {
     5         $fKey = $fKey . substr($pubKey, $i, 64) . "
    ";
     6         $i += 64;
     7     }
     8     $fKey .= "-----END PUBLIC KEY-----";
     9     return $fKey;
    10 }

    2、私钥签名、公钥验签

         /**********************************私钥签名*************************************/

     1 /**
     2  * 生成签名
     3  * @param    string     $signString 待签名字符串
     4  * @param    [type]     $priKey     私钥
     5  * @return   string     base64结果值
     6  */
     7 function getSign($signString,$priKey){
     8     $privKeyId = openssl_pkey_get_private($priKey);
     9     $signature = '';
    10     openssl_sign($signString, $signature, $privKeyId);
    11     openssl_free_key($privKeyId);
    12     return base64_encode($signature);
    13 }

         /**********************************公钥验签*************************************/

     1 /**
     2  * 校验签名
     3  * @param    string     $pubKey 公钥
     4  * @param    string     $sign   签名
     5  * @param    string     $toSign 待签名字符串
     6  * @param    string     $signature_alg 签名方式 比如 sha1WithRSAEncryption 或者sha512
     7  * @return   bool
     8  */
     9 function checkSign($pubKey,$sign,$toSign,$signature_alg=OPENSSL_ALGO_SHA1){
    10     $publicKeyId = openssl_pkey_get_public($pubKey);
    11     $result = openssl_verify($toSign, base64_decode($sign), $publicKeyId,$signature_alg);
    12     openssl_free_key($publicKeyId);
    13     return $result === 1 ? true : false;
    14 }

    3、公钥加密、私钥解密

      /**********************************公钥加密*************************************/

     1 /**
     2  *公钥加密
     3   *@param    string     $sign_str   待加密字符串
     4   *@param    string     $public_key  公钥
     5   *@param    string     $signature_alg 加密方式
     6   *@return    string      
     7 */
     8  function get_public_sign($sign_str,$public_key,$signature_alg=OPENSSL_ALGO_SHA1){
     9      $public_key = openssl_pkey_get_public($public_key);//加载密钥
    10      openssl_sign($sign_str,$signature,$public_key,$signature_alg);//生成签名
    11     $signature = base64_encode($signature);     
    12     openssl_free_key($public);
    13     return $signature;
    14  }

      /**********************************私钥解密**************************************/

     1  /**
     2   *私钥解密
     3   *@param    string     $sign_str   待加密字符串
     4   *@param    string     $sign sign
     5   *@param    string     $private_key 私钥
     6   *@param    string     $signature_alg 加密方式
     7   *@return     bool      
     8 */
     9 
    10  function private_verify($sign_str,$sign,$private_key,$signature_alg=OPENSSL_ALGO_SHA1){
    11     $private_key = openssl_get_privatekey($private_key);
    12     $verify = openssl_verify($sign_str, base64_decode($sign), $private_key, $signature_alg);
    13     openssl_free_key($private_key);
    14     return $verify==1;//false or true
    15 }

    示例代码如下(私钥签名公钥验签):

      

    <?php
    
    $pubKey = '-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDr6H/ictALLsV9/63lPFSYDPQK
    gRwEM2FiewfR/BYaPGfpgdl8lelNYqFxnqBRKbGnbFOwOxOu7oiiPYaJxcSU94hI
    d3S0/UsSXyRfTaHT8ZZv+5luikQAG62hwkxqcSdL3aEMbqsHRfQ9RXiFAneiJJwZ
    1D0nHPANfBA4UN+OXQIDAQAB
    -----END PUBLIC KEY-----';
     
    $priKey = '-----BEGIN PRIVATE KEY-----
    MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOvof+Jy0AsuxX3/
    reU8VJgM9AqBHAQzYWJ7B9H8Fho8Z+mB2XyV6U1ioXGeoFEpsadsU7A7E67uiKI9
    honFxJT3iEh3dLT9SxJfJF9NodPxlm/7mW6KRAAbraHCTGpxJ0vdoQxuqwdF9D1F
    eIUCd6IknBnUPScc8A18EDhQ345dAgMBAAECgYEAoNlVIQShn45TcBa97dhV4Zqr
    ZuIjRSX3V5uFeIKGW3smastzjAP3ICGI7Jx4uP5RuFMfOMD/Kb5QgTasHhIvdwe0
    kuMdUqd8YCLgZaV1u02GWkp5I7bG2HRKAqfrpaExeOJt3Iqmggt208P3BNQLTOa2
    NFtNqT+onI1dGwbC120CQQD2BbkrXPv+wGAKkcqIK77Bkrwpg7Iqj91uyVHBAleW
    AgfWDFA3rJb8jDCARHte2ehMImmhbsQmVBjdI1DNdYWLAkEA9XnEoVVIL5IA09s0
    XtL/Na065loDTJsQZiumdi6VMn6zWafu6GFhS0w5DQdkjtA7qhwpftjVRaWtK0DX
    4qpItwJAKxGrbfT0RI/HAHKvYxFNbrPSbu4YNa1D1Y422rQfQyqN1qIHNQfo0sN0
    BjB27I73RMTNey5Z9l/IjoYNMjq9qwJABChZ0jm1jUi1xuDRlEGSnQAgHUKtB6Eg
    t/pJSXskf8RxmTUk8L6lfTb/SF81rs2MFSeA9GsLwbA6rJ7eiTJFJQJBAJnixcdp
    F6knRxyOUDhWoa8uYmnUdcyrfo4dnNyliJbNTTSw0LJAGZsCbo9EDqQIxDrqDa9X
    qj0yz6UT1JM37Tk=
    -----END PRIVATE KEY-----';
    
    //$priKey = formatPriKey($priKey);
    //$pubKey = formatPubKey($pubKey);
    $params = [
        "merchant_id"=>"1",
        "uid"=>"2122334455",
        "out_trade_id"=>"13423423423",
        "amount"=>"88",
        "subject"=>"活动红包"
    ];
     
    //获取预处理字符串
    $signString = getSignString($params);
    //预处理字符串为
    //amount=88&merchant_id=1&out_trade_id=13423423423&subject=活动红包&uid=2122334455
     
    //获取签名
    $sign = getSign($signString,$priKey);
    
    //生成的签名为
    //k8DMuhe+q9rDVDgzAk8lFQEE+tZAahXLiZWExmiYl83vJpZlnKTBghLd1DM8itNzw3JYGhxR8ueHCIkkGyVh0BiPuKYmXFyrCwLVif9sMWCu2DFoEDFARZClDRCfE5rV+IDmumCBfVyxFY/uW/DIMS7AO7GlrydW5aVZ6xYKtBw=
     
    //验证签名
    $res = checkSign($pubKey,$sign,$signString);
    var_dump($res);//结果为 true
     
     
    /**
     * 生成签名
     * @param    string     $signString 待签名字符串
     * @param    [type]     $priKey     私钥
     * @return   string     base64结果值
     */
    function getSign($signString,$priKey){
        $privKeyId = openssl_pkey_get_private($priKey);
        $signature = '';
        openssl_sign($signString, $signature, $privKeyId);
        openssl_free_key($privKeyId);
        return base64_encode($signature);
    }
     
    /**
     * 校验签名
     * @param    string     $pubKey 公钥
     * @param    string     $sign   签名
     * @param    string     $toSign 待签名字符串
     * @param    string     $signature_alg 签名方式 比如 sha1WithRSAEncryption 或者sha512
     * @return   bool
     */
    function checkSign($pubKey,$sign,$toSign,$signature_alg=OPENSSL_ALGO_SHA1){
        $publicKeyId = openssl_pkey_get_public($pubKey);
        $result = openssl_verify($toSign, base64_decode($sign), $publicKeyId,$signature_alg);
        openssl_free_key($publicKeyId);
        return $result === 1 ? true : false;
    }
     
    /**
     * 获取待签名字符串
     * @param    array     $params 参数数组
     * @return   string
     */
    function getSignString($params){
        unset($params['sign']);
        ksort($params);
        reset($params);
     
        $pairs = array();
        foreach ($params as $k => $v) {
            if(!empty($v)){
                $pairs[] = "$k=$v";
            }
        }
     
        return implode('&', $pairs);
    }
    
    /**
     * 格式化私钥
     */
    function formatPriKey($priKey) {
        $fKey = "-----BEGIN PRIVATE KEY-----
    ";
        $len = strlen($priKey);
        for($i = 0; $i < $len; ) {
            $fKey = $fKey . substr($priKey, $i, 64) . "
    ";
            $i += 64;
        }
        $fKey .= "-----END PRIVATE KEY-----";
        return $fKey;
    }
    
    /**
     * 格式化公钥
     */
    function formatPubKey($pubKey) {
        $fKey = "-----BEGIN PUBLIC KEY-----
    ";
        $len = strlen($pubKey);
        for($i = 0; $i < $len; ) {
            $fKey = $fKey . substr($pubKey, $i, 64) . "
    ";
            $i += 64;
        }
        $fKey .= "-----END PUBLIC KEY-----";
        return $fKey;
    }
    ?>
  • 相关阅读:
    ubuntu install gobgp
    ubunut install golang
    Using GoBGP as an IXP connecting router
    400 行 C 代码实现一个虚拟机
    IPv6 Segment Routing (SRv6)
    How to Install VPP in ubuntu x86 or arm64
    mpls + sr + bgp
    ospf sr
    520了,用32做个简单的小程序
    FPGA设计经验总结
  • 原文地址:https://www.cnblogs.com/changning0822/p/9964258.html
Copyright © 2011-2022 走看看