Mã hoá, tokenization hay làm mờ: chọn đúng công cụ cho từng trường dữ liệu của khách
Buổi review bảo mật hiếm khi xoay quanh thuật toán. Đội bảo mật của khách sẽ hỏi ba điều: ai giữ khoá, ai được thấy gì, và khi cần xoá dữ liệu của một người thì có xoá được không.
Kỹ thuật bảo vệ chỉ đúng khi mỗi trường vẫn có đường để xoá dữ liệu của một người.
Đồ hoạ: FDE Times
Tóm tắt nhanh
- Mỗi trường dữ liệu cần một kỹ thuật riêng. Mã hoá trả lời câu hỏi ai giữ khoá, tokenization trả lời ai giữ bảng ánh xạ, còn làm mờ trả lời ai được thấy gì.
- Envelope encryption với KMS tách khoá khỏi dữ liệu và ghi log mọi lần dùng khoá. Đó là hai điều bạn nên chuẩn bị sẵn để trình bày khi review.
- Tránh xáo trộn và gán null bừa bãi. Pipeline cũng phải xoá được dữ liệu của một người, kể cả sau khi dữ liệu đã bị làm mờ hoặc token hoá.
Thử hình dung tuần thứ hai bạn làm việc tại công ty khách. Pipeline đưa ticket hỗ trợ khách hàng vào một LLM để phân loại đã chạy được, demo cũng suôn sẻ. Rồi đội bảo mật của khách gửi sang một bảng câu hỏi, và câu đầu tiên là: “Số điện thoại của khách hàng đi qua những hệ thống nào, ai đọc được, và khoá nằm ở đâu?”
Nhiều kỹ sư trả lời theo phản xạ: “Bên em mã hoá hết rồi.” Câu đó gần như không trả lời được gì. Đội bảo mật cần biết từng trường được xử lý thế nào, ai giữ khoá và ai được nhìn thấy gì.
Với một FDE, trả lời rõ ràng những câu này nên được coi là phần việc của chính mình, không phải chuyện để riêng đội security lo. Bạn là người hiểu pipeline nhất, nên bạn cũng là người giải thích nó tốt nhất.
Bài này đi qua ba công cụ là mã hoá, tokenization và làm mờ dữ liệu. Ví dụ xuyên suốt là pipeline ticket hỗ trợ ở trên, xét lần lượt từng trường. Cuối bài có danh sách các lỗi thường làm buổi review bảo mật kéo dài thêm vài tuần.
Mỗi công cụ bảo vệ theo một cách khác nhau
Mã hoá giữ dữ liệu nguyên vẹn, chỉ người có khoá mới đọc được. Vì vậy câu hỏi quan trọng nhất về mã hoá là khoá được giữ ở đâu. OWASP khuyến nghị cất khoá mã hoá ở một nơi khác với dữ liệu đã mã hoá, nếu điều kiện cho phép. Lý do đơn giản: nếu khoá nằm ngay cạnh dữ liệu, kẻ đánh cắp ổ đĩa sẽ lấy được cả hai.
Làm mờ (data masking) đi theo hướng ngược lại. Wikipedia định nghĩa đây là việc sửa dữ liệu nhạy cảm để nó không còn hoặc còn rất ít giá trị với người không có quyền truy cập. AWS diễn đạt sát với công việc kỹ thuật hơn: làm mờ là tạo một phiên bản dữ liệu giả nhưng có cấu trúc giống bản thật, để developer và analyst vẫn làm việc được với dữ liệu trông như thật.
Làm mờ có hai kiểu. Làm mờ tĩnh (static masking) áp dụng lên một bản sao của database đã lưu. Bản này thường dùng cho môi trường dev hoặc test. Làm mờ động (dynamic masking) áp dụng lúc truy vấn.
AWS mô tả nó như một bộ lọc: dữ liệu gốc giữ nguyên, phần hiển thị thay đổi theo quyền của người đang xem. Cơ chế này rất hợp với phân quyền theo vai trò trong hệ thống của khách.
Tokenization bảo mật nằm giữa hai cách trên. Trong thiết kế dưới đây, giá trị thật được thay bằng một mã ngẫu nhiên, còn bảng ánh xạ từ mã về giá trị thật được cất ở một nơi riêng và được bảo vệ chặt. Các hệ thống phía sau chỉ nhìn thấy mã, nhưng vẫn join và đếm được theo mã đó.
Hai nghĩa của “tokenization”
Đây là chỗ dân làm AI hay hiểu lầm trong cuộc họp với đội bảo mật. NVIDIA giải thích token trong AI là những đơn vị dữ liệu nhỏ, có được khi chia nhỏ một khối thông tin lớn hơn. Quá trình chuyển dữ liệu đầu vào thành token trước khi model xử lý cũng được gọi là tokenization.
Tokenization theo nghĩa này không bảo vệ được gì. Số điện thoại sau khi qua tokenizer của LLM vẫn là số điện thoại, chỉ bị cắt thành nhiều mảnh. Khi đội bảo mật hỏi “anh có tokenize PII không”, họ đang nói đến nghĩa bảo mật.
Nếu trong pipeline của bạn có cả hai nghĩa, hãy dùng hai tên khác nhau trong tài liệu, chẳng hạn “LLM tokenizer” và “PII token vault”, để không ai nhầm.
Đi từng trường trong pipeline ticket hỗ trợ
Giả sử mỗi ticket có năm trường: mã khách hàng, họ tên, số điện thoại, số thẻ ngân hàng mà khách lỡ dán vào nội dung, và phần mô tả sự cố. Khách hàng của công ty này có người sống ở California.
Văn phòng Tổng chưởng lý California liệt kê một số quyền theo CCPA, trong đó có quyền yêu cầu xoá thông tin cá nhân và quyền hạn chế việc sử dụng, tiết lộ thông tin cá nhân nhạy cảm. IBM cho biết CCPA yêu cầu các biện pháp bảo vệ hợp lý, và mức phạt cho một vi phạm cố ý là 7.500 USD.
Hai quyền này ảnh hưởng trực tiếp đến thiết kế. Quyền xoá nghĩa là pipeline phải tìm và xoá được dữ liệu của một người. Quyền hạn chế nghĩa là bạn phải cân nhắc xem trường nào được phép đi tiếp sang hệ thống phía sau hoặc sang LLM. Áp hai yêu cầu đó vào từng trường, ta có bảng sau:
| Trường | Kỹ thuật | Lý do |
|---|---|---|
| Mã khách hàng | Tokenization | Hệ thống phía sau vẫn cần join; muốn xoá thì xoá dòng ánh xạ |
| Họ tên | Làm mờ động | Nhân viên hỗ trợ thấy tên thật, analyst chỉ thấy tên đã che |
| Số điện thoại | Mã hoá envelope | Có lúc phải gọi lại cho khách nên cần giải ngược được |
| Số thẻ trong nội dung | Phát hiện rồi thay trước khi gửi LLM | Model không cần số thẻ để phân loại sự cố |
| Mô tả sự cố | Làm mờ tĩnh ở bản dev | Kỹ sư cần dữ liệu trông như thật để debug |
Với số điện thoại, cách triển khai chuẩn là envelope encryption. Theo tài liệu của AWS KMS, data key được sinh ra trên HSM và được bảo vệ bởi một KMS key. Data key mã hoá dữ liệu, còn KMS key (đóng vai KEK) bọc lấy data key. Cách này đúng với khuyến nghị tách khoá khỏi dữ liệu của OWASP.
import os, boto3
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
kms = boto3.client("kms")
def encrypt_field(plaintext: bytes, key_id: str) -> dict:
dk = kms.generate_data_key(KeyId=key_id, KeySpec="AES_256")
nonce = os.urandom(12)
ct = AESGCM(dk["Plaintext"]).encrypt(nonce, plaintext, None)
# Chỉ lưu data key ở dạng đã được KMS bọc, không lưu bản rõ
return {"ct": ct, "nonce": nonce, "edk": dk["CiphertextBlob"]}
Cách làm này còn cho bạn một thứ để trình bày trong buổi review. Theo AWS, mọi yêu cầu gửi tới customer managed key đều được ghi lại thành sự kiện CloudTrail. Khi đội bảo mật hỏi “ai đã giải mã số điện thoại tuần trước”, bạn trả lời bằng log, không phải bằng lời hứa.
Với mã khách hàng, điểm mấu chốt khi thiết kế token vault là gắn mỗi token với một chủ sở hữu. Nhờ vậy, khi nhận yêu cầu xoá, bạn tìm được mọi token của người đó trước khi xoá chúng.
import secrets
def tokenize(owner_id: str, value: str, vault) -> str:
token = "tok_" + secrets.token_hex(16)
vault.put(token, owner=owner_id, blob=encrypt_field(value.encode(), KEY_ID))
return token
def forget(owner_id: str, vault, stores) -> None:
tokens = vault.tokens_of(owner_id)
for store in stores: # DB chính, bản dev đã làm mờ, cache
store.delete_where_token_in(tokens)
vault.delete_by_owner(owner_id) # token nào còn sót lại không trỏ về đâu nữa
Thứ tự trong forget là có chủ ý. Bản dev làm mờ tĩnh không giữ tên hay số điện thoại thật, nhưng cột mã khách hàng ở đó được giữ dưới dạng token chứ không bị làm mờ.
Vì thế bạn vẫn tìm ra dòng cần xoá trong bản dev, trong khi các cột đã làm mờ vẫn không thể khôi phục: muốn đi từ token về người thật thì phải qua vault, nơi được bảo vệ chặt.
Năm bước trước buổi review bảo mật
Bước đầu tiên là lập bảng phân loại từng trường như ở trên, kể cả các trường bạn cho là vô hại. Nội dung tự do như phần mô tả sự cố thường chứa những thứ không ai ngờ tới. Bước thứ hai là vẽ đường đi của dữ liệu: mỗi trường xuất hiện ở đâu dưới dạng gốc và ở đâu dưới dạng đã xử lý.
Bước thứ ba là chọn nơi giữ khoá và token vault, tách khỏi kho dữ liệu chính. Tốt nhất là dùng KMS do khách quản lý, để quyền thu hồi khoá nằm trong tay họ.
Bước thứ tư là chứng minh được bằng log: lấy sẵn vài sự kiện CloudTrail mẫu để trình bày. Bước cuối là diễn tập một yêu cầu xoá từ đầu đến cuối, gồm database chính, bản dev đã làm mờ (tìm dòng qua token mã khách hàng), cache và mọi log có chứa prompt gửi sang LLM.
Những lỗi làm đội bảo mật mất tin tưởng
Lỗi đầu tiên là dùng kỹ thuật xáo trộn (shuffling) để làm mờ, tức là đổi chỗ giá trị giữa các dòng. Wikipedia lưu ý cách này có thể bị đảo ngược nếu ai đó tìm ra thuật toán xáo trộn. Dữ liệu đã làm mờ không được phép khôi phục lại được.
Lỗi thứ hai là gán null cho cả cột cho nhanh. Cách này đơn giản, nhưng làm hỏng tính toàn vẹn của dữ liệu và còn để lộ ra rằng cột đó đã bị làm mờ. Bản dev đầy giá trị null cũng khiến kỹ sư không debug được gì, và cuối cùng họ sẽ xin quyền truy cập bản thật.
Lỗi thứ ba là để khoá cạnh dữ liệu, ví dụ data key ở dạng rõ nằm trong file config cùng repo. Lỗi thứ tư là làm mờ luôn cả cột định danh trong bản dev, nên đến lúc nhận yêu cầu xoá thì không biết dòng nào là của ai.
Cách sửa là giữ cột đó ở dạng token như đã nói ở trên: các cột nhạy cảm vẫn bị làm mờ không đảo ngược được, chỉ riêng mối liên kết với chủ sở hữu đi qua vault.
Nếu bạn đang chuẩn bị ứng tuyển FDE, hãy đọc kỹ JD để tìm các từ khoá như “PII”, “KMS”, “data residency” hay “security review”. Trong CV, thay vì viết “có kinh nghiệm bảo mật dữ liệu”, hãy viết một dòng cụ thể như: “Thiết kế envelope encryption và token vault cho pipeline ticket, vượt qua security review của khách, hỗ trợ xoá dữ liệu theo từng khách hàng.”
Kỹ sư biết thuật toán mã hoá thì nhiều. Thứ đội bảo mật cần là người trả lời được, cho từng trường, ba câu hỏi: ai giữ khoá, ai thấy gì, và xoá một người có xoá sạch được không.
7 nguồn
- What Are AI Tokens? The Language and Currency Powering Modern AI · 2025-03-17
- Data masking - Wikipedia
- What is Data Masking? - Static and Dynamic Data Masking Explained - AWS
- Basic concepts - AWS KMS Cryptographic Details
- Cryptographic Storage Cheat Sheet - OWASP
- California Consumer Privacy Act (CCPA) - California Attorney General · 2026-08-28
- What is the California Consumer Privacy Act (CCPA)?