Skip to content

OpenSSL 扩展

PHP 的 OpenSSL 扩展提供了丰富的加密功能,包括对称加密、非对称加密、数字签名、证书管理和哈希计算。它是 PHP 安全编程的核心扩展,广泛用于 HTTPS、JWT、数据加密等场景。

前置知识

阅读本节前,建议先了解:PHP 类型系统密码散列算法

对称加密

AES 加密解密

php
<?php
declare(strict_types=1);

class AesEncryptor
{
    public function __construct(
        private readonly string $key,
        private readonly string $cipher = 'aes-256-cbc'
    ) {
        $keyLength = strlen($this->key);
        $requiredLength = $this->getKeyLength();

        if ($keyLength < $requiredLength) {
            throw new \InvalidArgumentException(
                "密钥长度不足,{$this->cipher} 需要 {$requiredLength} 字节"
            );
        }
    }

    private function getKeyLength(): int
    {
        return match ($this->cipher) {
            'aes-128-cbc', 'aes-128-cfb' => 16,
            'aes-192-cbc', 'aes-192-cfb' => 24,
            'aes-256-cbc', 'aes-256-cfb' => 32,
            default => 32,
        };
    }

    public function encrypt(string $data): string
    {
        $ivLength = openssl_cipher_iv_length($this->cipher);
        $iv = random_bytes($ivLength);

        $encrypted = openssl_encrypt(
            $data,
            $this->cipher,
            $this->key,
            OPENSSL_RAW_DATA,
            $iv
        );

        if ($encrypted === false) {
            throw new \RuntimeException("加密失败: " . openssl_error_string());
        }

        // 将 IV 附加到密文前面
        return base64_encode($iv . $encrypted);
    }

    public function decrypt(string $data): string
    {
        $data = base64_decode($data);
        $ivLength = openssl_cipher_iv_length($this->cipher);
        $iv = substr($data, 0, $ivLength);
        $encrypted = substr($data, $ivLength);

        $decrypted = openssl_decrypt(
            $encrypted,
            $this->cipher,
            $this->key,
            OPENSSL_RAW_DATA,
            $iv
        );

        if ($decrypted === false) {
            throw new \RuntimeException("解密失败: " . openssl_error_string());
        }

        return $decrypted;
    }
}

$enc = new AesEncryptor('0123456789abcdef0123456789abcdef', 'aes-256-cbc');
$encrypted = $enc->encrypt('Hello World, 你好世界!');
$decrypted = $enc->decrypt($encrypted);
echo "解密结果: {$decrypted}" . PHP_EOL;

非对称加密

RSA 加密解密

php
<?php
declare(strict_types=1);

// 生成 RSA 密钥对
$config = [
    "digest_alg" => "sha256",
    "private_key_bits" => 4096,
    "private_key_type" => OPENSSL_KEYTYPE_RSA,
];
$keyPair = openssl_pkey_new($config);

// 导出私钥
openssl_pkey_export($keyPair, $privateKey);

// 导出公钥
$publicKey = openssl_pkey_get_details($keyPair)['key'];

// 公钥加密
openssl_public_encrypt('Hello World', $encrypted, $publicKey);

// 私钥解密
openssl_private_decrypt($encrypted, $decrypted, $privateKey);
echo "RSA 解密: {$decrypted}" . PHP_EOL;

数字签名

php
<?php
declare(strict_types=1);

$data = '重要数据内容';

// 私钥签名
openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256);

// 公钥验证
$valid = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
echo "签名验证: " . ($valid === 1 ? '有效' : '无效') . PHP_EOL;

哈希计算

php
<?php
declare(strict_types=1);

// 常用哈希
echo "MD5: " . md5('hello') . PHP_EOL;
echo "SHA1: " . sha1('hello') . PHP_EOL;

// OpenSSL hash
echo "SHA256: " . hash('sha256', 'hello') . PHP_EOL;
echo "SHA512: " . hash('sha512', 'hello') . PHP_EOL;

// HMAC
echo "HMAC-SHA256: " . hash_hmac('sha256', 'hello', 'secret_key') . PHP_EOL;

// 使用 openssl_digest
$hash = openssl_digest('hello', 'sha256');
echo "openssl SHA256: {$hash}" . PHP_EOL;

证书操作

php
<?php
declare(strict_types=1);

// 读取证书
$cert = file_get_contents('/path/to/cert.pem');
$parsed = openssl_x509_parse($cert);
echo "颁发者: {$parsed['issuer']['CN']}" . PHP_EOL;
echo "有效期: {$parsed['validFrom']} - {$parsed['validTo']}" . PHP_EOL;

注意事项

  • 使用 AES-256-GCM 替代 CBC(PHP 7.1+)获得更好的安全性
  • RSA 密钥至少使用 2048 位,推荐 4096 位
  • 不要使用 md5/sha1 进行密码存储(使用 password_hash)
  • 使用 OPENSSL_RAW_DATA 选项避免 Base64 自动编码

下一节

继续学习:Hash 扩展

参考链接