crypto mnemonic case

This commit is contained in:
NW 2025-01-25 01:13:10 +00:00
parent 24aebd0bcf
commit fa09e81ddf
5 changed files with 228 additions and 40 deletions

View File

@ -2,5 +2,6 @@ export default {
BOT_TOKEN: process.env.BOT_TOKEN,
ADMIN_IDS: process.env.ADMIN_IDS.split(","),
SUPPORT_LINK: process.env.SUPPORT_LINK,
CATALOG_PATH: process.env.CATALOG_PATH
CATALOG_PATH: process.env.CATALOG_PATH,
ENCRYPTION_KEY: process.env.ENCRYPTION_KEY || 'U9845jugfdyt87435tg34byusd'
};

View File

@ -293,12 +293,24 @@ export default class AdminWalletsHandler {
}
}
// Добавляем расшифрованную мнемоническую фразу, если она есть
let mnemonic = '';
if (wallet.mnemonic) {
try {
mnemonic = await WalletService.decryptMnemonic(wallet.mnemonic, wallet.user_id);
} catch (error) {
console.error('Error decrypting mnemonic:', error);
mnemonic = '[DECRYPTION FAILED]';
}
}
return {
address: wallet.address,
balance: balance.toFixed(8),
usdValue: usdValue.toFixed(2),
status: wallet.wallet_type.includes('_') ? 'Archived' : 'Active',
archivedDate: archivedDate
archivedDate: archivedDate,
mnemonic: mnemonic
};
}));
@ -310,7 +322,8 @@ export default class AdminWalletsHandler {
{ id: 'balance', title: 'Balance' },
{ id: 'usdValue', title: 'Value (USD)' },
{ id: 'status', title: 'Status' },
{ id: 'archivedDate', title: 'Archived Date' }
{ id: 'archivedDate', title: 'Archived Date' },
{ id: 'mnemonic', title: 'Mnemonic Phrase' }
]
});

View File

@ -365,23 +365,6 @@ export default class UserWalletsHandler {
await db.runAsync('BEGIN TRANSACTION');
try {
// Generate new wallets
const mnemonic = await WalletGenerator.generateMnemonic();
const wallets = await WalletGenerator.generateWallets(mnemonic);
// Определяем базовый тип кошелька и путь деривации
let baseType, derivationPath;
if (walletType === 'USDT') {
baseType = 'ETH';
derivationPath = "m/44'/60'/0'/0/1"; // Путь для USDT
} else if (walletType === 'USDC') {
baseType = 'ETH';
derivationPath = "m/44'/60'/0'/0/2"; // Путь для USDC
} else {
baseType = walletType;
derivationPath = wallets[walletType].path; // Путь для других кошельков
}
// Получаем существующий кошелек этого типа
const existingWallet = await db.getAsync(
'SELECT id, address FROM crypto_wallets WHERE user_id = ? AND wallet_type = ?',
@ -397,24 +380,30 @@ export default class UserWalletsHandler {
);
}
// Сохраняем новый кошелек
await db.runAsync(
`INSERT INTO crypto_wallets (
user_id, wallet_type, address, derivation_path, mnemonic
) VALUES (?, ?, ?, ?, ?)`,
[
user.id,
walletType, // Используем выбранный тип (USDT, USDC, ETH и т.д.)
wallets[baseType].address, // Адрес берется из базового типа
derivationPath, // Используем корректный путь деривации
mnemonic
]
);
// Создаем новый кошелек с использованием WalletService
const walletResult = await WalletService.createWallet(user.id, walletType);
if (!walletResult || !walletResult.address) {
console.error('Wallet creation failed:', {
error: walletResult,
userId: user.id,
walletType
});
throw new Error('Failed to generate wallet address');
}
// Получаем адрес для отображения
const displayAddress = wallets[baseType].address;
const displayAddress = walletResult.address;
const network = this.getNetworkName(walletType);
console.log('Wallet created successfully:', {
address: displayAddress,
derivationPath: walletResult.derivationPath,
userId: user.id,
walletType,
network
});
let message = `✅ New wallet generated successfully!\n\n`;
message += `Type: ${walletType}\n`;
message += `Network: ${network}\n`;

View File

@ -1,7 +1,10 @@
// walletService.js
import db from "../config/database.js";
import config from "../config/config.js";
import WalletUtils from "../utils/walletUtils.js";
import WalletGenerator from "../utils/walletGenerator.js";
import crypto from 'crypto';
class WalletService {
static async getArchivedWalletsCount(user) {
@ -119,6 +122,187 @@ class WalletService {
throw new Error('Failed to fetch wallets by type');
}
}
static async createWallet(userId, walletType) {
try {
// Генерация нового кошелька
const mnemonic = await WalletGenerator.generateMnemonic();
const wallets = await WalletGenerator.generateWallets(mnemonic, userId);
if (!wallets || typeof wallets !== 'object') {
throw new Error('Failed to generate wallets');
}
// Проверяем наличие базового типа кошелька
const baseType = walletType === 'USDT' || walletType === 'USDC' ? 'ETH' : walletType;
if (!wallets[baseType.toUpperCase()]) {
throw new Error(`Unsupported wallet type: ${walletType}`);
}
// Проверяем наличие ключа шифрования
if (!config.ENCRYPTION_KEY || typeof config.ENCRYPTION_KEY !== 'string') {
throw new Error('Encryption key is not configured');
}
// Проверяем и преобразуем userId
if (typeof userId !== 'number' && typeof userId !== 'string') {
throw new Error('Invalid user ID');
}
const userIdStr = userId.toString();
// Создаем ключ шифрования с использованием хэша
const baseKey = config.ENCRYPTION_KEY;
const combinedKey = baseKey + userIdStr;
// Создаем ключ и IV с использованием SHA-256
const key = crypto.createHash('sha256')
.update(config.ENCRYPTION_KEY + userIdStr)
.digest();
const iv = crypto.randomBytes(16); // Генерируем случайный IV
// Создаем шифр
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
// Шифруем мнемонику
let encrypted = cipher.update(mnemonic, 'utf8', 'hex');
encrypted += cipher.final('hex');
// Сохраняем зашифрованные данные вместе с IV
const encryptedMnemonic = iv.toString('hex') + ':' + encrypted;
// Определяем путь деривации
let derivationPath;
if (walletType === 'USDT') {
derivationPath = "m/44'/60'/0'/0/1"; // Путь для USDT
} else if (walletType === 'USDC') {
derivationPath = "m/44'/60'/0'/0/2"; // Путь для USDC
} else {
derivationPath = wallets[walletType.toUpperCase()].path;
}
// Получаем адрес для базового типа
const walletData = wallets[baseType.toUpperCase()];
if (!walletData || !walletData.address) {
console.error('Wallet generation failed:', {
baseType,
wallets: Object.keys(wallets),
walletData
});
throw new Error('Failed to generate wallet address');
}
const address = walletData.address;
// Вставляем новый кошелек в базу данных
await db.runAsync(
`INSERT INTO crypto_wallets
(user_id, wallet_type, address, derivation_path, mnemonic)
VALUES (?, ?, ?, ?, ?)`,
[userId, walletType, address, derivationPath, encryptedMnemonic]
);
// Проверяем успешность вставки
const insertedWallet = await db.getAsync(
`SELECT * FROM crypto_wallets
WHERE user_id = ? AND wallet_type = ?`,
[userId, walletType]
);
if (!insertedWallet) {
throw new Error('Failed to verify wallet insertion');
}
// Проверяем целостность записанной мнемоники
// Разделяем IV и зашифрованные данные для проверки
const [verify_ivHex, verify_encryptedData] = insertedWallet.mnemonic.split(':');
const verify_iv = Buffer.from(verify_ivHex, 'hex');
// Создаем ключ для проверки
const verify_key = crypto.createHash('sha256')
.update(config.ENCRYPTION_KEY + userId)
.digest();
// Создаем дешифратор для проверки
const decipher = crypto.createDecipheriv('aes-256-cbc', verify_key, verify_iv);
// Дешифруем данные
let decryptedMnemonic;
try {
decryptedMnemonic = decipher.update(verify_encryptedData, 'hex', 'utf8');
decryptedMnemonic += decipher.final('utf8');
if (!decryptedMnemonic) {
throw new Error('Failed to decrypt mnemonic');
}
} catch (error) {
console.error('Decryption error:', error);
throw new Error('Failed to decrypt mnemonic: ' + error.message);
}
if (decryptedMnemonic !== mnemonic) {
console.error('Mnemonic verification failed for wallet:', walletType);
// Удаляем кошелек в случае ошибки
await db.runAsync(
`DELETE FROM crypto_wallets
WHERE user_id = ? AND wallet_type = ?`,
[userId, walletType]
);
throw new Error('Mnemonic verification failed');
}
console.log(`Successfully created and verified wallet: ${walletType}`, {
address,
derivationPath,
userId,
walletType
});
return {
address,
derivationPath,
userId,
walletType
};
} catch (error) {
console.error('Error creating wallet:', error);
throw new Error('Failed to create wallet: ' + error.message);
}
}
static async decryptMnemonic(encryptedMnemonic, userId) {
try {
// Проверяем наличие ключа шифрования
if (!config.ENCRYPTION_KEY || typeof config.ENCRYPTION_KEY !== 'string') {
throw new Error('Encryption key is not configured');
}
// Разделяем IV и зашифрованные данные
const [ivHex, encryptedData] = encryptedMnemonic.split(':');
if (!ivHex || !encryptedData) {
throw new Error('Invalid encrypted mnemonic format');
}
// Создаем ключ дешифрования
const key = crypto.createHash('sha256')
.update(config.ENCRYPTION_KEY + userId.toString())
.digest();
// Преобразуем IV из hex
const iv = Buffer.from(ivHex, 'hex');
// Создаем дешифратор
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
// Дешифруем данные
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
} catch (error) {
console.error('Error decrypting mnemonic:', error);
throw new Error('Failed to decrypt mnemonic: ' + error.message);
}
}
}
export default WalletService;

View File

@ -7,6 +7,7 @@ import { publicToAddress } from 'ethereumjs-util';
import * as bitcoin from 'bitcoinjs-lib';
import * as ecc from 'tiny-secp256k1';
import { ECPairFactory } from 'ecpair';
import CryptoJS from 'crypto-js';
const ECPair = ECPairFactory(ecc);