Jak działa szyfrowanie

SG/Send wykorzystuje symetryczne szyfrowanie AES-256-GCM, wykonywane w całości w przeglądarce. Serwer nigdy nie widzi danych w postaci jawnej, nazw plików ani kluczy szyfrowania. Ta strona wyjaśnia dokładnie, jak to działa.

Szyfrowanie symetryczne: jeden klucz, dwie operacje

SG/Send używa szyfrowania symetrycznego — ten sam klucz szyfruje i deszyfruje plik. Jest to najprostszy i najszybszy model szyfrowania, a przy prawidłowej implementacji — najbezpieczniejszy do transferu plików.

Czym jest AES-256-GCM?

AES (Advanced Encryption Standard) to algorytm szyfrowania używany przez rządy, banki i siły zbrojne na całym świecie. 256 to rozmiar klucza w bitach — istnieje 2256 możliwych kluczy, co czyni atak siłowy obliczeniowo niemożliwym. GCM (Galois/Counter Mode) dodaje szyfrowanie uwierzytelnione — nie tylko szyfruje, ale także wykrywa, czy ktoś manipulował tekstem zaszyfrowanym.

Dlaczego symetryczne?

Szyfrowanie symetryczne używa jednego klucza zarówno do szyfrowania, jak i deszyfrowania. Różni się to od szyfrowania asymetrycznego (jak RSA), które używa pary kluczy. Do transferu plików szyfrowanie symetryczne jest właściwym wyborem: jest szybkie, dobrze poznane, a Web Crypto API zapewnia sprawdzoną implementację w każdej nowoczesnej przeglądarce.

Kluczowa obserwacja: jeśli kontrolujesz, gdzie klucz jest generowany i dokąd trafia, szyfrowanie symetryczne zapewnia doskonałą poufność. SG/Send generuje klucz w przeglądarce, a klucz nigdy nie dotyka serwera.

Przepływ szyfrowania: krok po kroku

Oto dokładnie, co się dzieje, gdy wysyłasz plik przez SG/Send.

1

Generowanie klucza

Po wybraniu pliku przeglądarka generuje losowy 256-bitowy klucz AES za pomocą Web Crypto API (crypto.subtle.generateKey). Wykorzystywany jest kryptograficznie bezpieczny generator liczb losowych systemu operacyjnego. Klucz istnieje wyłącznie w pamięci przeglądarki.

Browser Server | | | crypto.subtle.generateKey( | | { name: "AES-GCM", length: 256 }, | | true, | | ["encrypt", "decrypt"] | | ) | | | | Key generated: 3a7f...b2c1 (256 bits) | | Key stays here. Server knows nothing. | | |
2

Generowanie IV

Losowo generowany jest 12-bajtowy wektor inicjalizacji (IV) (crypto.getRandomValues). IV zapewnia, że zaszyfrowanie tego samego pliku dwukrotnie da różny tekst zaszyfrowany. IV nie jest tajny — jest dołączany przed zaszyfrowanym wyjściem i wysyłany wraz z tekstem zaszyfrowanym.

3

Szyfrowanie

Plik jest szyfrowany w przeglądarce za pomocą crypto.subtle.encrypt z algorytmem AES-GCM, wygenerowanym kluczem i IV. Wynikiem jest tekst zaszyfrowany + 128-bitowy tag uwierzytelnienia. Tag uwierzytelnienia to gwarancja integralności GCM — jeśli ktoś zmodyfikuje choćby jeden bit tekstu zaszyfrowanego, deszyfrowanie się nie powiedzie.

Browser Server | | | plaintext ──► AES-256-GCM ──► ciphertext | | ▲ | | | | | key + IV | | | | Output = IV (12 bytes) | | + ciphertext (same size as plaintext) | | + auth tag (16 bytes) | | |
4

Wysyłanie

Na serwer wysyłane jest wyłącznie zaszyfrowane wyjście (IV + tekst zaszyfrowany + tag uwierzytelnienia). Serwer otrzymuje blok losowo wyglądających bajtów. Przypisuje ID transferu (12 losowych znaków) i zapisuje tekst zaszyfrowany. Brak nazwy pliku, brak wskazówki o typie zawartości, brak klucza — tylko zaszyfrowane bajty.

Browser Server | | | POST /transfers/create | | ──────────────────────────────────────────► | | | Stores: | PUT /transfers/{id}/upload | transfer_id: "a7x9k2m4p1" | Body: [IV + ciphertext + auth tag] | data: [encrypted bytes] | ──────────────────────────────────────────► | ip_hash: SHA256(ip + salt) | | timestamp: 2026-02-28T... | Key NEVER sent. File name NEVER sent. | | |
5

Udostępnianie linku

Nadawca otrzymuje link do pobrania. Klucz deszyfrowania jest umieszczany we fragmencie URL (części po #). Fragmenty URL nigdy nie są wysyłane na serwer przez przeglądarkę — jest to zdefiniowane w RFC 3986. Nadawca udostępnia ten link dowolnym kanałem (e-mail, czat, osobiście).

Link format: https://send.sgraph.ai/download/a7x9k2m4p1#3a7f...b2c1 ├──────────── domain ────────────┤├─ transfer id ─┤├─ key ─┤ ▲ │ URL fragment (#) Never sent to server Stays in the browser
6

Deszyfrowanie

Odbiorca otwiera link. Jego przeglądarka pobiera zaszyfrowane bajty z serwera, wyodrębnia klucz z fragmentu URL, oddziela IV od tekstu zaszyfrowanego i deszyfruje za pomocą crypto.subtle.decrypt. Jeśli tag uwierzytelnienia nie pasuje (wykryto manipulację), deszyfrowanie się nie powiedzie. Serwer nigdy nie uczestniczy w deszyfrowaniu.

Recipient's Browser Server | | | GET /transfers/{id}/download | | ──────────────────────────────────────────► | | ◄────────────────────────────────────────── | | Response: [IV + ciphertext + auth tag] | | | | Key extracted from URL fragment (#) | | crypto.subtle.decrypt( | | { name: "AES-GCM", iv: IV }, | | key, | | ciphertext | | ) | | | | ──► plaintext file restored | | Server never saw the key or the plaintext. |

Co serwer widzi, a czego nie

To jest gwarancja zero-knowledge. Oto dokładnie, jakie dane istnieją na serwerze.

Serwer przechowuje

ID transferu — losowe 12 znaków
Zaszyfrowane bajty — nierozróżnialne od losowych danych
Hash IP — SHA-256 adresu IP + dziennie rotowany salt
Znacznik czasu — kiedy transfer został utworzony
Rozmiar pliku — rozmiar zaszyfrowanego bloba (bajty)

Serwer nigdy nie widzi

Klucz szyfrowania — pozostaje w przeglądarce, udostępniany przez fragment URL
Nazwa pliku — nigdy nie jest wysyłana na serwer
Typ pliku — brak przechowywanych metadanych content-type
Treść jawna — wysyłany jest wyłącznie tekst zaszyfrowany
Surowy adres IP — haszowany przed zapisem

Pełne skompromitowanie serwera — pełny dostęp do bazy danych, wszystkie kopie zapasowe, wszystkie logi — nie ujawnia nic o treści przesyłanych plików. Tekst zaszyfrowany jest obliczeniowo nierozróżnialny od losowego szumu bez klucza.

Stos technologiczny

Każda warstwa została wybrana pod kątem prostoty, bezpieczeństwa i wdrożenia bez zależności.

Warstwa Technologia Przeznaczenie
Środowisko uruchomieniowe Python 3.12 / arm64 Język serwera aplikacyjnego
Framework webowy FastAPI via osbot-fast-api Routing HTTP i obsługa żądań
Compute AWS Lambda + Mangum Wykonywanie serverless, płatność za użycie
Magazyn danych Memory-FS (Storage_FS) Wymienny backend: pamięć, dysk lub S3
Szyfrowanie Web Crypto API (AES-256-GCM) Szyfrowanie po stronie klienta w przeglądarce
System typów Type_Safe (osbot-utils) Definicje schematów bez Pydantic
Frontend Vanilla JS + Web Components Zero zależności od frameworków (IFD)
Testy pytest, stos in-memory Bez mocków, bez patchów, prawdziwe implementacje
CI/CD GitHub Actions Pipeline testów, tagowania i wdrożeń

Architektura systemu

Dwie funkcje Lambda, jedna warstwa magazynowa, jeden CDN. Proste z założenia.

User Lambda (publiczne)

Publiczna funkcja obsługująca transfery plików, kontrole integralności, przesyłanie presigned, osobiste sejfy i integrację MCP. Dostęp przez Lambda Function URL za CloudFront.

18 punktów końcowych

Admin Lambda (uwierzytelnione)

Funkcja wyłącznie administracyjna do zarządzania tokenami, analityki, statystyk serwera i narzędzi administracyjnych MCP. Wymaga uwierzytelnienia. Osobne Lambda = osobna granica bezpieczeństwa.

55 punktów końcowych

Memory-FS (Storage_FS)

Każdy dostęp do magazynu odbywa się przez warstwę abstrakcji. Kod aplikacji nie wie, czy backend jest w pamięci, na dysku czy w S3. Ta sama baza kodu na wszystkie 7 celów wdrożeniowych.

Wymienny backend

CloudFront CDN

Zasoby statyczne, caching, terminacja SSL i WAF. Lambda URLs udostępniają punkty końcowe HTTPS bezpośrednio — bez potrzeby API Gateway.

Sieć edge

Cele wdrożeniowe

Jedna baza kodu, siedem celów wdrożeniowych zgrupowanych w cztery wzorce.

Lambda

Główne wdrożenie. Dwie funkcje Lambda za Lambda Function URLs. Bezpośrednie punkty końcowe HTTPS, bez potrzeby API Gateway.

Produkcja

Kontener

Docker, AWS Fargate i GCP Cloud Run. Ta sama aplikacja spakowana jako kontener.

Docker / Fargate / GCP

Serwer

Instancje EC2 i buildy AMI. Dla zespołów, które potrzebują pełnej kontroli nad środowiskiem uruchomieniowym.

EC2 / AMI

CLI

Interfejs wiersza poleceń do skryptowanych transferów, pipeline’ów CI/CD i zaawansowanych użytkowników.

Terminal
18
Agenci AI
73
Punkty końcowe HTTP
393
Zaliczone testy
7
Cele wdrożeniowe