Files
arestools/src/core/crypto.js
T
ros 15a03a77fd Переписать проект в личный MTProto-юзербот
Смена архитектуры с бизнес-бота на Bot API (команды со слешем) на
личный юзербот на GramJS/MTProto с управлением через компаньон-бота.

Возможности:
- antidelete — кэш входящих в личке, восстановление удалённых «у всех»
- onetime — перехват «просмотр один раз» фото/видео до истечения ссылки
- локальное хранилище node:sqlite + шифрование AES-256-GCM, чистка по сроку
- компаньон-бот (grammY): инлайн-панель, лента с пагинацией, выдача медиа,
  доступ только владельцу по OWNER_ID

Устройство:
- core/ — crypto, db, media, loader, registry, logger
- userbot/ — MTProto-клиент из строки сессии, подписка на события
- modules/ — фичи как модули с хуками setup/onMessage/onEdited/onDeleted
- bot/ — компаньон-бот (единственный UI)
- scripts/login.js — генерация строки сессии

Удалён старый код Bot API (commands/, handlers/, middlewares/, dispatcher,
store). Обновлены README и .env.example. Hcrgram/ (сторонний референс)
добавлен в .gitignore.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 19:16:52 +03:00

48 lines
1.7 KiB
JavaScript

import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'node:crypto';
import { config } from '../config.js';
const ALGORITHM = 'aes-256-gcm';
const IV_LEN = 12;
const TAG_LEN = 16;
let keyCache = null;
/**
* Ключ из ENCRYPTION_KEY. Принимаем как 64-символьный hex (готовые 32 байта),
* так и произвольную парольную фразу — её растягиваем scrypt до 32 байт.
*/
function getKey() {
if (keyCache) return keyCache;
const raw = config.encryptionKey();
if (/^[0-9a-f]{64}$/i.test(raw)) {
keyCache = Buffer.from(raw, 'hex');
} else {
keyCache = scryptSync(raw, 'telegrambusiness/v1', 32);
}
return keyCache;
}
/**
* Шифрует буфер. Формат на выходе: [iv(12)][tag(16)][ciphertext].
* Так весь артефакт самодостаточен — расшифровка не требует внешних метаданных.
*/
export function encrypt(plaintext) {
const iv = randomBytes(IV_LEN);
const cipher = createCipheriv(ALGORITHM, getKey(), iv);
const data = Buffer.concat([cipher.update(plaintext), cipher.final()]);
return Buffer.concat([iv, cipher.getAuthTag(), data]);
}
export function decrypt(payload) {
const iv = payload.subarray(0, IV_LEN);
const tag = payload.subarray(IV_LEN, IV_LEN + TAG_LEN);
const data = payload.subarray(IV_LEN + TAG_LEN);
const decipher = createDecipheriv(ALGORITHM, getKey(), iv);
decipher.setAuthTag(tag);
return Buffer.concat([decipher.update(data), decipher.final()]);
}
export const encryptString = (text) => encrypt(Buffer.from(text, 'utf8')).toString('base64');
export const decryptString = (b64) => decrypt(Buffer.from(b64, 'base64')).toString('utf8');