Files
claude-relay-service/scripts/debug-gemini-decrypt.js
shaw 8f0da8e914 fix: 修复 Gemini 解密调试脚本的密钥生成逻辑
- 使用 config.security.encryptionKey 而不是直接读取环境变量
- 添加 crypto.scryptSync 和 ENCRYPTION_SALT 以匹配实际加密逻辑
- 显示实际使用的加密配置信息

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-26 12:18:57 +08:00

146 lines
5.0 KiB
JavaScript
Raw 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.

#!/usr/bin/env node
/**
* 调试 Gemini refreshToken 解密问题
*/
const path = require('path');
const dotenv = require('dotenv');
const crypto = require('crypto');
// 加载环境变量
dotenv.config({ path: path.join(__dirname, '..', '.env') });
const redis = require('../src/models/redis');
const logger = require('../src/utils/logger');
const config = require('../config/config');
const ALGORITHM = 'aes-256-cbc';
const IV_LENGTH = 16;
const GEMINI_ACCOUNT_KEY_PREFIX = 'gemini_account:';
const ENCRYPTION_SALT = 'gemini-encryption-salt-2024';
// 生成加密密钥(使用与 geminiAccountService 相同的方法)
function generateEncryptionKey() {
return crypto.scryptSync(config.security.encryptionKey, ENCRYPTION_SALT, 32);
}
// 旧版解密函数(使用冒号分隔)
function decryptOld(text) {
if (!text) return '';
try {
const key = generateEncryptionKey();
const textParts = text.split(':');
const iv = Buffer.from(textParts.shift(), 'hex');
const encryptedText = Buffer.from(textParts.join(':'), 'hex');
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
} catch (error) {
return { error: error.message };
}
}
// 新版解密函数(固定长度)
function decryptNew(text) {
if (!text) return '';
try {
const key = generateEncryptionKey();
// IV 是固定长度的 32 个十六进制字符16 字节)
const ivHex = text.substring(0, 32);
const encryptedHex = text.substring(33); // 跳过冒号
const iv = Buffer.from(ivHex, 'hex');
const encryptedText = Buffer.from(encryptedHex, 'hex');
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
} catch (error) {
return { error: error.message };
}
}
async function debugGeminiDecrypt() {
try {
console.log('🚀 开始调试 Gemini refreshToken 解密...\n');
// 显示加密配置
console.log('📋 加密配置检查:');
console.log(` config.security.encryptionKey: ${config.security.encryptionKey}`);
console.log(` 实际使用的加密密钥长度: ${config.security.encryptionKey.length}`);
console.log(` ENCRYPTION_SALT: ${ENCRYPTION_SALT}`);
console.log();
// 连接 Redis
console.log('📡 连接 Redis...');
await redis.connect();
console.log('✅ Redis 连接成功\n');
// 获取 Gemini 账户
const client = redis.getClient();
const keys = await client.keys(`${GEMINI_ACCOUNT_KEY_PREFIX}*`);
if (keys.length === 0) {
console.log('❌ 没有找到 Gemini 账户');
process.exit(1);
}
console.log(`🔍 找到 ${keys.length} 个 Gemini 账户\n`);
for (const key of keys) {
const accountData = await client.hgetall(key);
const accountId = key.replace(GEMINI_ACCOUNT_KEY_PREFIX, '');
console.log(`\n📋 账户: ${accountData.name} (${accountId})`);
console.log(` 平台: ${accountData.platform}`);
if (accountData.refreshToken) {
console.log(`\n 🔐 RefreshToken 分析:`);
console.log(` 原始长度: ${accountData.refreshToken.length}`);
console.log(` 包含冒号: ${accountData.refreshToken.includes(':') ? '是' : '否'}`);
console.log(` 前50字符: ${accountData.refreshToken.substring(0, 50)}...`);
// 尝试旧版解密
console.log(`\n 📝 尝试旧版解密(冒号分隔):`);
const oldResult = decryptOld(accountData.refreshToken);
if (oldResult.error) {
console.log(` ❌ 失败: ${oldResult.error}`);
} else {
console.log(` ✅ 成功Token前20字符: ${oldResult.substring(0, 20)}...`);
}
// 尝试新版解密
console.log(`\n 📝 尝试新版解密(固定长度):`);
const newResult = decryptNew(accountData.refreshToken);
if (newResult.error) {
console.log(` ❌ 失败: ${newResult.error}`);
} else {
console.log(` ✅ 成功Token前20字符: ${newResult.substring(0, 20)}...`);
}
// 分析加密格式
if (accountData.refreshToken.includes(':')) {
const parts = accountData.refreshToken.split(':');
console.log(`\n 📊 加密格式分析(按冒号分隔):`);
console.log(` 部分数量: ${parts.length}`);
console.log(` 第一部分长度: ${parts[0].length} (应为32即16字节的hex)`);
}
} else {
console.log(` ⚠️ 无 refreshToken`);
}
console.log('\n' + '='.repeat(60));
}
} catch (error) {
console.error('❌ 调试失败:', error);
} finally {
await redis.disconnect();
process.exit(0);
}
}
// 运行调试
debugGeminiDecrypt();