An open API service indexing awesome lists of open source software.

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‑бэкенд. Доверяйте математике!!

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, уровень компрессии
```

dia

### ⚙️ Процесс шифрования (гибридная схема)

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`. Это обеспечивает высокую производительность криптографических операций и соответствие стандартам безопасности браузеров.

### 🔒 Принципы безопасности клиента

- Приватные ключи **никогда не покидают устройство в открытом виде**.
- Все криптографические операции выполняются локально.
- Пароль пользователя используется только для расшифровки локального приватного ключа; сервер его не получает.
- Кэшированные файлы хранятся в открытом виде, но доступ к ним ограничен файловой системой приложения.
- Идентификатор устройства не содержит персональных данных, только хэш системных атрибутов.