- JavaScript 79.8%
- HTML 20.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| client | ||
| example | ||
| server | ||
| LLMS.md | ||
| package.json | ||
| README.md | ||
| test.js | ||
VivaRAT Captcha
Легковесная, приватная и быстрая Proof-of-Work (PoW) капча для любых веб-сайтов.
Полная независимость от Google reCAPTCHA, Cloudflare Turnstile и hCaptcha. Без слежки, без сторонних серверов, с защитой от ботов и брутфорса.
Преимущества VivaRAT Captcha
- Никаких сторонних сервисов: Задачи генерируются и проверяются исключительно на вашем собственном сервере.
- Пользователь не решает светофоры и автобусы: Человек просто нажимает одну кнопку (чекбокс), а браузер решает криптографическую микрозадачу за 100–300 миллисекунд.
- Защита от ботов и спама: Бот не может отправить форму без затрат процессорного времени на поиск валидного хэша.
- Встроенная криптографическая защита:
- HMAC-SHA256 подпись каждого челленджа сервером (невозможно подделать).
- Защита от повторного использования токенов (Replay Attack Prevention).
- Тайм-аут жизни задачи (по умолчанию 3 минуты).
- Стильный интерфейс: Плавная анимация спиннера и галочки, поддержка тёмной и светлой тем, авто-адаптация.
- Работает везде: Чистый HTML/JS, React, Vue, Svelte, Node.js, Python, PHP.
Структура модуля
vivarat-captcha/
├── client/
│ └── vivarat-captcha.js # Универсальный клиентский JS-виджет (без зависимостей)
├── server/
│ └── vivarat-captcha.js # Серверная библиотека для Node.js (без зависимостей)
├── example/
│ ├── index.html # Пример формы авторизации с переключателем тем
│ └── server.js # Готовый демо-сервер на чистом Node.js
├── test.js # Автоматизированные тесты криптографии
└── README.md # Документация
Быстрый старт за 2 минуты
1. Быстрый запуск готового примера
В папке уже есть готовый демонстрационный сервер:
cd vivarat-captcha
node example/server.js
Откройте в браузере: http://localhost:3344
Интеграция на клиент (Фронтенд)
Вариант 1: Обычный HTML / Любой сайт
- Подключите скрипт
vivarat-captcha.jsи добавьте контейнер для виджета:
<!-- Контейнер для виджета капчи -->
<div id="captcha-box"></div>
<!-- Подключение скрипта (или скопируйте vivarat-captcha.js к себе в проект) -->
<script src="/path/to/vivarat-captcha.js"></script>
<script>
// Инициализация
const captcha = new VivaratCaptcha('#captcha-box', {
endpoint: '/api/captcha-challenge', // URL вашего эндпоинта выдачи задач
theme: 'dark', // 'dark' или 'light'
lang: 'ru', // 'ru' или 'en'
onVerified: (token) => {
console.log('Капча успешно решена, токен:', token);
}
});
// Получить токен при отправке формы через JS:
// const token = captcha.getToken();
</script>
Примечание: Если виджет находится внутри тега
<form>, он автоматически вставляет скрытое поле<input type="hidden" name="vivarat-captcha-token" value="...">, поэтому при обычной отправке формы токен сразу уйдёт на сервер вreq.body['vivarat-captcha-token'].
Вариант 2: React / Next.js
import { useEffect, useRef, useState } from 'react';
// Подключите скрипт через <Script> или скопируйте класс
export function CaptchaWidget({ onVerified }) {
const containerRef = useRef(null);
useEffect(() => {
if (window.VivaratCaptcha && containerRef.current) {
new window.VivaratCaptcha(containerRef.current, {
endpoint: '/api/captcha-challenge',
theme: 'dark',
onVerified: (token) => onVerified(token)
});
}
}, []);
return <div ref={containerRef}></div>;
}
Интеграция на сервер (Бэкенд)
Node.js / Express
const express = require('express');
const VivaratCaptchaServer = require('./server/vivarat-captcha');
const app = express();
app.use(express.json());
// 1. Инициализация сервера капчи с вашим секретным ключом
const captcha = new VivaratCaptchaServer({
secret: 'ваш-секретный-ключ-для-продакшна',
defaultDifficulty: 8000, // Сложность (8000 итераций ~0.15 сек)
expiresInMs: 3 * 60 * 1000 // 3 минуты
});
// 2. Эндпоинт выдачи задачи клиенту
app.get('/api/captcha-challenge', (req, res) => {
const challenge = captcha.generateChallenge();
res.json(challenge);
});
// 3. Проверка капчи при отправке формы
app.post('/api/login', (req, res) => {
const token = req.body['vivarat-captcha-token'];
// Проверяем токен капчи
const verifyResult = captcha.verify(token);
if (!verifyResult.success) {
return res.status(400).json({
error: 'Капча не пройдена',
reason: verifyResult.error
});
}
// Капча верна! Продолжаем вход / регистрацию
res.json({ success: true });
});
// Либо используйте встроенный middleware для маршрутов:
// app.post('/api/register', captcha.middleware(), registerHandler);
app.listen(3000);
Другие языки бэкенда (Python / PHP / Go)
Поскольку алгоритм основан на стандартном Proof-of-Work и HMAC-SHA256, его можно проверить на любом языке:
Пример на Python (FastAPI / Flask):
import hmac, hashlib, json, base64, time
SECRET = b'ваш-секретный-ключ'
def verify_captcha(token_b64):
try:
data = json.loads(base64.b64decode(token_b64).decode())
salt, ts, number = data['salt'], data['timestamp'], data['number']
challenge, sig = data['challenge'], data['signature']
# 1. Проверка времени (3 мин)
if time.time() * 1000 - ts > 180000:
return False
# 2. Проверка HMAC подписи сервера
expected_sig = hmac.new(SECRET, f"{challenge}:{ts}".encode(), hashlib.sha256).hexdigest()
if sig != expected_sig:
return False
# 3. Проверка вычисления SHA-256
computed = hashlib.sha256(f"{salt}:{ts}:{number}".encode()).hexdigest()
return computed == challenge
except Exception:
return False
Пример на PHP:
function verify_captcha($token_b64, $secret) {
$data = json_decode(base64_decode($token_b64), true);
if (!$data) return false;
// Проверка тайм-аута (3 минуты)
if ((round(microtime(true) * 1000) - $data['timestamp']) > 180000) return false;
// Проверка подписи
$expected_sig = hash_hmac('sha256', $data['challenge'] . ':' . $data['timestamp'], $secret);
if ($data['signature'] !== $expected_sig) return false;
// Проверка решения PoW
$computed = hash('sha256', $data['salt'] . ':' . $data['timestamp'] . ':' . $data['number']);
return $computed === $data['challenge'];
}
Опции клиента (VivaratCaptcha)
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
endpoint |
string |
'/api/captcha-challenge' |
URL адрес сервера, где вызывается generateChallenge() |
theme |
string |
'dark' |
Тема оформления: 'dark' или 'light' |
lang |
string |
'ru' |
Язык текста: 'ru' или 'en' |
inputName |
string |
'vivarat-captcha-token' |
Имя скрытого <input>, создаваемого внутри формы |
autoSolve |
boolean |
false |
Автоматически запускать решение при загрузке страницы |
onVerified |
function |
null |
Callback-функция (token) => {}, вызываемая при успешном решении |
onError |
function |
null |
Callback-функция (err) => {} при возникновении сетевой ошибки |
Методы объекта капчи:
captcha.getToken()— возвращает текущий base64-токен решения (или пустую строку, если ещё не решено).captcha.reset()— сбрасывает капчу в исходное состояние (нужно после неуспешного входа или для повторной отправки).captcha.solve()— программно запускает процесс решения.
Лицензия
MIT License. Свободно для использования в любых коммерческих и личных проектах. Разработано для сообщества VivaRAT.