Tonton video pelajaran: Mengamankan Agen AI dengan Resi Kriptografi
(Video pelajaran dan thumbnail akan ditambahkan oleh tim konten Microsoft setelah penggabungan, sesuai pola pelajaran 14 / 15.)
Pelajaran ini akan membahas:
Setelah menyelesaikan pelajaran ini, Anda akan tahu cara:
Bayangkan Anda telah menerapkan agen AI untuk Contoso Travel. Agen tersebut membaca permintaan pelanggan, memanggil API penerbangan untuk mencari opsi, dan memesan kursi atas nama pelanggan. Kuartal lalu, agen memproses 50.000 pemesanan.
Hari ini auditor datang. Mereka mengajukan pertanyaan sederhana: “Tunjukkan apa yang dilakukan agen Anda.”
Anda menyerahkan berkas log Anda. Auditor melihatnya dan mengajukan pertanyaan yang lebih sulit: “Bagaimana saya tahu log ini tidak diedit?”
Inilah masalah jejak audit. Sebagian besar penerapan agen saat ini bergantung pada:
Tidak satupun dari ini dapat menjawab pertanyaan auditor tanpa mengharuskan auditor mempercayai seseorang (Anda, penyedia cloud Anda, vendor basis data Anda). Untuk penggunaan internal, kepercayaan itu seringkali dapat diterima. Untuk beban kerja yang diatur (keuangan, kesehatan, apa pun yang tunduk pada EU AI Act), tidak demikian.
Resi kriptografi menyelesaikan ini dengan membuat setiap tindakan agen dapat diverifikasi secara independen. Auditor tidak perlu mempercayai Anda. Mereka hanya memerlukan kunci publik Anda dan resi itu sendiri.
Resi adalah objek JSON yang mencatat apa yang dilakukan agen, ditandatangani dengan tanda tangan digital.
flowchart LR
A[Agen memanggil alat] --> B[Bangun payload tanda terima]
B --> C[Kanonisasi JSON RFC 8785]
C --> D[Hash SHA-256]
D --> E[Tanda tangan Ed25519]
E --> F[Tanda terima dengan tanda tangan]
F --> G[Auditor memverifikasi secara offline]
G --> H{Apakah tanda tangan valid?}
H -- yes --> I[Bukti anti-pemalsuan]
H -- no --> J[Tanda terima ditolak]
Resi minimal terlihat seperti ini:
{
"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..."
}
}
Tiga properti yang melakukan pekerjaan ini:
Tanda tangan. Resi ditandatangani oleh gateway agen menggunakan kunci pribadi Ed25519. Siapa pun yang memiliki kunci publik yang sesuai dapat memverifikasi tanda tangan secara offline. Manipulasi pada bidang apa pun membuat tanda tangan menjadi tidak valid.
Pengodean kanonik. Sebelum penandatanganan, resi diserialisasikan menggunakan Skema Kanonisasi JSON (JCS, RFC 8785). Ini memastikan dua implementasi yang menghasilkan resi logis yang sama menghasilkan keluaran byte-identik. Tanpa kanonisasi, serializer JSON yang berbeda akan menghasilkan tanda tangan yang berbeda untuk konten yang sama.
Pengikatan hash berantai. Bidang previous_receipt_hash menghubungkan setiap resi ke yang sebelumnya. Menghapus atau mengurut ulang resi merusak setiap resi yang datang setelahnya. Manipulasi menjadi terlihat pada tingkat rantai meskipun tanda tangan individual dilewati.
Bersama-sama properti ini memberikan tiga jaminan:
Anda tidak perlu pustaka khusus untuk membuat resi. Primitif kriptografi tersedia luas dan logikanya hanya beberapa puluh baris Python.
Latihan langsung di code_samples/18-signed-receipts.ipynb menjelaskan keseluruhan alur. Versi ringkasnya:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # JSON kanonik 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()}"
# Hasilkan atau muat kunci penandatanganan (di produksi, simpan di brankas kunci)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Bangun muatan tanda terima (belum ada tanda tangan)
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,
}
# Kanonisasi, hash, tanda tangani.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Lampirkan objek tanda tangan terstruktur.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
Itu adalah seluruh jalur penandatanganan. Latihan di notebook menjelaskan setiap langkah.
Verifikasi adalah operasi kebalikan:
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:
# Tanda tangan adalah objek terstruktur: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Rekonstruksi payload yang benar-benar ditandatangani (semua kecuali tanda tangan).
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
Fungsi ini mengambil resi dan mengembalikan True jika tanda tangan valid, False jika tidak. Tidak ada panggilan jaringan, tidak ada ketergantungan layanan, tidak perlu mempercayai pihak ketiga.
Untuk melihat deteksi manipulasi secara langsung, notebook menjelaskan:
tool_args_hash.Ini adalah demonstrasi praktis bahwa resi tahan manipulasi: modifikasi apa pun, sekecil apa pun, merusak tanda tangan.
Satu resi bertanda tangan melindungi satu tindakan. Rantai resi melindungi urutan tindakan.
flowchart LR
R0[Tanda Terima 0<br/>awal] --> R1[Tanda Terima 1]
R1 --> R2[Tanda Terima 2]
R2 --> R3[Tanda Terima 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Setiap resi mencatat hash dari resi sebelumnya. Untuk menghapus resi 2 secara diam-diam, penyerang harus:
previous_receipt_hash dari resi 3 (merusak tanda tangan resi 3), ATAUJika kunci pribadi berada dalam kotak kunci perangkat keras dan Anda mempublikasikan kunci publik dengan setiap resi, kedua serangan tersebut tidak dapat dilakukan tanpa terdeteksi.
Notebook menjelaskan:
previous_receipt_hash dari setiap resi cocok dengan hash riil dari resi sebelumnya.Inilah cara menghasilkan jejak audit yang dapat diverifikasi auditor eksternal tanpa harus mempercayai Anda.
Ini adalah bagian terpenting dari pelajaran ini. Resi sangat kuat tetapi kekuatannya terbatas.
Resi membuktikan tiga hal:
Resi TIDAK membuktikan:
policy_id benar-benar dievaluasi, atau bahwa kebijakan tersebut akan mengizinkan tindakan ini jika diperiksa. Resi mencatat apa yang diklaim, bukan yang ditegakkan.Batas ini penting karena dua alasan:
Kesalahan umum adalah mengira bahwa “kami memiliki resi” berarti “kami diatur.” Tidak demikian. Resi adalah fondasi. Tata kelola adalah sistem yang Anda bangun di atasnya.
Poin 3 di atas layak jadi bagian sendiri: resi tindakan mengatakan “kunci ini menandatangani konten ini,” bukan “manusia ini mengotorisasi ini.” Untuk tindakan berisiko tinggi (pengembalian dana, penghapusan, transfer kawat), kerangka tata kelola semakin memerlukan pernyataan yang hilang ini, dan itu dapat dibuat dengan primitif yang sudah Anda bangun dalam pelajaran ini.
Notebook lanjutan code_samples/human-authorization-receipts.ipynb menambahkan jenis resi kedua, human.approval.v1, dalam bentuk amplop yang sama dengan resi pelajaran (payload bertipe yang ditandatangani oleh Ed25519 atas SHA-256 kanoniknya, dengan objek signature di luar byte yang ditandatangani). Pengotorisasi bernama menandatangani tindakan kanonik penuh dan digestnya sebelum eksekusi; resi tindakan agen membawa digest tindakan yang sama dan parent_approval_ref, yaitu receipt_hash dari persetujuan, konvensi sama seperti previous_receipt_hash dalam rantai yang Anda buat di atas. Satu verify_chain memeriksa kedua artefak di bawah registri kunci yang dipin terpisah (kunci pengotorisasi vs kunci agen), sehingga jalur kode sama tapi pihak berwenang berbeda.
Properti yang diperoleh ini, dengan pernyataan hati-hati: manusia menyetujui tindakan tepat ini, dan agen menjalankan tindakan yang disetujui persis itu. Fixture penolakan di notebook membuat properti ini nyata, bukan hanya klaim:
Setiap kegagalan menolak dengan alasan berbeda, sehingga auditor yang membaca penolakan bisa mengetahui apakah otoritas usang atau tindakan yang dijalankan berubah. Aturan yang diajarkan notebook: tanda tangan persetujuan bukan otoritas dengan sendirinya. Otoritas hanya ada jika kedua resi masih mengikat pada tindakan kanonik yang sama pada waktu eksekusi. Jalur tanda tangan bersama dalam Internet-Draft yang sama yang diikuti pelajaran ini (draft-farley-acta-signed-receipts) adalah bentuk standar dari pola ini.
Kode Python dalam pelajaran ini sengaja minimal agar Anda dapat membaca setiap baris dan memahami persis apa yang terjadi. Dalam produksi, Anda memiliki dua pilihan:
Bangun langsung di atas primitif kriptografi. 50 baris yang Anda lihat di atas sudah cukup untuk banyak kasus penggunaan. PyNaCl (Ed25519) dan paket jcs (JSON kanonik) adalah pustaka yang terawat dan diaudit dengan baik.
Gunakan pustaka resi produksi. Beberapa proyek sumber terbuka mengimplementasikan pola yang sama dengan fitur tambahan (rotasi kunci, verifikasi batch, distribusi JWK Set, integrasi dengan mesin kebijakan):
draft-farley-acta-signed-receipts, revisi 02) yang saat ini dalam proses standar, dengan suite konformansi bersama (agent-governance-testvectors) yang diuji silang oleh implementasi independen untuk output kanonik identik byte.protect-mcp (npm) dan @veritasacta/verify (npm) menyediakan implementasi Node dari penandatanganan resi dan verifikasi offline, ditujukan untuk membungkus server MCP apa pun dengan jejak audit tahan manipulasi, termasuk alur tahan untuk tanda tangan bersama di mana tindakan yang dijeda mengeluarkan resi persetujuan yang terkait dengan digest tindakan (didukung WebAuthn dalam alur desktop), pola resi persetujuan yang sama seperti notebook otorisasi manusia di atas.pip install nobulex) menyediakan pola tanda tangan Ed25519 + JCS yang sama di Python dengan integrasi LangChain dan CrewAI, termasuk vektor pengujian silang yang dipublikasikan dan pemetaan kepatuhan yang disumbangkan melalui OWASP PR #2210.Keputusan antara membuat sendiri dan menggunakan pustaka mencerminkan keputusan antara menulis pustaka JWT sendiri dan menggunakan yang sudah diuji: keduanya bisa diterima; pustaka menghemat waktu dan mengurangi permukaan audit; pendekatan dari awal memaksa Anda memahami setiap primitif. Pelajaran ini mengajarkan jalur dari awal agar Anda memiliki dasar untuk pilihan mana pun.
Uji pemahaman Anda sebelum melanjutkan ke latihan praktik.
1. Resi ditandatangani dengan kunci pribadi Ed25519 agen. Auditor hanya memiliki kunci publik. Apakah auditor dapat memverifikasi resi secara offline?
2. Penyerang memodifikasi bidang policy_id dari sebuah resi untuk mengklaim bahwa resi itu diatur oleh kebijakan yang lebih permisif. Tanda tangan ada pada payload asli. Apa yang terjadi saat verifikasi?
3. Mengapa tanda terima mencakup tool_args_hash dan result_hash daripada argumen mentah dan hasil?
4. Bidang previous_receipt_hash menghubungkan setiap tanda terima dengan pendahulunya. Jika penyerang diam-diam menghapus satu tanda terima dari tengah rantai, apa yang menjadi tidak valid?
5. Sebuah tanda terima diverifikasi dengan bersih. Apakah itu membuktikan tindakan agen benar, sah, atau sesuai kebijakan?
Buka code_samples/18-signed-receipts.ipynb dan selesaikan keempat bagian berikut:
Tantangan lanjutan 1: perluas skema tanda terima dengan bidang tambahan yang kamu pilih sendiri (misalnya, ID permintaan untuk pelacakan), perbarui logika penandatanganan kanonik untuk menyertakannya, dan pastikan bahwa tanda terima masih dapat melewati verifikasi. Kemudian ubah bidang itu setelah penandatanganan dan pastikan verifikasi gagal. Ini memaksa kamu untuk memahami bagaimana setiap byte dari encoding kanonik berkontribusi pada tanda tangan.
Tantangan lanjutan 2: Gabungkan dua tanda terima kamu dengan SHA-256 (gabungkan byte kanoniknya dalam urutan deterministik) dan masukkan hasil digest sebagai bidang baru pada tanda terima ketiga sebelum menandatanganinya. Verifikasi bahwa ketiga tanda terima masih dapat melewati verifikasi. Kamu baru saja membangun bukti inklusi satu langkah: siapa pun yang memegang tanda terima ketiga dapat membuktikan bahwa dua yang pertama ada pada saat tanda terima ditandatangani, tanpa perlu mengungkapkan isinya. Ini adalah pola yang digunakan tanda terima pengungkapan selektif berskala besar (komitmen Merkle, RFC 6962).
Tanda terima kriptografi memberikan agen AI jejak audit yang:
Mereka bukan pengganti validasi input, penegakan kebijakan, atau infrastruktur identitas. Mereka adalah dasar untuk lapisan tersebut. Saat kamu menerapkan agen dalam beban kerja teratur, alur kerja multi-organisasi, atau di mana auditor di masa depan tidak dapat dipercaya begitu saja, tanda terima adalah cara kamu membuat jejak audit jujur.
Hal terpenting yang bisa diambil: tanda terima membuktikan siapa yang mengatakan apa, kapan. Mereka tidak membuktikan bahwa apa yang dikatakan itu benar atau tepat. Pegang perbedaan itu erat-erat. Ini adalah perbedaan antara sistem asal-usul yang jujur dan yang menyesatkan.
Saat kamu siap naik tingkat dari pelajaran ini ke menerapkan agen bertanda terima di lingkungan nyata:
https://your-org.example.com/.well-known/agent-keys.json.Bergabunglah dengan Microsoft Foundry Discord untuk bertemu pelajar lain, menghadiri jam kantor, dan mendapatkan jawaban atas pertanyaan Agen AI kamu.
Pelajaran ini mencakup penandatanganan tanda terima tunggal dan urutan rantai hash. Primitif yang sama membentuk beberapa pola yang lebih maju yang mungkin kamu temui saat sikap tata kelola kamu berkembang:
authorization_*) dan post-eksekusi (result_*) dengan tanda tangan independen, berguna saat keputusan otorisasi dan hasil yang diamati dibuat oleh aktor berbeda atau pada waktu berbeda. Ini bertumpuk secara aditif di atas format tanda terima yang diajarkan dalam pelajaran ini.result_hash. Muatan dunia nyata seringkali lebih kaya daripada hasil panggilan alat tunggal: pertimbangan sebelum keputusan (prediksi model, opsi yang dipertimbangkan, bukti dan kelengkapannya, postur risiko, rantai akuntabilitas, hasil pengontrol) semuanya dapat ada di dalam muatan, disegel oleh satu tanda terima. Ini menjaga format tanda terima tetap minimal sambil membiarkan skema muatan berubah sesuai domain.signature.alg dapat membawa ML-DSA-65 (standar tanda tangan pasca-kuantum NIST) saat kamu perlu bermigrasi. Rencanakan masa transisi di mana tanda terima ditandatangani ganda.Penafian: Dokumen ini telah diterjemahkan menggunakan layanan terjemahan AI Co-op Translator. Meskipun kami berupaya untuk mencapai akurasi, harap diketahui bahwa terjemahan otomatis mungkin mengandung kesalahan atau ketidakakuratan. Dokumen asli dalam bahasa aslinya harus dianggap sebagai sumber yang sah. Untuk informasi penting, disarankan menggunakan terjemahan profesional oleh manusia. Kami tidak bertanggung jawab atas kesalahpahaman atau penafsiran yang keliru yang timbul dari penggunaan terjemahan ini.