Tonton video pelajaran: Memastikan Ejen AI dengan Resit Kriptografi
(Video pelajaran dan gambar kecil akan ditambah oleh pasukan kandungan Microsoft selepas gabungan, mengikut pola pelajaran 14 / 15.)
Pelajaran ini akan merangkumi:
Setelah selesai pelajaran ini, anda akan tahu cara untuk:
Bayangkan anda telah mengendalikan ejen AI untuk Contoso Travel. Ejen tersebut membaca permintaan pelanggan, memanggil API penerbangan untuk mencari pilihan, dan menempah tempat duduk bagi pihak pelanggan. Suku tahun lepas, ejen memproses 50,000 tempahan.
Hari ini seorang juruaudit datang. Mereka mengajukan soalan mudah: “Tunjukkan kepada saya apa yang ejen anda lakukan.”
Anda menyerahkan fail log anda. Juruaudit melihatnya dan mengajukan soalan yang lebih sukar: “Bagaimana saya tahu log ini tidak diedit?”
Ini adalah masalah jejak audit. Kebanyakan pengendalian ejen hari ini bergantung pada:
Tiada satu pun ini boleh menjawab soalan juruaudit tanpa memerlukan juruaudit mempercayai seseorang (anda, penyedia awan anda, vendor pangkalan data anda). Untuk kegunaan dalaman, kepercayaan itu biasanya boleh diterima. Untuk beban kerja yang dikawal selia (kewangan, penjagaan kesihatan, apa sahaja yang tertakluk kepada Akta AI EU), ia tidak boleh diterima.
Resit kriptografi menyelesaikan ini dengan menjadikan setiap tindakan ejen boleh disahkan secara berdikari. Juruaudit tidak perlu mempercayai anda. Mereka hanya memerlukan kunci awam anda dan resit itu sendiri.
Resit adalah objek JSON yang merekodkan apa yang dilakukan oleh ejen, ditandatangani dengan tandatangan digital.
flowchart LR
A[Ejen memanggil alat] --> B[Membangun muatan resit]
B --> C[Kanonkan JSON RFC 8785]
C --> D[Hash SHA-256]
D --> E[Tandatangan Ed25519]
E --> F[Resit dengan tandatangan]
F --> G[Juruaudit mengesahkan luar talian]
G --> H{Tandatangan sah?}
H -- yes --> I[Bukti tahan sengaja]
H -- no --> J[Resit ditolak]
Resit minimum kelihatan 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 sifat melaksanakan kerja ini:
Tandatangan. Resit ditandatangani oleh pintu masuk ejen menggunakan kunci peribadi Ed25519. Sesiapa dengan kunci awam yang sepadan boleh mengesahkan tandatangan itu secara luar talian. Pengubahan pada mana-mana medan meninvalidkan tandatangan.
Pengekodan kanonik. Sebelum menandatangani, resit diserikan menggunakan Skema Kanonifikasi JSON (JCS, RFC 8785). Ini memastikan bahawa dua pelaksanaan yang menghasilkan resit logik yang sama menghasilkan output identik dalam bait. Tanpa kanonifikasi, peleraian JSON yang berbeza menghasilkan tandatangan yang berbeza untuk kandungan yang sama.
Pengikatan hash. Medan previous_receipt_hash menghubungkan setiap resit dengan resit sebelumnya. Mengalih keluar atau menyusun semula resit memutuskan setiap resit selepasnya. Pengubahan menjadi kelihatan di peringkat rantai walaupun tandatangan individu dikelakkan.
Bersama-sama sifat ini menyediakan tiga jaminan:
Anda tidak memerlukan perpustakaan khusus untuk menghasilkan resit. Primitif kriptografi tersedia secara meluas dan logiknya hanya beberapa puluh baris Python.
Latihan praktikal dalam code_samples/18-signed-receipts.ipynb memandu melalui keseluruhan aliran. Versi ringkas:
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 naik kunci tandatangan (dalam pengeluaran, simpan dalam peti besi kunci)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Bina muatan resit (belum ada tandatangan)
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,
}
# Kanonikan, campur, tandatangan.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Lampirkan objek tandatangan berstruktur.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
Itu keseluruhan saluran penandatanganan. Latihan dalam buku nota berjalan melalui setiap langkah.
Pengesahan adalah operasi songsang:
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:
# Tandatangan adalah objek berstruktur: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Bina semula muatan yang sebenarnya ditandatangani (semua kecuali tandatangan).
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 resit dan mengembalikan True jika tandatangan sah, False jika tidak. Tiada panggilan rangkaian, tiada pergantungan perkhidmatan, tiada kepercayaan diperlukan pada pihak ketiga.
Untuk melihat pengesanan pengubahan berfungsi, buku nota menunjukkan:
tool_args_hash.Ini adalah demonstrasi praktikal bahawa resit adalah bukti pengubahan: sebarang pengubahan, walau kecil, memutuskan tandatangan.
Satu resit bertandatangan melindungi satu tindakan. Rantaian resit melindungi satu urutan.
flowchart LR
R0[Resit 0<br/>genesis] --> R1[Resit 1]
R1 --> R2[Resit 2]
R2 --> R3[Resit 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Setiap resit merekod hash resit sebelumnya. Untuk membuang resit 2 secara senyap, penyerang perlu:
previous_receipt_hash resit 3 (memutuskan tandatangan resit 3), ATAUJika kunci peribadi berada dalam peti besi kunci perkakasan dan anda menerbitkan kunci awam dengan setiap resit, tiada serangan boleh dilakukan tanpa dikesan.
Buku nota memandu melalui:
previous_receipt_hash setiap resit sepadan dengan hash sebenar resit sebelumnya.Begitulah anda menghasilkan jejak audit yang boleh disahkan oleh juruaudit luar tanpa mempercayai anda.
Ini adalah bahagian paling penting dalam pelajaran ini. Resit berkuasa tetapi kuasanya terhad.
Resit membuktikan tiga perkara:
Resit TIDAK membuktikan:
policy_id benar-benar dinilai, atau bahawa ia akan membenarkan tindakan ini jika diperiksa. Resit merekod apa yang didakwa, bukan apa yang dikuatkuasakan.Sempadan ini penting untuk dua sebab:
Kesilapan biasa ialah menganggap bahawa “kami ada resit” bermakna “kami diatur.” Ia tidak begitu. Resit adalah asas. Tadbir urus ialah sistem yang anda bina di atasnya.
Perkara 3 di atas berhak mendapat seksyen sendiri: resit tindakan mengatakan “kunci ini menandatangani kandungan ini,” tidak pernah “manusia ini membenarkan ini.” Untuk tindakan berisiko tinggi (bayaran balik, penghapusan, pemindahan wayar), rangka kerja tadbir urus semakin memerlukan penyataan hilang itu, dan ia boleh dihasilkan dengan primitif yang sama yang sudah anda bina dalam pelajaran ini.
Buku nota lanjutan code_samples/human-authorization-receipts.ipynb menambah jenis resit kedua, human.approval.v1, dalam bentuk sampul yang sama seperti resit pelajaran (muatan berjenis ditandatangani oleh Ed25519 ke atas SHA-256 kanoniknya, dengan objek signature di luar bait yang ditandatangani). Pelulus bernama menandatangani tindakan penuh kanonik dan ringkasannya sebelum pelaksanaan; resit tindakan ejen membawa ringkasan tindakan yang sama dan parent_approval_ref, receipt_hash kelulusan, konvensi yang sama seperti previous_receipt_hash dalam rantai yang anda bina sebelum ini. Satu verify_chain memeriksa kedua-dua artifak di bawah daftar kunci tersemat berasingan (kunci pelulus vs kunci ejen), jadi laluan kod dikongsi tetapi pihak berkuasa tidak pernah berkongsi.
Sifat yang ini bawa, dinyatakan dengan teliti: manusia meluluskan tindakan tepat ini, dan ejen melaksanakan tindakan yang diluluskan itu dengan tepat. Kerangka penolakan dalam buku nota menjadikan sifat ini nyata dan bukan sekadar dakwaan:
Setiap kegagalan ditolak dengan sebab yang berbeza, jadi juruaudit membaca penolakan boleh membezakan sama ada kuasa telah lapuk atau tindakan yang dilaksanakan berubah. Peraturan yang diajar oleh buku nota: kelulusan bertandatangan bukan kuasa sendiri. Kuasa wujud hanya jika kedua-dua resit masih mengikat tindakan kanonik yang sama pada masa pelaksanaan. Laluan kopengesahan dalam Draf Internet yang sama dengan pelajaran ini (draft-farley-acta-signed-receipts) adalah bentuk trajektori piawaian corak ini.
Kod Python dalam pelajaran ini sengaja minimal supaya anda boleh membaca setiap baris dan faham apa yang sedang berlaku. Dalam pengeluaran, anda ada dua pilihan:
Bina terus di atas primitif kriptografi. 50 baris yang anda lihat di atas sudah mencukupi untuk banyak kes penggunaan. PyNaCl (Ed25519) dan pakej jcs (JSON kanonik) adalah perpustakaan yang diselenggara dengan baik dan diaudit.
Gunakan perpustakaan resit pengeluaran. Beberapa projek sumber terbuka melaksanakan corak yang sama dengan ciri tambahan (putaran kunci, pengesahan berkumpulan, pengedaran Kumpulan Kunci JWK, integrasi dengan enjin dasar):
draft-farley-acta-signed-receipts, semakan 02) yang kini dalam proses piawaian, dengan suite pematuhan bersama (agent-governance-testvectors) yang pelaksanaan bebas saling mengesahkan untuk output kanonik identik bait.protect-mcp (npm) dan @veritasacta/verify (npm) menyediakan pelaksanaan tandatangan resit dan pengesahan luar talian berasaskan Node, bertujuan untuk membungkus mana-mana pelayan MCP dengan jejak audit bukti pengubahan, termasuk aliran tahan-kopengesahan di mana tindakan dihentikan mengeluarkan resit kelulusan terikat kepada ringkasan tindakan (disokong WebAuthn dalam aliran desktop), corak resit kelulusan yang sama seperti buku nota pengesahan manusia di atas.pip install nobulex) menyediakan corak tandatangan Ed25519 + JCS yang sama dalam Python dengan integrasi LangChain dan CrewAI, termasuk vektor ujian silang yang diterbitkan dan pemetaan kepatuhan yang disumbangkan melalui OWASP PR #2210.Keputusan antara membina sendiri atau menggunakan perpustakaan mencerminkan keputusan antara menulis perpustakaan JWT anda sendiri dan menggunakan yang telah diuji: kedua-duanya munasabah; perpustakaan menjimatkan masa dan mengurangkan permukaan audit; pendekatan dari awal memaksa anda faham setiap primitif. Pelajaran ini mengajar laluan dari awal supaya anda mempunyai asas untuk mana-mana pilihan.
Uji pemahaman anda sebelum bergerak ke latihan praktikal.
1. Resit ditandatangani dengan kunci peribadi Ed25519 ejen. Juruaudit hanya mempunyai kunci awam. Bolehkah juruaudit mengesahkan resit secara luar talian?
2. Penyerang mengubah medan policy_id resit untuk mendakwa ia dikawal oleh dasar yang lebih membenarkan. Tandatangan dibuat ke atas muatan asal. Apa yang berlaku semasa pengesahan?
3. Mengapakah resit termasuk tool_args_hash dan result_hash dan bukannya argumen mentah dan hasil?
4. Medan previous_receipt_hash menghubungkan setiap resit kepada pendahulunya. Jika penyerang membuang satu resit dari tengah rantaian secara senyap, apa yang menjadi tidak sah?
5. Resit mengesahkan dengan bersih. Adakah itu membuktikan tindakan agen betul, tepat, atau mematuhi polisi?
Buka code_samples/18-signed-receipts.ipynb dan lengkapkan keempat-empat bahagian:
Cabaran lanjutan 1: luaskan skema resit dengan medan tambahan pilihan anda sendiri (contoh, ID permintaan untuk penjejakan), kemas kini logik penandatanganan kanonik untuk memasukkannya, dan pastikan resit masih melalui pengesahan pusing-balik. Kemudian ubah medan selepas tandatangan dan pastikan pengesahan gagal. Ini memaksa anda memahami bagaimana setiap bait pengekodan kanonik menyumbang kepada tandatangan.
Cabaran lanjutan 2: SHA-256 hash dua resit anda bersama (sambungkan bait kanonik mereka dalam susunan deterministik) dan tanamkan hasil digest sebagai medan baru pada resit ketiga sebelum menandatangan. Sahkan ketiga-tiga resit masih pusing-balik. Anda baru sahaja membina bukti inklusi satu langkah: sesiapa yang memegang resit ketiga boleh membuktikan dua yang pertama wujud ketika ia ditandatangani, tanpa perlu dedah kandungan mereka. Ini corak yang digunakan resit pendedahan terpilih secara besar-besaran (komitmen Merkle, RFC 6962).
Resit kriptografi memberi agen AI jejak audit yang:
Ia bukan pengganti pengesahan input, penguatkuasaan polisi, atau infrastruktur identiti. Ia asas bagi lapisan-lapisan tersebut. Apabila melaksanakan agen dalam beban kerja terkawal, aliran kerja berbilang organisasi, atau mana-mana situasi di mana juruaudit masa depan tidak boleh dipercayai, resit memastikan jejak audit jujur.
Intipati paling penting: resit membuktikan siapa kata apa, bila. Ia tidak membuktikan apa yang dikatakan itu betul atau tepat. Pegang perbezaan itu erat-erat. Ia bezakan sistem asal usul jujur dan yang mengelirukan.
Apabila anda sudah bersedia untuk lulus dari pelajaran ini ke pengeluaran agen tandatangan resit dalam persekitaran sebenar:
https://your-org.example.com/.well-known/agent-keys.json.Sertai Microsoft Foundry Discord untuk berjumpa pelajar lain, hadir jam pejabat, dan dapatkan jawapan untuk soal agen AI anda.
Pelajaran ini merangkumi tandatangan resit tunggal dan urutan rantaian hash. Primitif sama membina beberapa corak maju yang mungkin anda temui seiring kematangan postur tadbir urus:
authorization_*) dan pasca-pelaksanaan (result_*) dengan tandatangan bebas, berguna bila keputusan kebenaran dan hasil yang diperhatikan dihasilkan pelaku berbeza atau masa berbeza. Ini menambah di atas format resit dalam pelajaran ini.result_hash. Muatan dunia sebenar selalunya lebih kaya daripada hasil panggilan alat tunggal: pemikiran pra-keputusan (ramalan model, pilihan dipertimbangkan, bukti dan kelengkapannya, postur risiko, rantaian akauntabiliti, keputusan pintu) boleh dimuat dalam muatan, ditutup oleh satu resit. Ini memastikan format resit minimal sambil membenarkan skema muatan berkembang domain demi domain.signature.alg boleh bawa ML-DSA-65 (standard tandatangan kuantum pasca NIST) apabila anda perlu beralih. Rancang tempoh peralihan di mana resit ditandatangani berganda.Penafian: Dokumen ini telah diterjemahkan menggunakan perkhidmatan terjemahan AI Co-op Translator. Walaupun kami berusaha untuk ketepatan, sila ambil maklum bahawa terjemahan automatik mungkin mengandungi kesilapan atau ketidaktepatan. Dokumen asal dalam bahasa asalnya harus dianggap sebagai sumber yang sahih. Untuk maklumat penting, terjemahan oleh manusia profesional adalah disyorkan. Kami tidak bertanggungjawab terhadap sebarang salah faham atau salah tafsir yang timbul daripada penggunaan terjemahan ini.