wpbridge/includes/Security/Encryption.php
feibisi fe4095db80 fix: 修复 Codex 代码评审发现的问题
HIGH 级别修复:
- AdminPage.php: 移除重复的 Logger 导入
- AdminPage.php: 修复 auth_token 双重加密问题
- AdminPage.php: 添加 action 参数白名单验证
- CacheManager.php: get_stats() 使用 $wpdb->prepare()
- source-editor.php: 不显示加密后的 token,使用占位符
- Validator.php: DNS 解析失败时视为本地地址(SSRF 防护)

MEDIUM 级别修复:
- BridgeCommand.php: 使用 WordPress 文件系统 API
- SourceModel.php: 改进 auth_token 解密回退逻辑
- SourceModel.php: 添加 URL 协议验证 (http/https)
- Encryption.php: 使用随机生成的密钥替代站点 URL 哈希

LOW 级别修复:
- BackgroundUpdater.php: 移除 PHP 8.0 联合类型语法
- Plugin.php: 使用 wp_cache_flush_group() 如果可用
- Validator.php: 添加 IPv6 私有地址检查
- uninstall.php: 清理 wpbridge_encryption_key 选项

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 19:59:13 +08:00

212 lines
5.1 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* 密钥加密
*
* @package WPBridge
*/
namespace WPBridge\Security;
// 防止直接访问
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* 密钥加密类
*/
class Encryption {
/**
* 加密方法
*
* @var string
*/
const METHOD = 'aes-256-cbc';
/**
* 获取加密密钥
*
* @return string
*/
private static function get_key(): string {
// 优先使用自定义密钥
if ( defined( 'WPBRIDGE_ENCRYPTION_KEY' ) && WPBRIDGE_ENCRYPTION_KEY ) {
return WPBRIDGE_ENCRYPTION_KEY;
}
// 使用 WordPress 的 AUTH_KEY
if ( defined( 'AUTH_KEY' ) && AUTH_KEY ) {
return AUTH_KEY;
}
// 最后使用 SECURE_AUTH_KEY
if ( defined( 'SECURE_AUTH_KEY' ) && SECURE_AUTH_KEY ) {
return SECURE_AUTH_KEY;
}
// 如果都没有,生成并存储一个随机密钥
$key = get_option( 'wpbridge_encryption_key' );
if ( empty( $key ) ) {
$key = bin2hex( random_bytes( 32 ) );
update_option( 'wpbridge_encryption_key', $key, false );
}
return $key;
}
/**
* 加密数据
*
* @param string $data 明文数据
* @return string 加密后的数据base64 编码)
*/
public static function encrypt( string $data ): string {
if ( empty( $data ) ) {
return '';
}
$key = hash( 'sha256', self::get_key(), true );
$iv = openssl_random_pseudo_bytes( openssl_cipher_iv_length( self::METHOD ) );
$encrypted = openssl_encrypt( $data, self::METHOD, $key, OPENSSL_RAW_DATA, $iv );
if ( false === $encrypted ) {
return '';
}
// 将 IV 和加密数据一起存储
return base64_encode( $iv . $encrypted );
}
/**
* 解密数据
*
* @param string $data 加密数据base64 编码)
* @return string 解密后的明文
*/
public static function decrypt( string $data ): string {
if ( empty( $data ) ) {
return '';
}
$data = base64_decode( $data );
if ( false === $data ) {
return '';
}
$key = hash( 'sha256', self::get_key(), true );
$iv_length = openssl_cipher_iv_length( self::METHOD );
if ( strlen( $data ) < $iv_length ) {
return '';
}
$iv = substr( $data, 0, $iv_length );
$encrypted = substr( $data, $iv_length );
$decrypted = openssl_decrypt( $encrypted, self::METHOD, $key, OPENSSL_RAW_DATA, $iv );
if ( false === $decrypted ) {
return '';
}
return $decrypted;
}
/**
* 检查数据是否已加密
*
* @param string $data 数据
* @return bool
*/
public static function is_encrypted( string $data ): bool {
if ( empty( $data ) ) {
return false;
}
// 检查是否是有效的 base64
$decoded = base64_decode( $data, true );
if ( false === $decoded ) {
return false;
}
// 检查长度是否足够包含 IV
$iv_length = openssl_cipher_iv_length( self::METHOD );
return strlen( $decoded ) > $iv_length;
}
/**
* 安全地存储敏感数据
*
* @param string $key 选项键
* @param string $value 敏感值
* @return bool
*/
public static function store_secure( string $key, string $value ): bool {
$encrypted = self::encrypt( $value );
return update_option( 'wpbridge_secure_' . $key, $encrypted );
}
/**
* 安全地获取敏感数据
*
* @param string $key 选项键
* @param string $default 默认值
* @return string
*/
public static function get_secure( string $key, string $default = '' ): string {
$encrypted = get_option( 'wpbridge_secure_' . $key, '' );
if ( empty( $encrypted ) ) {
return $default;
}
$decrypted = self::decrypt( $encrypted );
return ! empty( $decrypted ) ? $decrypted : $default;
}
/**
* 删除安全存储的数据
*
* @param string $key 选项键
* @return bool
*/
public static function delete_secure( string $key ): bool {
return delete_option( 'wpbridge_secure_' . $key );
}
/**
* 生成随机令牌
*
* @param int $length 长度
* @return string
*/
public static function generate_token( int $length = 32 ): string {
return bin2hex( random_bytes( $length / 2 ) );
}
/**
* 哈希密码/令牌(用于比较)
*
* @param string $data 数据
* @return string
*/
public static function hash( string $data ): string {
return hash( 'sha256', $data . self::get_key() );
}
/**
* 验证哈希
*
* @param string $data 原始数据
* @param string $hash 哈希值
* @return bool
*/
public static function verify_hash( string $data, string $hash ): bool {
return hash_equals( self::hash( $data ), $hash );
}
}