crypto mnemonic case
This commit is contained in:
@@ -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;
|
||||
export default WalletService;
|
||||
|
||||
Reference in New Issue
Block a user