Skip to content

ADR-0003. Mã hóa AES-256-GCM cho credential nhà cung cấp khi lưu trữ

TrườngGiá trị
Trạng tháiAccepted
Ngày2026-02-12
Người quyết địnhpayment-team, security
Thay thế

Bối cảnh

  • Credential nhà cung cấp thanh toán (VNPAY appId/secrets, token theo merchant) có độ nhạy cảm cao — rò rỉ cho phép thanh toán trái phép.
  • Lưu trữ chúng dạng plaintext trong bảng Configuration là không chấp nhận được.
  • Chúng tôi cần cân bằng giữa bảo mật và tính đơn giản vận hành (chúng tôi chưa ở quy mô yêu cầu HSM/KMS).

Quyết định

Tất cả credential thanh toán được mã hóa khi lưu trữ bằng AES-256-GCM qua CryptoUtility (từ @nx/core). Khóa mã hóa được dẫn xuất từ APP_ENV_APPLICATION_SECRET.

Chi tiết:

  • Cột Configuration.credential được ẩn khỏi các thao tác đọc CRUD chuẩn (drizzle hidden field).
  • PaymentConfigurationService.getPaymentCredential truy cập cột trực tiếp qua drizzle connector và giải mã inline.
  • Cùng secret mã hóa các config payment không phải credential trong tValue (ví dụ masterMerchantCode, appId của VNPAY).
  • Tất cả pod (API + WORKER) PHẢI chia sẻ APP_ENV_APPLICATION_SECRET.

Hệ quả

Ưu điểmNhược điểm
Chỉ có dump database không làm rò rỉ credentialMô hình một secret — rò rỉ secret = compromise toàn bộ
Mã hóa xác thực (chế độ GCM) ngăn tamperingXoay vòng secret yêu cầu mã hóa lại mọi row credential (thủ công)
Giải mã in-process — sub-millisecondKhông có cô lập KMS theo từng merchant
Primitive tiêu chuẩn, đã được audit kỹApp secret phải lưu trong K8s secret với RBAC nghiêm ngặt

Quy trình xoay vòng

  1. Sinh secret mới.
  2. Đọc tất cả row Configuration có credential, giải mã bằng secret cũ.
  3. Mã hóa lại bằng secret mới.
  4. Roll deployment với env mới.

Việc xoay vòng PHẢI được điều phối — không có trạng thái half-rolled nơi các pod có secret khác nhau.

Phương án thay thế đã cân nhắc

Lựa chọnƯu điểmNhược điểmLý do từ chối
HashiCorp Vault / AWS KMSKhóa per-credential, xoay vòng tích hợp sẵnVendor lock-in, chi phí ops, độ trễQuá sớm cho quy mô của chúng tôi
Bất đối xứng (RSA per merchant)Cô lập theo merchantPhức tạp; bùng nổ khóaKhông cần thiết với threat model hiện tại
Plaintext + DB ACLĐơn giảnKhông chấp nhận được — DB ops có thể đọc credentialKhông

Tham chiếu

  • core/src/utilities/crypto.utility.ts (CryptoUtility)
  • services/payment-configuration.service.ts:43-176 (vị trí giải mã)
  • core/src/models/schemas/public/configuration/schema.ts (cột credential hidden)

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.