diff --git a/admin-next/src/lib/mnemonic.ts b/admin-next/src/lib/mnemonic.ts
new file mode 100644
index 0000000..e1d1f2c
--- /dev/null
+++ b/admin-next/src/lib/mnemonic.ts
@@ -0,0 +1,49 @@
+import crypto from 'crypto';
+
+// Дешифровка мнемоник — тот же алгоритм, что в боте (src/utils/encryption.js)
+const HKDF_SALT_LENGTH = 32;
+const IV_LENGTH = 16;
+const KEY_LENGTH = 32;
+const HKDF_INFO = 'telegram-shop-mnemonic-encryption';
+
+function deriveKeyHKDF(masterKey: string, salt: Buffer, userId: number) {
+ return crypto.hkdfSync(
+ 'sha256',
+ Buffer.from(masterKey, 'utf8'),
+ salt,
+ HKDF_INFO + ':' + userId.toString(),
+ KEY_LENGTH
+ );
+}
+
+function deriveKeyLegacy(masterKey: string, userId: number) {
+ return crypto.createHash('sha256').update(masterKey + userId.toString()).digest();
+}
+
+export function decryptMnemonic(encryptedData: string, userId: number): string {
+ const parts = encryptedData.split(':');
+ const masterKey = process.env.ENCRYPTION_KEY || '';
+
+ if (parts.length === 3) {
+ const salt = Buffer.from(parts[0], 'hex');
+ const key = deriveKeyHKDF(masterKey, salt, userId);
+ const iv = Buffer.from(parts[1], 'hex');
+ const ciphertext = parts[2];
+ const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
+ let decrypted = decipher.update(ciphertext, 'hex', 'utf8');
+ decrypted += decipher.final('utf8');
+ return decrypted;
+ }
+
+ if (parts.length === 2) {
+ const key = deriveKeyLegacy(masterKey, userId);
+ const iv = Buffer.from(parts[0], 'hex');
+ const ciphertext = parts[1];
+ const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
+ let decrypted = decipher.update(ciphertext, 'hex', 'utf8');
+ decrypted += decipher.final('utf8');
+ return decrypted;
+ }
+
+ throw new Error('Invalid encrypted data format');
+}
diff --git a/docker-compose.yml b/docker-compose.yml
index bdccd37..0e94e45 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -46,6 +46,8 @@ services:
- DATABASE_URL=file:/app/db/shop.db
- ADMIN_SECRET=${ADMIN_SECRET:-changeme}
- SUPER_ADMIN_SECRET=${SUPER_ADMIN_SECRET:-changeme_super}
+ # Ключ шифрования мнемоник (тот же, что у бота — для дешифровки сид-фраз)
+ - ENCRYPTION_KEY=${ENCRYPTION_KEY}
# ИИ-чатбот: настройки берутся из site_settings (chatbot_*)
- CHATBOT_API_ENDPOINT=${CHATBOT_API_ENDPOINT:-https://api.openai.com/v1}
- CHATBOT_API_KEY=${CHATBOT_API_KEY:-}