ADR-0003. Mã hoá payload ECDH + AES-256-GCM bắt buộc trên /stream
| Trường | Giá trị |
|---|---|
| Status | Accepted |
| Date | 2026-03-28 |
| Deciders | Phat Nguyen |
| Supersedes | - |
Bối cảnh
- TLS kết thúc tại Traefik; sau đó, lưu lượng đi qua mạng nội bộ và một bus Redis dùng chung.
- Payload WebSocket mang dữ liệu order/payment không nên bị đọc được ở bus hay bởi các kết nối khác cùng dùng chung hạ tầng.
- Chúng ta muốn cô lập khoá theo từng kết nối và đạt forward secrecy mà không cần một service quản lý khoá riêng.
Quyết định
Chúng ta sẽ yêu cầu mã hoá payload đầu-cuối cho mọi kết nối /stream (requireEncryption: true):
- Trong quá trình handshake, client gửi
clientPublicKey; server sinh một cặp khoá ECDH P-256 tạm thời, dẫn xuất một khoá AES-256 qua HKDF-SHA-256, và lưu vào map_clientAesKeystrong bộ nhớ, đánh chỉ mục theo client id. - Server trả
{ serverPublicKey, salt }bên trong sự kiệnconnectedđể client dẫn xuất ra cùng một khoá. - Mọi message sau đó đều là AES-256-GCM
{ iv, ct }. Chỉconnectedvàerrorđược gửi dưới dạng plaintext. - Khoá bị xoá khi ngắt kết nối và mất khi khởi động lại (client kết nối lại để dẫn xuất khoá mới).
Hệ quả
| Ưu | Nhược |
|---|---|
| Payload không đọc được trên đường truyền, ở bus, và với các kết nối khác | Không lưu - khởi động lại buộc mọi client phải kết nối lại |
| Forward secrecy (khoá tạm thời cho mỗi kết nối) | clientPublicKey là bắt buộc - client không hỗ trợ ECDH sẽ bị từ chối |
| Không cần KMS bên ngoài | Map khoá trong bộ nhớ chỉ giới hạn trong một process; phải dựa vào sticky socket + Redis để mở rộng |
Phương án đã cân nhắc
| Phương án | Ưu | Nhược | Vì sao loại |
|---|---|---|---|
| Chỉ TLS (không mã hoá payload) | Đơn giản nhất | Plaintext sau Traefik + trên bus Redis | Không đủ an toàn cho dữ liệu payment |
| Khoá AES tĩnh dùng chung | Không cần handshake | Không có forward secrecy; chỉ một lần rò rỉ là lộ tất cả | Phạm vi ảnh hưởng quá lớn, không chấp nhận được |
| mTLS theo từng client | Định danh mạnh | Quản lý vòng đời cert nặng nề trên client POS/Tauri | Bất khả thi về vận hành cho cả đội client |
Tham chiếu
signal/src/components/websocket.component.ts(ECDH, handshake, transformer cho luồng đi ra, handler xử lý message)- Encryption
- Operations - bảo mật