feat: 添加 Gemini refreshToken 解密调试脚本

- 检查环境变量中的 ENCRYPTION_KEY
- 显示加密数据的格式信息
- 尝试新旧两种解密方法
- 输出详细的调试信息帮助定位问题

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
shaw
2025-07-26 12:16:08 +08:00
parent 3d13542fff
commit a939fcebac

View File

@@ -0,0 +1,147 @@
#!/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 ALGORITHM = 'aes-256-cbc';
const IV_LENGTH = 16;
const GEMINI_ACCOUNT_KEY_PREFIX = 'gemini_account:';
// 生成加密密钥
function generateEncryptionKey() {
const configKey = process.env.ENCRYPTION_KEY;
if (!configKey || configKey.length !== 32) {
throw new Error('ENCRYPTION_KEY must be exactly 32 characters long');
}
return Buffer.from(configKey);
}
// 旧版解密函数(使用冒号分隔)
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(` ENCRYPTION_KEY 长度: ${process.env.ENCRYPTION_KEY ? process.env.ENCRYPTION_KEY.length : 'undefined'}`);
console.log(` ENCRYPTION_KEY 前8位: ${process.env.ENCRYPTION_KEY ? process.env.ENCRYPTION_KEY.substring(0, 8) + '...' : 'undefined'}`);
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();