1,php中RSA实现(公钥加密私钥解密)

/**
* 公钥加密数据.
* @param string $decrypted 数据明文
* @return null|string null加密失败
*/
public function encryptTxtContent(string $decrypted): ?string
{
    $pubKey = openssl_get_publicKey($this->getPubKeyPem($this->txtPubKey));
    return openssl_public_encrypt($decrypted, $encrypted, $pubKey) ? base64_encode($encrypted) : null;
}

/**
* 私钥解密
* @param string $encrypted 数据密文
* @return mixed
*/
public function decryptTxtContent(string $encrypted): ?string
{
    $privateKey = openssl_get_privatekey($this->getPriKeyPem($this->txtPriKey));
    return openssl_private_decrypt(base64_decode($encrypted), $decrypted, $privateKey) ? $decrypted : null;
}

在开发过程中,我就用了上边的加解密方式,但是在实践过程中由于加密字符串过长导致加密失败;获取一下错误信息:error:0909006C:PEM routines:get_name:no start line;搜索了一下官方也有对应的解决方案,
https://www.php.net/manual/zh/function.openssl-public-encrypt.php#56449 。

加密出现错误的原因:

RSA对明文长度和密文长度有限制,如果要加密的明文太长则会出错。RSA 1024bit 加密明文最大长度117字节,解密要求密文最大长度为128字节,所以在加密和解密的过程中需要分块进行。

注意事项:

RSA不同的密钥长度,在分段加、解密时,分段字节数是不同的,若RSA密钥长度为M bit,分段加密字节数为(M/8-11),分段解密字节数为(M/8)。
如:
1024bit:分段加密字节数为117,分段解密字节数为128。
2048bit:分段加密字节数为245,分段解密字节数为256。

我用的是2048bit加密明文的所有代码如下:

/**
* 公钥加密数据.
* @param string $decrypted 数据明文
* @return null|string null加密失败
*/
public function encryptTxtContent(string $decrypted): ?string
{
		$publicKey = openssl_get_publicKey($pubKey);
    $crypted = array_reduce(str_split($decrypted, 245), function ($carry, $item) use ($publicKey) {
        $subCrypted = null;
        openssl_public_encrypt($item, $subCrypted, $publicKey);
        $subCrypted && $carry .= $subCrypted;
        return $carry;
    }, '');
    if (empty($crypted)) {
    		return '';
    }
    return base64_encode($crypted);
}

/**
* 私钥解密
* @param string $encrypted 数据密文
* @return mixed
*/
public function decryptTxtContent(string $encrypted): ?array
{
    $privateKey = openssl_get_privatekey($this->getPriKeyPem($this->txtPriKey));
    $dataArr   = str_split(base64_decode($encrypted), 256);
    $decrypted = array_reduce($dataArr, function ($carry, $item) use ($privateKey) {
        $subDecrypted = null;
        openssl_private_decrypt($item, $subDecrypted, $privateKey);
        $subDecrypted && $carry .= $subDecrypted;
        return $carry;
    }, '');
    if (! $decrypted) {
    		return [];
    }
    return json_decode($decrypted, true, 512, JSON_THROW_ON_ERROR);
}