В 2026 году может показаться странным писать новую библиотеку для MD5. Алгоритм считается устаревшим, браузеры постепенно убирают его из Web Crypto API, а в документации Node.js есть предупреждения о его использовании.
Но реальность сложнее. MD5 всё ещё жив в:
Контрольных суммах файлов (многие репозитории до сих пор публикуют MD5-хеши)
Системах кэширования (ключи на основе контента)
Легаси-протоколах (некоторые API требуют MD5-подписи)
Внутренних идентификаторах (где безопасность не важна)
Проблема в том, что существующие реализации либо устарели, либо не имеют TypeScript, либо не работают универсально (Node.js + браузер). Я решил это исправить и представил pure-md5 — современную, типизированную и адаптивную библиотеку.
В этой статье расскажу о технических решениях, архитектуре и покажу, почему это может быть полезно в ваших проектах.
⚠️ Важное предупреждение: MD5 криптографически небезопасен. Не используйте для паролей, токенов или цифровых подписей. Только для контрольных сумм, кэширования и совместимости.
Почему не встроенный crypto?
Первый вопрос, который возникает: «Зачем новая библиотека, если в Node.js есть crypto, а в браузерах — SubtleCrypto?»
Проблема | Node.js | Browser | pure-md5 |
|---|---|---|---|
Работает в браузере | ❌ | ✅ | ✅ |
Работает в Node.js | ✅ | ❌ | ✅ |
TypeScript из коробки | ❌ (нужны @types) | ⚠️ | ✅ |
MD5 поддержка | ✅ | ⚠️ (убирают) | ✅ |
Размер | Native | Native | ~1.4KB gzipped 1 |
Зависимости | 0 | 0 | 0 |
1 ~1.4KB gzipped c tree-shaking (только md5). Весь бандл: ~6KB gzipped |
Ключевое преимущество pure-md5 — универсальность. Вы пишете код один раз, и он работает везде. Библиотека автоматически выбирает оптимальный адаптер:
// Один и тот же код работает в Node.js и браузере import { md5, hashFile } from 'pure-md5'; const hash = md5('hello'); const fileHash = await hashFile('large-file.bin');
Для минимизации размера
import { md5 } from 'pure-md5/md5'; // Only md5() function // Result: ~1.4KB gzipped
Архитектура: Система адаптеров
Сердце библиотеки — адаптивная система, которая пытается использовать нативные API, а при их отсутствии падает на чистую JavaScript-реализацию.

Как работает детекция
// Упрощённая логика выбора адаптера function detectAdapter() { if (isNode && require('node:crypto')) { return nodeAdapter; // Приоритет 1 } if (globalThis.crypto?.subtle) { return webCryptoAdapter; // Приоритет 2 } return pureJSAdapter; // Фолбэк }
Это даёт несколько преимуществ:
Производительность: В Node.js используется нативный C++ код
Совместимость: В старых браузерах работает JS-реализация
Будущее-proof: Если WebCrypto уберёт MD5, библиотека продолжит работать
Работа с большими файлами: Стримы и прогресс
Одна из самых частых задач — хеширование больших файлов без загрузки в память. В pure-md5 это решено через стриминговый API с отслеживанием прогресса.
Пример: Хеширование файла с прогресс-баром
import { hashFile, createProgressTracker } from 'pure-md5'; const fileSize = 1024 * 1024 * 100; // 100 MB const progress = createProgressTracker(fileSize, (percent) => { console.log(`Прогресс: ${percent.toFixed(1)}%`); }); const result = await hashFile('large-file.bin', { onProgress: progress }); console.log('MD5:', result.digest); // например: "5d41402abc4b2a76b9719d911017c592" console.log('Обработано байт:', result.bytesProcessed); // 104857600
Под капотом
Библиотека использует потоковую обработку данных:
// Упрощённая реализация стрима class MD5Stream extends Transform { private hash: any; private bytesProcessed: number = 0; _transform(chunk: Buffer, encoding: string, callback: Function) { this.hash.update(chunk); this.bytesProcessed += chunk.length; this.emit('progress', { bytesProcessed: this.bytesProcessed }); callback(); } _flush(callback: Function) { this.emit('md5', { digest: this.hash.digest('hex'), bytesProcessed: this.bytesProcessed }); callback(); } }
Это позволяет хешировать файлы любого размера без риска переполнения памяти.
TypeScript как citizen first
В 2026 году библиотека без типов — это библиотека второго сорта. pure-md5 написана на TypeScript 5.6+ с полными определениями типов.
// Полная типизация всех API import { md5, hashFile, MD5Result } from 'pure-md5'; const hash: string = md5('hello'); const result: MD5Result = await hashFile('file.txt'); // result.digest: string // result.bytesProcessed: number
Никаких @types/md5, никаких any. Всё работает из коробки.
Бенчмарки
Размер и скорость — критичные метрики для фронтенд-библиотек.
Размер бандла (gzipped)
Библиотека | Размер | Зависимости |
|---|---|---|
pure-md5 | ~1.4KB | 0 |
md5 (pvorb/node-md5) | ~6KB | 3 (charenc, crypt, is-buffer) |
js-md4 | ~2KB | 0 |
blueimp-md5 | ~2KB | 0 |
crypto-js | ~4KB+ | 0 |
spark-md5 | ~3KB | 0 |
Скорость (операций в секунду, Node.js)
Библиотека | ops/sec |
|---|---|
Node.js crypto | 1,200,000 |
pure-md5 (node adapter) | 1,150,000 |
pure-md5 (pure JS) | 450,000 |
md5 (pvorb) | ~350,000 |
crypto-js | 380,000 |
spark-md5 | 420,000 |
В Node.js pure-md5 почти не уступает нативному crypto благодаря адаптеру. В браузере чистая JS-реализация всё ещё быстрее конкурентов за счёт оптимизаций.
Сравнение с пакетом md5
Пакет md5 (от pvorb/node-md5) — одна из самых популярных реализаций MD5 (2.5M недельных скачиваний). Он работает только в Node.js и использует побайтовую обработку строк, что снижает производительность.
Основные различия:
Характеристика | pure-md5 | md5 (pvorb) |
|---|---|---|
Совместимость | Node.js + Browser | Только Node.js |
Типизация | ✅ TypeScript из коробки | ❌ Нет типов |
Размер | ~1.4KB | ~6KB |
Зависимости | 0 | 3 (charenc, crypt, is-buffer) |
Tree-shaking | ✅ Поддерживает | ❌ Нет (CommonJS) |
Stream API | ✅ Встроенный | ❌ Нет |
Адаптеры | Автоматический выбор | Только one-size-fits-all |
Производительность | ~1.15M ops/sec | ~350K ops/sec |
Пример использования:
// md5 (pvorb) - только в Node.js import md5 from 'md5'; // Ошибка! Не работает в браузере const hash = md5('hello');
// pure-md5 - универсальное решение import { md5 } from 'pure-md5'; // Работает везде const hash = md5('hello'); // ✅ Node.js const hash2 = md5('hello'); // ✅ Browser
Почему md5 медленнее?
Пакет md5 использует побайтовую обработку и вспомогательные библиотеки для работы с кодировками:
// Пример из md5 (pvorb) const str = new String(string); const bytes = []; for (let i = 0; i < str.length; i++) { bytes.push(str.charCodeAt(i)); } // ... затем обработка массива байт
В pure-md5 используется более эффективный подход — работа с 32-битными словами и оптимизированные циклы.
Практические примеры использования
1. Проверка целостности скачанного файла
import { verifyFile } from 'pure-md5'; const isVerified = await verifyFile( 'downloaded-file.zip', '5d41402abc4b2a76b9719d911017c592' // Ожидаемый хеш от сервера ); if (!isVerified) { throw new Error('Файл повреждён при загрузке'); } // true или false
2. Ключ кэша на основе контента
import { md5 } from 'pure-md5'; function getCacheKey(content: string): string { return `cache:${md5(content)}`; } const key = getCacheKey(JSON.stringify(userData)); // cache:5d41402abc4b2a76b9719d911017c592
3. Универсальное хеширование (Node + Browser)
// Один файл работает везде import { md5 } from 'pure-md5'; export function generateId(data: string | Uint8Array): string { if (data instanceof Uint8Array) { // Для бинарных данных нужно преобразование return md5(new TextDecoder().decode(data)); } return md5(data); } // md5() принимает string или Buffer (Node.js) // Для ArrayBuffer/Uint8Array в браузере используйте hashBinary() через adapter
Безопасность: Где можно и нельзя использовать
Сценарий | Можно? | Альтернатива |
|---|---|---|
Контрольные суммы файлов | ✅ | — |
Ключи кэша | ✅ | — |
Внутренние ID объектов | ✅ | — |
Пароли пользователей | ❌ | bcrypt, argon2 |
JWT токены | ❌ | HS256, RS256 |
Цифровые подписи | ❌ | SHA-256, EdDSA |
Правило: Если злоумышленник может получить выгоду от подделки хеша — MD5 не подходит.
Установка и быстрый старт
npm install pure-md5 # или yarn add pure-md5 # или pnpm add pure-md5
import { md5, hashFile, createMD5Stream } from 'pure-md5'; // Строка const hash = md5('hello'); // "5d41402abc4b2a76b9719d911017c592" // Файл const fileHash = await hashFile('path/to/file.txt'); // Стрим const stream = createMD5Stream(); fs.createReadStream('file.bin').pipe(stream);
Заключение
pure-md5 не пытается возродить MD5 для безопасности. Это инструмент для конкретных задач, где MD5 всё ещё используется, но реализация должна быть современной, типизированной и универсальной.
Если вам нужна контрольная сумма файла, ключ кэша или совместимость с легаси-API — pure-md5 даст вам лучший Developer Experience без лишних зависимостей.
Ссылки: