PHP Conference Japan 2024

openssl_public_decrypt

(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)

openssl_public_decrypt使用公钥解密数据

描述

openssl_public_decrypt(
    字符串 $data,
    #[\SensitiveParameter] 字符串 &$decrypted_data,
    OpenSSLAsymmetricKey|OpenSSLCertificate|数组|字符串 $public_key,
    整数 $padding = OPENSSL_PKCS1_PADDING
): 布尔值

openssl_public_decrypt() 使用 public_key 解密之前通过 openssl_private_encrypt() 加密的 data,并将结果存储到 decrypted_data 中。

例如,您可以使用此函数来检查消息是否由私钥所有者编写。

参数

data

decrypted_data

public_key

public_key 必须与用于加密数据的私钥相对应的公钥。

padding

padding 可以是 OPENSSL_PKCS1_PADDINGOPENSSL_NO_PADDING

返回值

成功时返回 true,失败时返回 false

变更日志

版本 描述
8.0.0 public_key 现在接受 OpenSSLAsymmetricKeyOpenSSLCertificate 实例;之前,接受类型为 OpenSSL keyOpenSSL X.509资源

参见

添加注释

用户贡献的注释 1 条注释

Hernanibus
8 年前
关于手册中 openssl_private_encrypt 的 [P.Peyremorte] 的注释的一点补充。

“- openssl_private_encrypt 每次最多可以加密 117 个字符。”

这取决于 $key 的长度

- 对于 1024 位密钥长度 => 最多可加密的字符(字节)数 = 1024/8 - 11(使用填充时)= 117 个字符(字节)。
- 对于 2048 位密钥长度 => 最多可加密的字符(字节)数 = 2048/8 - 11(使用填充时)= 245 个字符(字节)。
... 等等

顺便说一句,如果 openssl_private_encrypt 由于数据大小而失败,您将一无所获,只会返回 false,openssl_public_decrypt() 在解密时也是如此。

“- 加密后的输出字符串始终为 129 个字符长度。如果您对加密后的输出使用 base64_encode,它将始终给出 172 个字符,最后一个始终为“=”(填充)”

这再次取决于 $key 的长度

- 对于 1024 位密钥长度 => 加密后的原始字节数始终是 RSA 设计的 128 字节(1024 位)块。
- 对于 2048 位密钥长度 => 加密后的原始字节数始终是 RSA 设计的 256 字节(2048 位)块。
... 等等

关于 base64_encode 输出长度,它取决于您编码的内容(意味着它取决于加密后产生的字节),但通常生成的编码字符串大约会大 33%(对于 128 字节大约为 170 字节,对于 256 字节大约为 340 字节)。

然后,我将通过以下方式稍微概括一下 [P.Peyremorte] 的注释
<?php
// 将变量作为常量给出:

// 加密块密码的块大小
private $ENCRYPT_BLOCK_SIZE = 200;// 例如,对于 2048 位密钥,留出一些空间

// 解密块密码的块大小
private $DECRYPT_BLOCK_SIZE = 256;// 再次用于 2048 位密钥

// 对于加密,我们将使用:
function encrypt_RSA($plainData, $privatePEMKey)
{
$encrypted = '';
$plainData = str_split($plainData, $this->ENCRYPT_BLOCK_SIZE);
foreach(
$plainData as $chunk)
{
$partialEncrypted = '';

// 例如,使用 OPENSSL_PKCS1_PADDING 作为填充
$encryptionOk = openssl_private_encrypt($chunk, $partialEncrypted, $privatePEMKey, OPENSSL_PKCS1_PADDING);

if(
$encryptionOk === false){return false;}// 也可以返回错误。如果太大,这将为 false
$encrypted .= $partialEncrypted;
}
return
base64_encode($encrypted);// 将整个二进制字符串编码为 MIME base 64
}

// 对于解密,我们将使用:
protected function decrypt_RSA($publicPEMKey, $data)
{
$decrypted = '';

// 解码必须在拆分之前完成,以获取二进制字符串
$data = str_split(base64_decode($data), $this->DECRYPT_BLOCK_SIZE);

foreach(
$data as $chunk)
{
$partial = '';

// 确保匹配填充
$decryptionOK = openssl_public_decrypt($chunk, $partial, $publicPEMKey, OPENSSL_PKCS1_PADDING);

if(
$decryptionOK === false){return false;}// 在此处也处理解密中的错误。如果太大,这将为 false
$decrypted .= $partial;
}
return
$decrypted;
}
?>
To Top