Tài liệu này mô tả chi tiết toàn bộ quy trình mã hóa của Digital Inheritance. Thiết kế ưu tiên tính minh bạch — mọi quyết định kỹ thuật đều có thể được kiểm chứng độc lập.

1. Tổng quan luồng mã hóa

1
Master password + salt_128bitArgon2idAES key 256-bit (key không rời thiết bị)
2
Plaintext payload + nonce_96bit + AAD = user_idAES-256-GCMciphertext + auth_tag_128bit
3
AES key 256-bitShamir SSS trên GF(M521)n SharePacket (mỗi người thừa kế giữ 1)
4
Server lưu: salt · nonce · ciphertext · auth_tag · share_indexkhông có key, không có password, không có share_value

2. Key Derivation — Argon2id

Tham sốGiá trịGhi chú
AlgorithmArgon2idHybrid mode, kháng side-channel
Memory65536 KiB (64 MiB)OWASP High-Security preset
Iterations3time_cost
Parallelism1lanes
Salt128 bits (16 bytes)os.urandom(16), lưu server
Output256 bits (32 bytes)Dùng làm AES key trực tiếp
Libraryargon2-cffi ≥ 23.1Python binding của argon2 C ref
# Pseudocode — key derivation
salt    = os.urandom(16)
aes_key = argon2.hash(
    password   = master_password.encode("utf-8"),
    salt       = salt,
    time_cost  = 3,
    memory_cost= 65536,
    parallelism= 1,
    hash_len   = 32,
    type       = Argon2Type.ID,
)

3. Symmetric Encryption — AES-256-GCM

Tham sốGiá trịGhi chú
AlgorithmAES-256-GCMNIST SP 800-38D
Key size256 bitsOutput từ Argon2id
Nonce (IV)96 bits (12 bytes)os.urandom(12), lưu server
Auth tag128 bits (16 bytes)Lưu kèm ciphertext
AADuser_id (bytes)Chống relocation attack
Librarycryptography ≥ 42.0PyCA cryptography, FIPS-140 backend
# Pseudocode — encryption
nonce   = os.urandom(12)
aesgcm  = AESGCM(aes_key)
ct      = aesgcm.encrypt(nonce, plaintext, aad=user_id.encode())
# ct = ciphertext || auth_tag (16 bytes cuối)

# Decryption (xác thực trước khi giải mã)
plaintext = aesgcm.decrypt(nonce, ct, aad=user_id.encode())
# Raise InvalidTag nếu auth_tag không khớp

4. Secret Sharing — Shamir SSS

Tham sốGiá trịGhi chú
TrườngGF(M521)Prime p = 2^521 − 1 (Mersenne prime)
SecretAES key 256-bitNhúng vào GF(M521) như một số nguyên
Tổng mảnh (n)1 – 10Do người dùng cấu hình
Ngưỡng (k)1 – nCần đúng k mảnh để khôi phục
Khôi phụcLagrange interpolationTính f(0) từ k điểm
Bảo mậtInformation-theoretick-1 mảnh = zero information về secret
# Pseudocode — share generation
M521  = 2**521 - 1
secret = int.from_bytes(aes_key, "big")
# Polynomial: f(x) = secret + a1*x + ... + a(k-1)*x^(k-1)  mod M521
coeffs = [secret] + [randbelow(M521) for _ in range(k-1)]
shares = [(i, poly_eval(coeffs, i, M521)) for i in range(1, n+1)]
# share_value không bao giờ lưu trên server

5. Ghi chú triển khai

6. Tài liệu tham khảo