Home  >  Article  >  Backend Development  >  Implement SHA1withRSA signature, encryption, and verification using PHP

Implement SHA1withRSA signature, encryption, and verification using PHP

little bottle
little bottleforward
2019-04-18 11:19:179508browse

I saw a PHP signature encryption code shared by a PHP expert on the Internet. I would like to share it with you. If you are interested, please come and find out more.

Concept explanation:

The SHA1 secure hash algorithm is mainly applicable to the digital signature algorithm defined in the digital signature standard.

RSA is currently the most influential public key encryption algorithm. It can resist most password attacks known so far and has been recommended by ISO as a public key data encryption standard.

SHA1WithRSA: Use the SHA algorithm for signing and the RSA algorithm for encryption.

Business requirements:

The content assembled by each signature is sorted and connected in ascending dictionary order of the field names

Assemble the content that needs to be signed first:

/**
     * 拼接需要签名的内容
     * Author: Tao.
     *
     * @param array $data 需签名的字段内容
     * 
     * @return string
     */     
    public static function getSign($data)
    {
        foreach ($data as $k => $v) {
            $Parameters[$k] = $v;
        }
        //按字典序排序参数
        ksort($Parameters);
        $sign = '';
        foreach ($Parameters as $k => $v) {
            $sign .= $k . "=" . $v . "&";
        }
        $sign = '&' . rtrim($sign, '&');
        return $sign;
    }

The signature string is as follows:
&amount=amount value&ccy=ccy value&merchantId=merchantId value¬ifyUrl=notifyUrl value&orderId=orderId value&payeeAcctNo=payeeAcctNo value (plain text).

It should be noted that according to business needs, you can choose whether to splice the ampersand before the signature content.

Then generate the secret key signature:

/**
     * 秘钥加密
     * Author: Tao.
     *
     * @param string $data 之前生成好的需加密内容
     * @param $key 私钥证书位置(.pfx文件)
     * @param string $pwd 证书密码
     *
     * @return string
     */
    public static function SHA1withRSA($data, $key,$pwd)
    {
        openssl_pkcs12_read(file_get_contents($key), $certs, $pwd); 
        if (!$certs) return;
        $signature = '';
        openssl_sign($data, $signature, $certs['pkey']);
        return bin2hex($signature);  
    }

Since the third-party company requires conversion to hexadecimal, you can choose bin2hex() or base64_encode() according to your needs.

What should be noted here is whether the signed content needs to be case-sensitive according to business needs.

The signed content should be in lowercase and can be converted to uppercase using strtoupper().

The above is the private key encryption method compiled for everyone.

But this business also requires that the bank card number needs to be encrypted with RSA public key
The following is the method to obtain the public key:
Here is Obtain the public key of the other party's platform certificate (.cer file)


/**
     * 获取公钥
     * Author: Tao.
     *
     * @param $path //公钥证书位置 (.cer文件)
     *
     * @return mixed
     * @throws \Exception
     */
    public static function loadCert($path)
    {
        $file = file_get_contents($path);
        if (!$file) {
            throw new \Exception('loadx509Cert::file_get_contents ERROR');
        }

        $cert = chunk_split(base64_encode($file), 64, "\n");
        $cert = "-----BEGIN CERTIFICATE-----\n" . $cert . "-----END CERTIFICATE-----\n";

        $res = openssl_pkey_get_public($cert);
        $detail = openssl_pkey_get_details($res);
        openssl_free_key($res);

        if (!$detail) {
            throw new \Exception('loadX509Cert::openssl_pkey_get_details ERROR');
        }
        return $detail['key'];
    }

    /**
     * 公钥加密
     * Author: Tao.
     * 
     * @param $pubPath  //公钥证书位置 (.cer文件)
     * @param string $bankCode //银行卡号
     * 
     * @return string
     */
    public static function rsa_encode($bankCode,$pubPath)
    {
        $pubkey = self::loadCert($pubPath);
        $encrypt_data = '';
        openssl_public_encrypt($bankCode, $encrypt_data, $pubkey);
        $encrypt_data = base64_encode($encrypt_data);
        return $encrypt_data;
    }

You have to ask me why the private key is bin2hex() and the public key is changed to base64_encode(). I don’t know why. I asked and it said it was 16 bits, but requesting a signature kept failing. I changed it to 64 and it succeeded. The other party said that the document was too old and had been forgotten. . Choose according to your needs

Final callback result signature verification

First, take out the contents of the assembled signature field in the callback data and sort according to the getSign() method above.
Then verify:

/**
     * 验证返回的签名是否正确
     *
     * @param string $data 要验证的签名原文
     * @param string $signature 签名内容
      *@param $pubPath  公钥证书位置 (.cer文件)
     *
     * @return bool
     */
    public static function verifyRespondSign($data, $signature,$pubPath)
    {
        $keys = self::loadCert($pubPath);
        $signature = hex2bin($signature);
        $ok = openssl_verify($data, $signature, $keys);
        if ($ok == 1) {
            return true;
        }
        return false;
    }

I hope it will be helpful to you. If there is anything wrong, please point it out, modify it in time, and learn from each other. Related tutorials: PHP video tutorial

The above is the detailed content of Implement SHA1withRSA signature, encryption, and verification using PHP. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete