如何在CodeIgniter3项目中集成并使用Sodium AES 256加密
我刚好在几个月前给一个运行中的CodeIgniter 3项目集成过Sodium AES-256加密,踩过一些坑,分享一下亲测有效的完整流程,应该能帮到你:
前置检查
首先确认你的PHP 7.4环境已经启用Sodium扩展:
- 运行
php -m | grep sodium,如果输出sodium则说明已启用; - 或者在CI项目中新建一个测试控制器,调用
var_dump(extension_loaded('sodium')),返回true即可。
如果未启用,在php.ini中添加对应配置: - Linux:
extension=sodium.so - Windows:
extension=sodium
创建Sodium加密库
在CI3的application/libraries/目录下新建Sodium_encryption.php,这是我们封装的加密工具类,专门实现AES-256-GCM加密(Sodium官方推荐的AES-256实现方式):
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Sodium_encryption { private $key; public function __construct() { $this->CI =& get_instance(); // 从配置中读取密钥(建议通过环境变量存储) $this->key = $this->CI->config->item('sodium_encryption_key'); // 前置验证 if (!$this->key || !sodium_crypto_aead_aes256gcm_is_available()) { show_error('Sodium AES-256-GCM 不可用或密钥未配置'); } if (strlen($this->key) !== SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES) { show_error('Sodium 密钥必须为32字节长度'); } } /** * 加密明文内容 * @param string $plaintext 要加密的内容 * @return string base64编码后的加密串(包含随机nonce+密文+验证标签) */ public function encrypt($plaintext) { // 生成12字节的随机nonce(每个加密请求必须唯一) $nonce = sodium_randombytes_buf(SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES); // 执行加密 $ciphertext = sodium_crypto_aead_aes256gcm_encrypt( $plaintext, '', // 可选附加数据,加密解密需保持一致 $nonce, $this->key ); // 拼接nonce和密文后base64编码,方便存储/传输 $encrypted = base64_encode($nonce . $ciphertext); // 清理内存中的敏感数据 sodium_memzero($plaintext); sodium_memzero($nonce); return $encrypted; } /** * 解密加密串 * @param string $encrypted base64编码的加密串 * @return string|false 解密后的明文,验证失败返回false */ public function decrypt($encrypted) { $decoded = base64_decode($encrypted); if (!$decoded) return false; // 拆分nonce(前12字节)和密文 $nonce = substr($decoded, 0, SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES); $ciphertext = substr($decoded, SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES); // 执行解密并验证 $plaintext = sodium_crypto_aead_aes256gcm_decrypt( $ciphertext, '', // 需和加密时的附加数据一致 $nonce, $this->key ); // 清理敏感数据 sodium_memzero($ciphertext); sodium_memzero($nonce); return $plaintext; } /** * 生成符合要求的密钥(仅用于初始化,生成后务必保存到环境变量) * @return string 32字节的随机密钥 */ public static function generate_key() { return sodium_crypto_aead_aes256gcm_keygen(); } }
配置密钥
- 生成密钥:在命令行执行以下命令,得到一个32字节的密钥字符串:
php -r "echo sodium_crypto_aead_aes256gcm_keygen().PHP_EOL;"
- 将密钥存储到服务器环境变量中(不要硬编码到代码里,避免泄露);
- 在CI3的
application/config/config.php中添加配置项:
$config['sodium_encryption_key'] = getenv('SODIUM_ENCRYPTION_KEY');
在CI3中使用
你可以选择全局自动加载,或者在需要的控制器中手动加载:
- 全局自动加载:在
application/config/autoload.php中,把sodium_encryption添加到$autoload['libraries']数组; - 手动加载:在控制器中调用:
$this->load->library('sodium_encryption');
使用示例:
// 加密示例 $original_content = '用户敏感数据,比如手机号、身份证号'; $encrypted_content = $this->sodium_encryption->encrypt($original_content); // 解密示例 $decrypted_content = $this->sodium_encryption->decrypt($encrypted_content); if ($decrypted_content === false) { // 处理解密失败(比如内容被篡改) show_error('内容验证失败,可能已被篡改'); }
注意事项
- 密钥绝对不能提交到版本控制,必须通过环境变量管理;
- 同一个明文每次加密结果都不一样(因为nonce随机),这是正常且安全的;
- 如果解密返回
false,说明加密串被篡改或密钥不正确,需要做异常处理; - 用完敏感数据后,一定要用
sodium_memzero()清理内存,防止内存泄露。
内容的提问来源于stack exchange,提问作者Nazeer Shaik
相关产品推荐
相关产品推荐

