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

PHP 自訂雙向加密解密類別:基於字元替換表的簡易實作

     編輯:PHP 相關知識

設計概念

本類別展示一種基於「密鑰字元位移替換表」的對稱加密演算法。特點:

  • 雙向:同一組函數可加密也可解密
  • 無需外部擴展,純 PHP 實作
  • 可手工運算(紙筆即可),適合教學理解加密原理
  • 不適用於生產環境敏感資料(缺乏完整性驗證、抗暴力破解能力弱)

核心演算法邏輯

  1. 建立基礎字元表 $ralphabet(含大小寫字母、數字、符號)
  2. 將字元表複製一份拼接成 $alphabet,方便循環位移
  3. 密鑰每個字元在 $alphabet 中對應一個位移後的替換表
  4. 加密:明文字元在 $ralphabet 位置 → 對應密鑰位移表的字元
  5. 解密:密文字元在密鑰位移表位置 → 對應 $ralphabet 原字元

完整類別程式碼

<?php
$ralphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !,.:;?~@#$%^&*()_+-=][}{/><\'"';
$alphabet = $ralphabet . $ralphabet;

class Crypto {
    public function encrypt(string $password, string $plaintext): string {
        $tables = $this->buildTables($password);
        $plen = strlen($plaintext);
        $klen = count($tables);
        $cipher = '';
        
        for ($i = 0, $k = 0; $i < $plen; $i++, $k = ($k + 1) % $klen) {
            $pos = strpos($ralphabet, $plaintext[$i]);
            if ($pos !== false) {
                $cipher .= $tables[$k][$pos];
            } else {
                // 不在字元表內的字元保留原樣(或拋出異常)
                $cipher .= $plaintext[$i];
            }
        }
        return $cipher;
    }

    public function decrypt(string $password, string $ciphertext): string {
        $tables = $this->buildTables($password);
        $clen = strlen($ciphertext);
        $klen = count($tables);
        $plain = '';
        
        for ($i = 0, $k = 0; $i < $clen; $i++, $k = ($k + 1) % $klen) {
            $pos = strpos($tables[$k], $ciphertext[$i]);
            if ($pos !== false) {
                $plain .= $ralphabet[$pos];
            } else {
                $plain .= $ciphertext[$i];
            }
        }
        return $plain;
    }

    // 產生密鑰對應的位移替換表陣列
    private function buildTables(string $password): array {
        $tables = [];
        $rlen = strlen($ralphabet);
        for ($i = 0; $i < strlen($password); $i++) {
            $ch = $password[$i];
            $pos = strpos($alphabet, $ch);
            if ($pos !== false) {
                $tables[] = substr($alphabet, $pos, $rlen);
            }
        }
        return $tables ?: [$ralphabet]; // 至少有一個表
    }

    // 除錯用:輸出替換表 HTML 表格
    public function printTable(string $password): void {
        $tables = $this->buildTables($password);
        echo '<table border="1" cellpadding="3" cellspacing="0">';
        echo '<tr><th>Pos</th>';
        for ($j = 0; $j < strlen($ralphabet); $j++) {
            echo '<th>' . htmlspecialchars($ralphabet[$j]) . '</th>';
        }
        echo '</tr>';
        foreach ($tables as $idx => $table) {
            echo '<tr><td>' . ($idx + 1) . '</td>';
            for ($j = 0; $j < strlen($table); $j++) {
                echo '<td>' . htmlspecialchars($table[$j]) . '</td>';
            }
            echo '</tr>';
        }
        echo '</table>';
    }
}

// 簡易測試表單
$crypto = new Crypto();
$mode = $_POST['mode'] ?? 'encrypt';
$password = $_POST['password'] ?? 'secret';
$input = $_POST['input'] ?? '';

if ($mode === 'encrypt') {
    $output = $crypto->encrypt($password, $input);
    $action = 'decrypt';
    $btn = '解密';
} else {
    $output = $crypto->decrypt($password, $input);
    $action = 'encrypt';
    $btn = '加密';
}
?>
<!DOCTYPE html>
<html lang="zh-TW">
<head><meta charset="UTF-8"><title>Crypto Demo</title></head>
<body>
  <h2>自訂加密/解密示範</h2>
  <form method="post">
    <input type="hidden" name="mode" value="<?= $action ?>">
    <label>密鑰: <input type="text" name="password" value="<?= htmlspecialchars($password) ?>" size="20"></label><br><br>
    <label><?= $mode === 'encrypt' ? '明文' : '密文' ?>:<br>
    <textarea name="input" rows="5" cols="60"><?= htmlspecialchars($input) ?></textarea></label><br>
    <button type="submit"><?= $btn ?></button>
  </form>
  <hr>
  <label>結果:<br>
  <textarea rows="5" cols="60" readonly><?= htmlspecialchars($output) ?></textarea></label>
  <hr>
  <h3>替換表</h3>
  <?php $crypto->printTable($password); ?>
</body>
</html>

安全性警示與改進方向

生產環境建議

<?php
// 使用 PHP 內建 sodium 擴展 (PHP 7.2+)
// 加密
$key = sodium_crypto_secretbox_keygen(); // 安全儲存金鑰
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$cipher = sodium_crypto_secretbox($plaintext, $nonce, $key);
// 儲存: base64_encode($nonce . $cipher)

// 解密
$combined = base64_decode($stored);
$nonce = substr($combined, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$cipher = substr($combined, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
$plaintext = sodium_crypto_secretbox_open($cipher, $nonce, $key);

或使用 defuse/php-encryption、paragonie/halite 等經驗證庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題影響改進建議
無完整性驗證 (MAC)密文被竄改後解密不會報錯加密後附加 HMAC-SHA256,解密前驗證
金鑰衍生弱直接使用密碼字元,熵值低使用 PBKDF2 / Argon2 衍生金鑰
ECB 模式特性相同明文區塊產生相同密文,洩漏模式引入 IV (Initialization Vector) 改為 CBC/GCM 模式
字元表固定已知明文攻擊容易破解使用標準加密庫 (OpenSSL、libsodium)