https://github.com/efedotof/vaultly
Vaultly — облачное хранилище с end‑to‑end шифрованием и нулевым разглашением. Flutter‑клиент + Spring Boot‑бэкенд. Доверяйте математике!!
https://github.com/efedotof/vaultly
aes-gcm cloud-storage cross-platform cryptography end-to-end-encryption file-encryption flutter privacy rsa-oaep security self-hosted shps spring-boot zero-knowledge
Last synced: 2 months ago
JSON representation
Vaultly — облачное хранилище с end‑to‑end шифрованием и нулевым разглашением. Flutter‑клиент + Spring Boot‑бэкенд. Доверяйте математике!!
- Host: GitHub
- URL: https://github.com/efedotof/vaultly
- Owner: efedotof
- Created: 2026-02-08T06:52:21.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-04-18T10:07:23.000Z (2 months ago)
- Last Synced: 2026-04-18T11:44:10.208Z (2 months ago)
- Topics: aes-gcm, cloud-storage, cross-platform, cryptography, end-to-end-encryption, file-encryption, flutter, privacy, rsa-oaep, security, self-hosted, shps, spring-boot, zero-knowledge
- Homepage:
- Size: 5.61 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Vaultly. Конфиденциальность как стандарт.
Vaultly — облачное хранилище нового поколения, созданное для тех, кто понимает разницу между простым паролем и сквозным шифрованием.
### 🔐 End-to-End Encryption (E2EE)
Ваши файлы шифруются на устройстве до отправки в сеть. Сервер видит только зашифрованные блоки данных, не имея ключей для их расшифровки. Это не функция, это фундамент архитектуры Vaultly.
### 📱 Бесшовный доступ
Flutter-основа обеспечивает плавный и нативный опыт на всех платформах. Получите доступ к своему хранилищу так же легко, как к локальной папке, но с уровнем защиты банковского хранилища.
### 🛡 Целостность данных
Никакой слежки, никакого анализа содержимого для рекламы. Только вы решаете, что, где и как хранить.
---
Vaultly — это ответ тем, кто устал читать новости об утечках. **Доверяйте математике, а не обещаниям.**
---
## 🏛 Архитектура бэкенда
Серверная часть Vaultly построена на **Spring Boot** с применением **PostgreSQL** и **AWS S3**-совместимого объектного хранилища. Вся бизнес-логика спроектирована вокруг принципа **нулевого разглашения (Zero-Knowledge)** — сервер никогда не обрабатывает пользовательские данные в открытом виде.
| Компонент | Технологии | Назначение |
| :--- | :--- | :--- |
| **REST API** | Spring Boot, Spring Security | Аутентификация, управление файлами и папками, сессии |
| **Хранение файлов** | S3 API (Beget Cloud) | Хранение зашифрованных `.shps` контейнеров |
| **База данных** | PostgreSQL | Метаданные, пользователи, права доступа, ключи устройств |
| **Криптография** | `javax.crypto`, `java.security` | Реализация протокола SHPS, управление ключами |
---
## 🛡 Протокол шифрования SHPS (Shirmps Protocol)
Сердце безопасности Vaultly — собственный формат файлов `.shps`, реализующий гибридное шифрование. Каждый файл, покидающий устройство клиента, упаковывается в криптографический контейнер, который сервер может лишь хранить, но не читать.
### 📦 Структура SHPS-контейнера
Файл `.shps` состоит из трёх логических частей:
1. **Заголовок (Header)** — 4 байта длины + JSON с метаданными и зашифрованным сессионным ключом.
2. **Зашифрованное тело** — данные, зашифрованные **AES-256-GCM**.
3. **Тег аутентификации** — встроен в поток GCM.
```java
// Ключевые поля заголовка (ShirmpsHeader)
private String version = "1.0";
private String algorithm = "AES-256-GCM";
private String keyEncryption = "RSA-OAEP";
private String encryptedKey; // AES-ключ, зашифрованный RSA
private String iv; // Вектор инициализации для AES-GCM
private String signature; // Цифровая подпись (SHA256withRSA)
private String keyOwner; // "user" или "server"
private Map metadata; // Сжатие GZIP, уровень компрессии
```

### ⚙️ Процесс шифрования (гибридная схема)
1. **Генерация сессионного ключа**: Случайный 256-битный ключ AES.
2. **Сжатие (опционально)**: GZIP с максимальной компрессией для уменьшения трафика.
3. **Шифрование данных**: `AES/GCM/NoPadding` с вектором инициализации 12 байт. GCM обеспечивает аутентификацию и целостность.
4. **Шифрование ключа**: Сессионный AES-ключ зашифровывается с помощью `RSA-2048 OAEP (SHA-256)` публичным ключом получателя (пользователя или сервера).
5. **Подпись**: Хэш SHA-256 от исходных данных подписывается приватным ключом отправителя для гарантии авторства и неизменности.
### 🔓 Режимы работы ключей
| Режим | `keyOwner` | Сценарий использования |
| :--- | :--- | :--- |
| **Приватный файл** | `"user"` | AES-ключ зашифрован публичным ключом пользователя. Только владелец может расшифровать. Сервер хранит непрозрачный блоб. |
| **Публичный доступ** | `"server"` | AES-ключ зашифрован публичным ключом сервера. Сервер расшифровывает файл для отдачи по временной ссылке. |
### 💾 Потоковая обработка
Бэкенд реализует потоковое шифрование/дешифрование с минимальным потреблением памяти, используя `CipherInputStream` / `CipherOutputStream`. Это позволяет обрабатывать файлы размером в десятки гигабайт, не загружая их целиком в оперативную память.
```java
// Пример потоковой расшифровки для публичной ссылки (ShpsSecurityService)
public void decryptServerEncryptedToStream(InputStream shpsStream, OutputStream out) {
// 1. Чтение заголовка
// 2. Расшифровка AES-ключа серверным приватным ключом
// 3. CipherInputStream -> (GZIPInputStream) -> OutputStream
}
```
### 🗄 Модель данных и безопасность ключей
База данных спроектирована так, чтобы даже в случае компрометации SQL-дампа злоумышленник не получил доступ к содержимому файлов.
- **Пользователи (`users`)**: Хранят публичный ключ RSA, зашифрованный приватный ключ (защищён паролем пользователя с использованием `salt`), `storage_used`, `storage_limit`.
- **Устройства (`devices`)**: Каждое клиентское устройство (смартфон, ПК) регистрирует свой уникальный ID и публичный ключ. Приватный ключ пользователя хранится на устройстве в зашифрованном виде и синхронизируется через бэкенд (зашифрован публичным ключом устройства).
- **Файлы (`files`)**: Хранят `s3_key` на объект `.shps`. Поле `is_public` управляет режимом шифрования (`keyOwner`).
- **Временные ссылки (`temp_file_access`)**: Токены для публичного доступа с ограничением по времени и количеству скачиваний. Пароль на ссылку хранится в виде хэша.
### 🔑 Управление ключами сервера
Пара ключей сервера загружается из файлов `.pem`, пути к которым задаются в `.env`. Для шифрования сессионных ключей используется строго `OAEPWithSHA-256AndMGF1Padding`. При старте приложения сервер проверяет валидность пары ключей тестовым шифрованием/дешифрованием.
```java
// ServerKeyService: загрузка ключей и проверка пары
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.ENCRYPT_MODE, serverPublicKey);
byte[] encrypted = cipher.doFinal(testData);
cipher.init(Cipher.DECRYPT_MODE, serverPrivateKey);
byte[] decrypted = cipher.doFinal(encrypted);
```
---
### 📱 Клиентская часть (Flutter)
---
Клиент, написанный на Flutter, выполняет всю криптографическую работу локально, не доверяя серверу:
- Генерация и управление ключевыми парами RSA.
- Шифрование файлов перед отправкой.
- Дешифрование на лету при скачивании.
- Бесшовная синхронизация состояния с бэкендом через REST API.
### 🚀 Быстрый старт (Backend)
1. **Клонируйте репозиторий**
```bash
git clone https://github.com/your-org/vaultly-backend.git
cd vaultly-backend
```
2. **Настройте переменные окружения (файл `.env`)**
```dotenv
SERVER_PRIVATE_KEY_PATH=/path/to/private.pem
SERVER_PUBLIC_KEY_PATH=/path/to/public.pem
S3_BUCKET=your-bucket-name
S3_PUBLIC_URL=https://s3.example.com/bucket-name
```
3. **Запустите PostgreSQL и выполните миграции**
Миграции Flyway (`V1__initial_schema.sql` и последующие) создадут все необходимые таблицы и триггеры.
4. **Соберите и запустите**
```bash
./mvnw spring-boot:run
```
## 📱 Клиентская часть (Flutter)
Клиент Vaultly написан на Flutter и обеспечивает полную реализацию end‑to‑end шифрования непосредственно на устройстве пользователя. Приложение работает на Android, iOS, Windows, macOS, Linux и в браузере (Web), используя единую кодовую базу.
### 🧩 Ключевые зависимости
- **Управление состоянием и маршрутизация:** `flutter_bloc`, `auto_route`
- **Сетевое взаимодействие:** `dio`, `http`
- **Локальное хранение:** `flutter_secure_storage`, `shared_preferences`, `path_provider`
- **Криптография:**
- Для нативных платформ – `pointycastle`, `encrypt`, `basic_utils`
- Для Web – `webcrypto` (реализация Web Crypto API)
- **Работа с файлами:** `file_picker`, `open_filex`, `flutter_pdfview`, `media_kit`
- **Дополнительно:** `device_info_plus` (генерация идентификатора устройства), `permission_handler`, `qr_flutter`
### 🔐 Криптографическая подсистема
Вся криптография выполняется локально. Приложение никогда не передаёт на сервер незашифрованные данные или приватные ключи.
#### Генерация и управление ключами
- **`RsaKeyGeneratorWeb`** – генерация 2048‑битных пар RSA (для Web и нативных платформ).
- **`KeyManagerService` / `KeyManagerServiceWeb`** – централизованное управление ключами пользователя и устройства:
- Хранение публичных ключей в открытом виде.
- Приватные ключи шифруются паролем пользователя (AES‑GCM, ключ выводится через PBKDF2 с солью).
- Кэширование расшифрованного приватного ключа в памяти на время сессии.
- Отдельные пары ключей для пользователя (для шифрования файлов) и для текущего устройства (для синхронизации зашифрованного пользовательского приватного ключа через сервер).
- **`SecureStorageAdapter`** – адаптер поверх `flutter_secure_storage` и `shared_preferences`:
- На iOS/Android/macOS/Windows/Linux использует защищённое хранилище (Keychain/Keystore).
- В Web данные сохраняются в `SharedPreferences` (с учётом ограничений платформы).
- **`AuthLocalStorage`** – сохранение токенов доступа, информации о пользователе и пароля, зашифрованного мастер‑ключом (AES‑GCM).
#### Формат SHPS
- **`ShirmpsHeader`** – структура заголовка контейнера `.shps` с метаданными, зашифрованным AES‑ключом, IV и цифровой подписью.
- **`ShirmEncryptionService`** (нативный) и **`ShirmEncryptionServiceWeb`** (Web):
- Генерация случайного AES‑256 ключа и 12‑байтного IV.
- Шифрование данных алгоритмом AES‑GCM (аутентифицированное шифрование).
- Зашифрование AES‑ключа публичным RSA‑ключом получателя (OAEP с SHA‑256).
- Опциональная цифровая подпись исходных данных приватным ключом отправителя (SHA256withRSA).
- Формирование итогового `.shps` контейнера: `[4 байта длины заголовка][JSON‑заголовок][зашифрованные данные]`.
- **`ShirmDecryptionService`** и **`ShirmDecryptionServiceWeb`** – обратный процесс с расшифровкой AES‑ключа и данных.
#### Обработка публичных файлов
- **`PublicFileDecryptionService`** – специализированная расшифровка файлов, предназначенных для публичного доступа (когда сервер перешифровывает AES‑ключ на публичный ключ запросившего пользователя).
### 🗂 Локальное кэширование файлов
- **`LocalFileCache`** – сохраняет расшифрованные файлы в директории приложения (`file_cache`) для быстрого повторного доступа без повторной загрузки и расшифровки.
- Для каждого файла сохраняется его оригинальное имя в отдельном файле `.name`.
- Поддерживается очистка кэша и расчёт занимаемого объёма.
- На Web кэширование отключено (ограничения платформы).
### 🔄 Расшифровка файлов «на лету»
- **`FileDecryptionService`** – оркеструет процесс получения файла:
1. Проверка наличия в локальном кэше.
2. Загрузка `.shps` контейнера с сервера (через `FileInterface`).
3. Определение типа файла (приватный или публичный).
4. Расшифровка с использованием приватного ключа пользователя (запрашивается пароль).
5. Сохранение расшифрованных данных в кэш.
### 🌐 Уникальная идентификация устройства
- **`DeviceIdGenerator`** – генерирует стабильный идентификатор устройства на основе аппаратных и системных характеристик (Android ID, identifierForVendor на iOS, machine ID на Linux и т.д.) с хэшированием SHA‑256. Используется для регистрации устройства на сервере и управления ключами синхронизации.
### 🧪 Поддержка Web
Для работы в браузере реализованы отдельные сервисы, использующие `package:webcrypto` (Web Crypto API) вместо `pointycastle`. Это обеспечивает высокую производительность криптографических операций и соответствие стандартам безопасности браузеров.
### 🔒 Принципы безопасности клиента
- Приватные ключи **никогда не покидают устройство в открытом виде**.
- Все криптографические операции выполняются локально.
- Пароль пользователя используется только для расшифровки локального приватного ключа; сервер его не получает.
- Кэшированные файлы хранятся в открытом виде, но доступ к ним ограничен файловой системой приложения.
- Идентификатор устройства не содержит персональных данных, только хэш системных атрибутов.