PHP RSA 加解密 对接Java

近期对接一项目,对方是Java,用到了rsa的加解密以及签名。熬了一天才解决。。。

rsa的加解密需要用到OpenSSL的公钥私钥,在我上一篇的文章又说到,不懂得可以去看。

先上代码,然后再说这次开发中踩的坑::

一、RSA 加解密类

<?php
namespace util;
use Exception;
class RSA
{
    const PKCS1 = 'PKCS#1';
    const PKCS8 = 'PKCS#8';

    private $rsa_public;
    private $rsa_private;
    private $key_format;
    private $padding;

    public function __construct($rsa_public, $rsa_private, $key_format = self::PKCS8, $padding = OPENSSL_PKCS1_PADDING)
    {
        $this->rsa_public = $rsa_public;
        $this->rsa_private = $rsa_private;
        $this->key_format = $key_format;
        $this->padding = $padding;
    }
    public function sign($str)
    {
        openssl_sign($str, $sign,  $this->getPrivateKey());
       return base64_encode($sign);
    }

    // 加密
    public function encrypt($content)
    {
        $crypto = '';
        $pu_key = $this->getPublicKey();
        foreach (str_split($content, 117) as $chunk) {
            openssl_public_encrypt($chunk, $encryptData, $pu_key,$this->padding);
            $crypto .= $encryptData;
        }
        return base64_encode($crypto);
    }

    // 解密
    public function decrypt($content)
    {
        if (!is_string($content)) return null;
                $decrypted = '';
        $chunks = str_split(base64_decode($content), 128);
        foreach ($chunks as $chunk) {
                    $partial = '';
            $decryptIsTrue = openssl_private_decrypt($chunk, $partial, $this->getPrivateKey());
            if ($decryptIsTrue === false) {
                            return null;
            }
            $decrypted .= $partial;
        }
        return $decrypted;
    }

    public function getPublicKey()
    {
        if ($this->key_format == self::PKCS1) {
            $search = [
                "-----BEGIN PUBLIC KEY-----",
                "-----END PUBLIC KEY-----",
                "\n",
                "\r",
                "\r\n"
            ];
            $public_key = str_replace($search, "", $this->rsa_public);
            $public_key = $search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1];
        } else {
            $public_key = $this->rsa_public;
        }
        $key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
        if (!$key) {
            $this->throwError('公钥不可用');
        }
        return $key;
    }
    public function getPrivateKey()
    {
        if ($this->key_format == self::PKCS1) {
            $search = [
                "-----BEGIN PRIVATE KEY-----",
                "-----END PRIVATE KEY-----",
                "\n",
                "\r",
                "\r\n"
            ];
            $private_key = str_replace($search, "", $this->rsa_private);
            $private_key = $search[0] . PHP_EOL . wordwrap($private_key, 64, "\n", true) . PHP_EOL . $search[1];
        } else {
            $private_key = $this->rsa_private;
        }
        $pi_key = openssl_pkey_get_private($private_key);
        if (!$pi_key) {
            $this->throwError('私钥不可用');
        }
        return $pi_key;
    }
    public function throwError($msg)
    {
        throw new Exception($msg);
    }
}

二、调用方法

rsa加解密,普遍的是把自己的公钥给对方,使用彼此的公钥进行加密,然后使用

私钥进行解密的操作。这里只提供加解密以及签名案例

    //我自己的私钥
    private $private_key = '-----BEGIN RSA PRIVATE KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END RSA PRIVATE KEY-----';

    //对方的公钥
    private $public_key = '-----BEGIN PUBLIC KEY-----
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-----END PUBLIC KEY-----';

  
    //定义需要加密的测试数据
   $bizContent=array(
        "supplierCode"=>"202372000142021000064",         
        "type"=>"1",                                                                                  
        "surrenderTime"=>"2021-09-10 15:30:00"                                       
   );
    //TODO 对数据进行签名以及加密
    $bizContent=json_encode($bizContent);
    $utilRsa = new RSA($this->public_key , '');
    $bizContent_k = $utilRsa->encrypt($bizContent);

    //需要进行签名的数据串
    $sign='appKey=123123&bizContent='.$bizContent_k.'&charset=UTF-8&format=JSON&serviceName=serviceName&signType=RSA&timestamp=111111&version=1.0.0';

    //对sign进行私钥加密
    $sign_k= (new RSA('',$this->private_key))->sign($sign);
   
    //数据解密
    $res_bizContent = '需要解密的密文';
    $res = (new RSA('',$this->private_key))->decrypt($res_bizContent);
    $bizContent = json_decode($res,true);


三、注意细节

1、加密用的是对方的公钥,解密使用自己的私钥。

2、加解密的时候,会受到密文长度的限制报错,这时需要将密文分段加解密然后把结果在拼接起来

3、PHP的rsa加解密方法和Java还是有区别的,需要进行详细的沟通,了解具体的加密方法才可以匹配成功

4、第三方提供的java rsa秘钥(pkcs8格式),PHP不能直接使用;只能将rsa秘钥转成pkcs1格式,然后再按照PHP rsa秘钥格式处理。上面的加解密类有类似的方法


                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值