Watch the lesson video: Bảo mật Tác nhân AI với Biên lai Mã hóa
(Video bài học và ảnh thu nhỏ sẽ được nhóm nội dung Microsoft thêm vào sau khi gộp, theo mẫu bài học 14 / 15.)
Bài học này sẽ đề cập đến:
Sau khi hoàn thành bài học này, bạn sẽ biết cách:
Hãy tưởng tượng bạn đã triển khai một tác nhân AI cho Contoso Travel. Tác nhân đọc yêu cầu khách hàng, gọi API chuyến bay để tra cứu lựa chọn và đặt chỗ thay cho khách hàng. Quý trước, tác nhân đã xử lý 50.000 đặt chỗ.
Hôm nay, một kiểm toán viên đến. Họ hỏi một câu đơn giản: “Cho tôi xem tác nhân của bạn đã làm gì.”
Bạn giao các tập tin nhật ký cho họ. Kiểm toán viên xem qua và hỏi câu khó hơn: “Làm sao tôi biết các nhật ký này chưa bị chỉnh sửa?”
Đây là vấn đề dấu vết kiểm tra. Hầu hết các triển khai tác nhân hiện nay dựa vào:
Không phương pháp nào trong số này trả lời được câu hỏi của kiểm toán viên nếu không yêu cầu kiểm toán viên tin tưởng ai đó (bạn, nhà cung cấp đám mây, nhà cung cấp cơ sở dữ liệu). Đối với sử dụng nội bộ, sự tin tưởng đó thường được chấp nhận. Đối với các khối lượng công việc có quy định (tài chính, chăm sóc sức khỏe, bất cứ thứ gì chịu Luật AI EU), thì không.
Biên lai mã hóa giải quyết vấn đề này bằng cách làm cho mỗi hành động của tác nhân trở nên có thể xác minh độc lập. Kiểm toán viên không cần tin bạn. Họ chỉ cần khóa công khai của bạn và biên lai đó.
Biên lai là một đối tượng JSON ghi lại những gì tác nhân đã làm, có chữ ký số.
flowchart LR
A[Đại lý gọi một công cụ] --> B[Xây dựng dữ liệu biên lai]
B --> C[Chuẩn hóa JSON RFC 8785]
C --> D[Băm SHA-256]
D --> E[Ký Ed25519]
E --> F[Biên lai có chữ ký]
F --> G[Kiểm toán viên xác minh offline]
G --> H{Chữ ký hợp lệ?}
H -- có --> I[Bằng chứng chống giả mạo]
H -- không --> J[Biên lai bị từ chối]
Một biên lai tối giản trông như sau:
{
"type": "agent.tool_call.v1",
"agent_id": "contoso-travel-bot",
"tool_name": "lookup_flights",
"tool_args_hash": "sha256:a3f9c1...",
"result_hash": "sha256:7b2e1d...",
"policy_id": "contoso-travel-policy-v3",
"timestamp": "2026-04-25T14:30:00Z",
"sequence": 47,
"previous_receipt_hash": "sha256:9d4e6a...",
"signature": {
"alg": "EdDSA",
"sig": "c5af83...",
"public_key": "8f3b2c..."
}
}
Ba thuộc tính làm nên tính năng:
Chữ ký. Biên lai được ký bởi gateway của tác nhân bằng khóa riêng Ed25519. Bất cứ ai có khóa công khai tương ứng có thể xác minh chữ ký ngoại tuyến. Sửa đổi bất kỳ trường nào làm chữ ký không hợp lệ.
Mã hóa chuẩn hóa. Trước khi ký, biên lai được tuần tự hóa dùng JSON Canonicalization Scheme (JCS, RFC 8785). Điều này đảm bảo hai triển khai tạo ra cùng một biên lai logic sẽ sản xuất dữ liệu byte giống hệt nhau. Nếu không chuẩn hóa, các trình tuần tự JSON khác nhau sẽ tạo ra các chữ ký khác nhau cho cùng nội dung.
Chuỗi băm. Trường previous_receipt_hash liên kết mỗi biên lai với biên lai trước đó. Việc xóa hoặc thay đổi thứ tự một biên lai sẽ phá vỡ tất cả các biên lai tiếp theo. Việc giả mạo trở nên hiển nhiên ở mức chuỗi ngay cả khi các chữ ký riêng lẻ bị bỏ qua.
Ba thuộc tính này cùng đảm bảo ba điều:
Bạn không cần thư viện đặc biệt để tạo biên lai. Các hàm mật mã cơ bản rất phổ biến và logic chỉ là vài chục dòng Python.
Các bài tập thực hành trong code_samples/18-signed-receipts.ipynb hướng dẫn toàn bộ quy trình. Phiên bản tóm tắt:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # JSON chuẩn RFC 8785
def b64url_nopad(data: bytes) -> str:
return base64.urlsafe_b64encode(data).decode("ascii").rstrip("=")
def sha256_canonical(obj) -> str:
"""SHA-256 of a Python object's JCS-canonical JSON form."""
return f"sha256:{hashlib.sha256(canonicalize(obj)).hexdigest()}"
# Tạo hoặc tải khóa ký (trong môi trường sản xuất, lưu trong kho khóa)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Xây dựng payload biên nhận (chưa ký)
tool_args = {"origin": "SYD", "destination": "LAX"}
tool_result = [{"flight": "QF11", "price": 1850, "stops": 0}]
payload = {
"type": "agent.tool_call.v1",
"agent_id": "contoso-travel-bot",
"tool_name": "lookup_flights",
"tool_args_hash": sha256_canonical(tool_args),
"result_hash": sha256_canonical(tool_result),
"policy_id": "contoso-travel-policy-v3",
"timestamp": "2026-04-25T14:30:00Z",
"sequence": 0,
"previous_receipt_hash": None,
}
# Chuẩn hóa, băm, ký.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Đính kèm đối tượng chữ ký có cấu trúc.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
Đó là toàn bộ pipeline ký. Các bài tập trong sổ tay sẽ đi qua từng bước.
Xác minh là thao tác ngược lại:
import base64
import hashlib
from nacl import signing
from nacl.exceptions import BadSignatureError
from jcs import canonicalize
def b64url_decode(s: str) -> bytes:
padding = "=" * ((4 - len(s) % 4) % 4)
return base64.urlsafe_b64decode(s + padding)
def verify_receipt(receipt: dict) -> bool:
# Chữ ký là một đối tượng có cấu trúc: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Tái tạo lại phần payload đã được ký thực tế (mọi thứ ngoại trừ chữ ký).
payload = {k: v for k, v in receipt.items() if k != "signature"}
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
try:
verify_key = signing.VerifyKey(b64url_decode(sig_obj["public_key"]))
verify_key.verify(message_hash, b64url_decode(sig_obj["sig"]))
return True
except BadSignatureError:
return False
Hàm này nhận một biên lai và trả về True nếu chữ ký hợp lệ, False nếu không. Không gọi mạng, không phụ thuộc dịch vụ, không cần tin tưởng bên thứ ba nào.
Để thấy việc phát hiện giả mạo vận hành thế nào, sổ tay hướng dẫn:
tool_args_hash.Đây là minh chứng thực tế rằng biên lai phát hiện giả mạo: bất kỳ sửa đổi nào dù nhỏ làm chữ ký không hợp lệ.
Một biên lai ký bảo vệ một hành động. Một chuỗi biên lai bảo vệ cả chuỗi hành động.
flowchart LR
R0[Biên nhận 0<br/>khởi nguyên] --> R1[Biên nhận 1]
R1 --> R2[Biên nhận 2]
R2 --> R3[Biên nhận 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Mỗi biên lai ghi lại băm của biên lai trước đó. Để lặng lẽ xóa biên lai số 2, kẻ tấn công sẽ cần:
previous_receipt_hash của biên lai 3 (phá vỡ chữ ký biên lai 3), HOẶCNếu khóa riêng nằm trong khoá phần cứng và bạn công bố khóa công khai với mỗi biên lai, thì không thể thực hiện hai cuộc tấn công đó mà không bị phát hiện.
Sổ tay thực hiện:
previous_receipt_hash của mỗi biên lai khớp với băm thực tế của biên lai trước đó.Đây là cách bạn tạo dấu vết kiểm tra để kiểm toán viên bên ngoài có thể xác minh mà không cần tin bạn.
Đây là phần quan trọng nhất của bài học. Biên lai rất mạnh nhưng sức mạnh có giới hạn.
Biên lai chứng minh ba điều:
Biên lai KHÔNG chứng minh:
policy_id đã được đánh giá, hay rằng chính sách đó sẽ cho phép hành động này nếu được kiểm tra. Biên lai ghi lại những điều đã tuyên bố, không phải những điều được thi hành.Ranh giới này quan trọng vì hai lý do:
Một lỗi phổ biến là cho rằng “chúng ta có biên lai” nghĩa là “chúng ta có quản trị.” Không phải vậy. Biên lai là nền tảng. Quản trị là hệ thống bạn xây dựng trên nền tảng đó.
Mã Python trong bài học này được thiết kế tối giản để bạn có thể đọc từng dòng và hiểu rõ điều xảy ra. Trong sản xuất, bạn có hai lựa chọn:
Xây dựng trực tiếp trên các hàm mật mã cơ bản. 50 dòng bạn thấy ở trên đủ cho nhiều trường hợp sử dụng. PyNaCl (Ed25519) và gói jcs (JSON chuẩn hóa) là thư viện được duy trì và kiểm tra tốt.
Dùng thư viện biên lai sản xuất. Một số dự án mã nguồn mở thực hiện mẫu tương tự với các tính năng bổ sung (đổi khóa, xác minh hàng loạt, phân phối bộ JWK, tích hợp với động cơ chính sách):
draft-farley-acta-signed-receipts) đang trong quá trình chuẩn hóa.protect-mcp (npm) và @veritasacta/verify (npm) cung cấp triển khai trên Node của việc ký biên lai và xác minh ngoại tuyến, dùng để bao quanh bất kỳ máy chủ MCP nào với dấu vết kiểm toán phát hiện giả mạo.pip install nobulex) cung cấp mẫu ký Ed25519 + JCS tương tự trong Python với tích hợp LangChain và CrewAI, bao gồm vector kiểm tra ngang và bản đồ tuân thủ đóng góp qua OWASP PR #2210.Việc lựa chọn tự viết hoặc dùng thư viện tương tự như quyết định giữa viết thư viện JWT riêng và dùng thư viện đã kiểm thử: cả hai đều hợp lý; thư viện tiết kiệm thời gian và giảm bề mặt kiểm toán; viết từ đầu buộc bạn hiểu mọi hàm cơ bản. Bài học này dạy từ đầu để bạn có nền tảng cho cả hai lựa chọn.
Kiểm tra hiểu biết của bạn trước khi chuyển sang bài tập thực hành.
1. Biên lai được ký bằng khóa riêng Ed25519 của tác nhân. Kiểm toán viên chỉ có khóa công khai. Liệu kiểm toán viên có thể xác minh biên lai ngoại tuyến không?
2. Kẻ tấn công sửa đổi trường policy_id trong biên lai để tuyên bố nó chịu chính sách ít nghiêm ngặt hơn. Chữ ký là trên payload gốc. Điều gì xảy ra khi xác minh?
3. Tại sao biên lai lại bao gồm tool_args_hash và result_hash thay vì các đối số và kết quả thô?
4. Trường previous_receipt_hash liên kết mỗi biên lai với biên lai trước đó. Nếu kẻ tấn công âm thầm xóa một biên lai ở giữa chuỗi, điều gì trở nên không hợp lệ?
5. Biên lai xác minh sạch. Liệu điều đó có chứng minh hành động của tác nhân là đúng, hợp lý, hoặc tuân thủ chính sách không?
Mở code_samples/18-signed-receipts.ipynb và hoàn thành bốn phần sau:
Thử thách nâng cao 2: Băm SHA-256 hai biên lai của bạn với nhau (nối byte chuẩn của chúng theo thứ tự xác định được) và nhúng giá trị băm kết quả như một trường mới trên biên lai thứ ba trước khi ký nó. Xác nhận tất cả ba biên lai vẫn xác minh hai chiều được. Bạn vừa xây dựng một bằng chứng bao hàm một bước: bất kỳ ai có biên lai thứ ba đều có thể chứng minh biên lai thứ nhất và thứ hai đã tồn tại vào thời điểm nó được ký, mà không cần phải tiết lộ nội dung. Đây là mô hình mà biên lai tiết lộ chọn lọc sử dụng ở quy mô lớn (Cam kết Merkle, RFC 6962).
Biên lai mã hóa cung cấp cho các đại lý AI một dấu vết kiểm toán:
Chúng không thay thế cho việc kiểm tra đầu vào, thực thi chính sách, hoặc hạ tầng nhận dạng. Chúng là nền tảng cho những lớp đó. Khi bạn triển khai đại lý vào các khối công việc có quy định, luồng công việc đa tổ chức, hoặc bất kỳ môi trường nào mà người kiểm toán tương lai không thể cho là tin tưởng bạn, biên lai là cách bạn làm cho dấu vết kiểm toán trở nên trung thực.
Điều quan trọng nhất cần ghi nhớ: biên lai chứng minh ai đã nói gì, khi nào. Chúng không chứng minh rằng những gì được nói là đúng hay chính xác. Hãy giữ sự phân biệt đó rõ ràng. Đó là sự khác biệt giữa một hệ thống xuất xứ trung thực và một hệ thống gây hiểu lầm.
Khi bạn sẵn sàng ra khỏi bài học này để triển khai đại lý ký biên lai trong môi trường thực:
https://your-org.example.com/.well-known/agent-keys.json.Tham gia Microsoft Foundry Discord để gặp gỡ các học viên khác, tham dự giờ tư vấn, và giải đáp thắc mắc về đại lý AI.
Bài học này đề cập đến ký một biên lai đơn và chuỗi băm nối tiếp. Các nguyên thủy tương tự phối hợp thành nhiều mô hình nâng cao mà bạn có thể gặp khi chính sách quản trị của bạn trưởng thành:
authorization_*) và sau thực thi (result_*) với chữ ký riêng biệt, hữu ích khi quyết định ủy quyền và kết quả quan sát do các tác nhân khác nhau tạo ra hoặc tại các thời điểm khác nhau. Điều này thêm vào cấu trúc biên lai được dạy trong bài học này.result_hash. Tải trọng thế giới thực thường phong phú hơn kết quả lệnh đơn giản: lý luận trước quyết định (dự đoán mô hình, các lựa chọn đã xem xét, bằng chứng và mức độ đầy đủ, tư thế rủi ro, chuỗi trách nhiệm, kết quả kiểm soát) đều có thể nằm trong tải trọng, niêm phong trong một biên lai duy nhất. Điều này giữ định dạng biên lai tối giản trong khi cho phép các lược đồ tải trọng tiến hóa theo từng lĩnh vực.signature.alg có thể mang ML-DSA-65 (chuẩn chữ ký hậu lượng tử của NIST) khi bạn cần di cư. Lên kế hoạch cho giai đoạn chuyển tiếp với biên lai ký kép.Khởi tạo Đại Lý Sử Dụng Máy Tính (CUA)
(Được xác định bởi người quản lý chương trình học)
Tuyên bố miễn trừ trách nhiệm: Tài liệu này đã được dịch bằng dịch vụ dịch thuật AI Co-op Translator. Mặc dù chúng tôi cố gắng đảm bảo độ chính xác, xin lưu ý rằng bản dịch tự động có thể chứa lỗi hoặc sai sót. Tài liệu gốc bằng ngôn ngữ gốc nên được coi là nguồn tin chính thức. Đối với thông tin quan trọng, nên sử dụng dịch vụ dịch thuật chuyên nghiệp bởi con người. Chúng tôi không chịu trách nhiệm về bất kỳ hiểu lầm hoặc giải thích sai nào phát sinh từ việc sử dụng bản dịch này.