首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP Blowfish 加密解密實戰:CBC 模式 + PKCS5 填充完整封裝類

     編輯:PHP 相關知識

PHP Blowfish 加密解密實戰:CBC 模式 + PKCS5 填充完整封裝類

Blowfish 是對稱分組加密演算法,區塊大小 64 位,密鑰長度 32-448 位。PHP 早期通過 mcrypt 擴展支援,PHP 7.1 棄用、7.2 移除,現代專案建議改用 openssl 或 sodium。本文保留 mcrypt 版本供維舊專案參考,並提供 OpenSSL 現代替代方案對照。

一、mcrypt 版封裝類(PHP ≤ 7.1)

<?php
class BlowfishCBC
{
    private $key;
    private $iv;

    public function __construct(string $key, string $iv = '')
    {
        $this->key = $key;
        $this->iv  = $iv ?: substr(hash('sha256', $key, true), 0, 8); // 8 字節 IV
    }

    /** PKCS#5 填充 */
    private function pad(string $data, int $block): string
    {
        $pad = $block - (strlen($data) % $block);
        return $data . str_repeat(chr($pad), $pad);
    }

    /** PKCS#5 去填充 */
    private function unpad(string $data): string
    {
        $pad = ord($data[strlen($data) - 1]);
        return substr($data, 0, -$pad);
    }

    /** 加密 → Base64 */
    public function encrypt(string $plain): string
    {
        $td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '');
        $block = mcrypt_get_block_size(MCRYPT_BLOWFISH, MCRYPT_MODE_CBC);
        $padded = $this->pad($plain, $block);

        mcrypt_generic_init($td, $this->key, $this->iv);
        $cipher = mcrypt_generic($td, $padded);
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);

        return base64_encode($cipher);
    }

    /** Base64 → 解密 */
    public function decrypt(string $cipherB64): string
    {
        $td = mcrypt_module_open(MCRYPT_BLOWFISH, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($td, $this->key, $this->iv);
        $decrypted = mdecrypt_generic($td, base64_decode($cipherB64));
        mcrypt_generic_deinit($td);
        mcrypt_module_close($td);

        return $this->unpad($decrypted);
    }
}

// 使用範例
$bf = new BlowfishCBC('my-32-byte-secret-key-1234567890');
$encrypted = $bf->encrypt('敏感資料');
$decrypted = $bf->decrypt($encrypted);
?>

二、OpenSSL 現代替代方案(PHP 7.1+ 推薦)

openssl_encrypt 原生支援 BF-CBC,無需額外擴展:

<?php
function bfEncrypt(string $data, string $key, string $iv = ''): string
{
    $iv = $iv ?: random_bytes(8); // Blowfish IV 必須 8 字節
    $ct = openssl_encrypt($data, 'BF-CBC', $key, OPENSSL_RAW_DATA, $iv);
    return base64_encode($iv . $ct); // IV 前置存儲
}

function bfDecrypt(string $payload, string $key): string
{
    $raw = base64_decode($payload);
    $iv = substr($raw, 0, 8);
    $ct = substr($raw, 8);
    return openssl_decrypt($ct, 'BF-CBC', $key, OPENSSL_RAW_DATA, $iv);
}

// 測試
$key = 'my-32-byte-secret-key-1234567890';
$enc = bfEncrypt('Hello Blowfish!', $key);
echo $enc . "\n";
echo bfDecrypt($enc, $key); // Hello Blowfish!
?>

三、關鍵參數說明

  • Key 長度: 16-56 字節(128-448 位),建議 32 字節(256 位)
  • IV 長度: 固定 8 字節(64 位),每次加密應使用隨機 IV
  • 模式: CBC 需 IV,ECB 不需 IV 但不安全,禁用
  • 填充: PKCS#5/PKCS#7 等效(區塊 8 字節時),OpenSSL 預設自動處理

四、安全性建議

  1. 棄用 mcrypt,全面遷移至 OpenSSL 或 Sodium(sodium_crypto_aead_*)
  2. 密鑰管理:使用環境變數或 Vault,勿硬編碼
  3. 認證加密:Blowfish-CBC 無完整性保護,建議改用 AES-256-GCM(openssl_encrypt(..., 'aes-256-gcm'))或 Sodium crypto_aead_xchacha20poly1305_ietf
  4. 舊資料遷移:雙寫期同時支援新舊格式,驗證後逐步清理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved