diff --git a/functions.php b/functions.php index 4802dd85..905d8ecc 100644 --- a/functions.php +++ b/functions.php @@ -2305,19 +2305,17 @@ function change_avatar($avatar) preg_match('/:\"([^\"]*)\"/i', $qqavatar, $matches); return '😀'; } - + // Ensure $sakura_privkey is defined and not null if (isset($sakura_privkey) && !is_null($sakura_privkey)) { - // 生成一个合适长度的初始化向量 - $iv_length = openssl_cipher_iv_length('aes-128-cbc'); - $iv = openssl_random_pseudo_bytes($iv_length); - + $iv = substr(md5($sakura_privkey), 0, 16); + // 加密数据 $encrypted = openssl_encrypt($qq_number, 'aes-128-cbc', $sakura_privkey, 0, $iv); - + // 将初始化向量和加密数据一起编码 $encrypted = urlencode(base64_encode($iv . $encrypted)); - + return '😀'; } else { // Handle the case where $sakura_privkey is not set or is null @@ -2326,7 +2324,6 @@ function change_avatar($avatar) } return $avatar; } - //生成随机链接,防止浏览器缓存策略 function get_random_url(string $url): string { @@ -4212,3 +4209,20 @@ function iro_action_operator() } } iro_action_operator(); + + +/* * 检查并生成加密密钥 + * 如果不存在,则生成一个新的256位密钥并存储在选项中 + */ +// 检查密钥是否存在,如果不存在则生成并存储 +if (!get_option('sakura_encryption_key')) { + // 生成一个安全的 128-bit (16字节) 密钥,适用于 AES-128-CBC + $new_key = bin2hex(random_bytes(16)); // 或者使用 openssl_random_pseudo_bytes(16) + update_option('sakura_encryption_key', $new_key, false); // 'false' 表示不自动加载 +} + +// 在 init 钩子中设置全局变量 +add_action('init', function() { + global $sakura_privkey; + $sakura_privkey = get_option('sakura_encryption_key'); +}); diff --git a/inc/classes/QQ.php b/inc/classes/QQ.php index 6f235f39..aaa11f1a 100644 --- a/inc/classes/QQ.php +++ b/inc/classes/QQ.php @@ -5,7 +5,21 @@ class QQ { public static function get_qq_info($qq) { - $get_info = file_get_contents('https://api.qjqq.cn/api/qqinfo?qq=' . $qq); + // Validate QQ number: must be 3 or more digits + if (!preg_match('/^\d{3,}$/', $qq)) { + return array( + 'status' => 400, + 'success' => false, + 'message' => 'Invalid QQ number.' + ); + } + $api_key = iro_opt('qq_avatar_api_key'); + $query = http_build_query([ + 'key' => $api_key, + 'qq' => $qq + ]); + $url = 'https://api.nsmao.net/api/qq/v1/query?' . $query; + $get_info = file_get_contents($url); $name = json_decode($get_info, true); if ($name) { if ($name['code'] == 200){ @@ -13,8 +27,8 @@ public static function get_qq_info($qq) { 'status' => 200, 'success' => true, 'message' => 'success', - 'avatar' => 'https://q2.qlogo.cn/headimg_dl?dst_uin=' . $qq . '&spec=100', - 'name' => $name['name'], + 'avatar' => $name['data']['avatar'], + 'name' => $name['data']['name'], ); } } else { @@ -30,9 +44,11 @@ public static function get_qq_info($qq) { public static function get_qq_avatar($encrypted) { global $sakura_privkey; if (isset($encrypted)) { - $iv = str_repeat($sakura_privkey, 2); - $encrypted = base64_decode(urldecode($encrypted)); - $qq_number = openssl_decrypt($encrypted, 'aes-128-cbc', $sakura_privkey, 0, $iv); + $decoded = base64_decode(urldecode($encrypted)); + $iv = substr($decoded, 0, 16); // 提取前16字节作为IV + $data = substr($decoded, 16); // 剩余是加密数据 + $qq_number = openssl_decrypt($data, 'aes-128-cbc', $sakura_privkey, 0, $iv); + preg_match('/^\d{3,}$/', $qq_number, $matches); return 'https://q2.qlogo.cn/headimg_dl?dst_uin=' . $matches[0] . '&spec=100'; } diff --git a/opt/options/theme-options.php b/opt/options/theme-options.php index 007062fd..c8203e3a 100644 --- a/opt/options/theme-options.php +++ b/opt/options/theme-options.php @@ -3158,6 +3158,14 @@ function iro_validate_optional_url( $value ) { 'default' => true ), + array( + 'id' => 'qq_avatar_api_key', + 'type' => 'text', + 'title' => __('QQ Avatar API Key','sakurairo_csf'), + 'desc' => __('Enter your API key for QQ avatar service, get your API key at: https://api.nsmao.net','sakurairo_csf'), + 'default' => '' + ), + array( 'id' => 'qq_avatar_link', 'type' => 'select',