Vaadake õppetunni videot: AI agentide turvamine krüptograafiliste kviitungitega
(Õppetunni video ja pisipilt lisatakse Microsofti sisutiimi poolt pärast ühendamist, järgides õppetunni 14 / 15 mustrit.)
See õppetund käsitleb:
Pärast selle õppetunni lõpetamist oskad sa:
Kujuta ette, et oled rakendanud AI agendi Contoso Travel jaoks. Agent loeb klientide päringuid, kutsub lendude API-d, et otsida võimalusi, ja broneerib istekohti kliendi nimel. Eelmisel kvartalil töötles agent 50 000 broneeringut.
Täna ilmub audiitor. Ta küsib lihtsa küsimuse: “Näita mulle, mida sinu agent tegi.”
Sa annad üle oma logifailid. Audiitor vaatab neid ja esitab raskema küsimuse: “Kuidas ma tean, et neid logisid ei muudetud?”
See on auditeerimisjälje probleem. Enamik agendi rakendusi tänapäeval toetub järgnevatele:
Ükski neist ei suuda audiitori küsimusele vastata ilma, et audiitor peaks kedagi usaldama (sind, sinu pilveteenuse pakkujat, sinu andmebaasi pakkujat). Siseotstarbel on see usaldus sageli vastuvõetav. Reguleeritud töökoormuste puhul (finants, tervishoid, mis iganes Euroopa Liidu AI seaduse alla kuulub) see ei kehti.
Krüptograafilised kviitungid lahendavad selle, muutes iga agendi tegevuse iseseisvalt kontrollitavaks. Audiitor ei pea sind usaldama. Tal on vaja vaid sinu avalikku võtit ja kviitungit ennast.
Kviitung on JSON-objekt, mis salvestab, mida agent tegi, allkirjastatud digitaalse allkirjaga.
flowchart LR
A[Esindaja kutsub tööriista] --> B[Koosta kviitungi andmepakett]
B --> C[Kanoniseeri JSON RFC 8785 järgi]
C --> E[Ed25519 allkirjasta kanonilised baitid]
E --> F[Kviitung koos allkirjaga]
F --> G[Audiitor kontrollib võrguühenduseta]
G --> H{Kas allkiri on kehtiv?}
H -- yes --> I[Välistegijate puutumatu tõend]
H -- no --> J[Kviitung lükati tagasi]
Minimalistlik kviitung näeb välja selline:
{
"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..."
}
}
Kolm omadust teevad selle töö:
Allkiri. Kviitungi allkirjastab agendi värav Ed25519 privaatvõtmega. Kõik, kellel on vastav avalik võti, saavad allkirja võrguühenduseta kontrollida. Välja muutmine rikub allkirja.
Kanoniline kodeerimine. Enne allkirjastamist serialiseeritakse kviitung JSON-i kanoniseerimisskeemi (JCS, RFC 8785) järgi. See tagab, et kaks erinevat rakendust, mis toodavad sama loogilist kviitungit, annavad baiti täpselt võrdsed tulemused. Ilma kanoniseerimiseta tooteks erinevad allkirjad.
Räsiketting. Välja previous_receipt_hash ühendab iga kviitungi eelmisega. Kviitungi eemaldamine või ümberjärjestamine katki lõhub kõiki pärast seda olevaid kviitungeid. Manipuleerimine muutub nähtavaks ka keti tasemel, isegi kui üksikud allkirjad jäävad vahele.
Koos annavad need kolm omadust kolm garantiid:
Sul ei ole vaja spetsiaalset teeki kviitungi tootmiseks. Krüptograafilised primitiivid on laialdaselt kättesaadavad ning loogika on paarikümne rea pikkune Python.
Praktilistes harjutustes failis code_samples/18-signed-receipts.ipynb on kogu protsess samm-sammult lahti kirjutatud. Kokkuvõte:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # RFC 8785 kanoniline JSON
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()}"
# Genereeri või laadi allkirjastamise võti (tootmises hoia võtmekeldris)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Koosta kviitungi laad (veel allkirjata)
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,
}
# Kanoniliseeri ja allkirjasta JCS baitid otse. Puhtalt EdDSA räsi seesmiselt.
canonical_bytes = canonicalize(payload)
signature_bytes = signing_key.sign(canonical_bytes).signature
# Lisa struktureeritud allkirjaobjekt.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
See on kogu allkirjastamise torujuhe. Harjutused märkmikus selgitavad kõiki samme.
Kontrollimine on vastupidine protsess:
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:
# Allkiri on struktureeritud objekt: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Taasta koormus, mis tegelikult allkirjastati (kõik peale allkirja).
payload = {k: v for k, v in receipt.items() if k != "signature"}
canonical_bytes = canonicalize(payload)
try:
verify_key = signing.VerifyKey(b64url_decode(sig_obj["public_key"]))
verify_key.verify(canonical_bytes, b64url_decode(sig_obj["sig"]))
return True
except BadSignatureError:
return False
See funktsioon võtab kviitungi ja tagastab True, kui allkiri on kehtiv, muidu False. Ei mingit võrguiga, ei teenuse sõltuvust ega usaldust kolmandatesse osapooltesse.
Manipuleerimise avastamist näitab märkmes:
tool_args_hash sees.See on praktiline demonstratsioon, et kviitungid on manipuleerimise suhtes haavatavad: iga muudatus, isegi väga väike, katkestab allkirja.
Üksik allkirjastatud kviitung kaitseb üht tegevust. Kviitungite jada kaitseb järjestust.
flowchart LR
R0[Kviitung 0<br/>algus] --> R1[Kviitung 1]
R1 --> R2[Kviitung 2]
R2 --> R3[Kviitung 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Iga kviitung salvestab eelmise kviitungi räsi. Kviitungi 2 vaikselt eemaldamiseks peaks ründaja:
previous_receipt_hash (katkestab kviitungi 3 allkirja), VÕIKui privaatvõti on riistvaras ja avalikku võtit publitseeritakse iga kviitungiga, ei ole kumbki rünnak avastamata võimalik.
Märkmik selgitab:
previous_receipt_hash vastab eelmise kviitungi räsidele.Nii toodad auditeerimisjälje, mida väline audiitor saab kontrollida ilma sind usaldamata.
See on selle õppetunni kõige olulisem osa. Kviitungid on võimsad, kuid nende võim on piiratud.
Kviitungid tõestavad kolme asja:
Kviitungid EI TÕESTA:
policy_id-s viidatud poliitika oli tegelikult hinnatud või et see oleks selle tegevuse lubanud. Kviitung salvestab, mida väideti, mitte mida rakendati.See piirastus on oluline kahe põhjusel:
Levinud viga on arvata, et “meil on kviitungid” tähendab “meil on regulatsioon.” See ei kehti. Kviitungid on alus. Regulatsioon on süsteem, mida sellele rajad.
Punkt 3 on omaette teema: tegevuse kviitung ütleb “see võti allkirjastas selle sisu,” mitte kunagi “see inimene volitas seda.” Kõrge riski tegevustele (tagasimaksed, kustutused, ülekanded) nõuavad regulatsiooniraamistikud üha enam seda täpselt puuduvat avaldust, mis on saavutatav siin koolitatud primitiividega.
Järgnev märkmete komplekt code_samples/human-authorization-receipts.ipynb lisab teise liigi kviitungid, human.approval.v1, samas ümbrikus nagu selle õppetunni kviitungid (tüüpidatud andmepakett, millele on Ed25519 allkiri kanonilisel JCS kujul, kus signature objekt on allkirjastatud baitidest väljaspool). Nimetatud heakskiitja allkirjastab täieliku kanonilise tegevuse ja selle räsi enne täideviimist; agendi tegevuse kviitung kannab sama tegevuse räsi ja parent_approval_ref, heakskiidu receipt_hash, see on sama tava, mis previous_receipt_hash keti puhul eespool. Üks verify_chain kontrollib mõlemat objekti erinevates kinnitatud võtme registrites (volitaja võtmed vs agendi võtmed), nii et koodi tee on ühine, ent volitused ei ole kunagi.
Selle omandamise mõiste kõlab nii: inimene heaks kiitis selle täpse tegevuse ja agent sooritas täpselt selle heakskiidetud tegevuse. Märkmiku keeldumisjuhtumid teevad omaduse reaalseks, mitte ainult väljaütlemiseks:
Iga viga keelab teatud põhjusel, nii et audiitor saab lugeda, kas volitus aegus või tegevus muutus. Märkmik õpetab: allkirjastatud heakskiit ei ole volitus iseenesest. Volitus eksisteerib ainult, kui mõlemad kviitungid seovad endiselt sama kanonilise tegevusega selle täideviimise ajal. Inimese heakskiidu kviitung on hariduslik kompositsioon, mille määrab see õppetund, mitte tüüpiline kviitung draft-farley-acta-signed-receipts.
Selle õppetunni Pythoni kood on tahtlikult minimaalne, et sa saaksid iga rea läbi lugeda ja mõista, mis toimub. Tootmises on sul kaks võimalust:
Ehita otse krüptograafiliste primitiivide peale. Eespool nähtud 50 rida katavad paljud kasutusjuhtumid. PyNaCl (Ed25519) ja jcs pakett (kanoniline JSON) on hästi hooldatud ja auditeeritud teegid.
Kasuta tootmislikku kviitungite teeki. Mitmed avatud lähtekoodiga projektid rakendavad sama mustrit lisafunktsioonidega (võtme pööramine, kihiline kontroll, JWK kogumite levitamine, poliitika mootorite integreerimine):
draft-farley-acta-signed-receipts, revisjon 02). Selle õppetunni tasane hariduslik kviitung erineb drafti {payload, signature} ümbrikust ega ole esitatud kui nõuetele vastav teostus. Draft avaldab ühise vastavuskomplekti (agent-governance-testvectors) neile, kes sihivad tema juurdepääsuformaati.protect-mcp (npm) ja @veritasacta/verify (npm) pakuvad Node-põhist teostust kviitungite allkirjastamiseks ja võrguühenduseta kontrolliks, mõeldud MCP serveri ümber mässimiseks manipuleerimiskindla auditeerimisjäljega, kaasa arvatud ootel oleku kooskõlastusvool, kus pausitud tegevus väljastab heakskiidu kviitungi, mis on seotud tegevuse räsidega (WebAuthn tugi töölaua voos), sama heakskiit-kviitungi mustriga nagu eelnevalt mainitud inimese volituse märkmete komplekt.pip install nobulex) pakub sama Ed25519 + JCS allkirjastamise mustrit Pythonis koos LangChain ja CrewAI integratsioonidega, sisaldades avaldatud ristkontrolli testvektoreid ja vastavuskaardi panust OWASP PR #2210 kaudu.Rohelise teegi ja oma teegi valiku otsus on sama, mis JWT teegi enda kirjutamise ja testitud kolmanda osapoole kasutamise vahe. Mõlemad on põhjendatud; teek säästab aega ja vähendab auditeerimise pindala; algne lähenemine sunnib sind mõistma iga primitiivi. See õppetund õpetab algusest algust, et sul oleks alus mõlemaks valikuks.
Testi oma arusaama enne praktilist harjutust.
1. Kviitung on allkirjastatud agendi privaatse Ed25519 võtmega. Audiitoril on ainult avalik võti. Kas audiitor saab kviitungit võrguühenduseta kontrollida?
2. Ründaja muudab kviitungi välja policy_id, et väita, et seda valitses lubavam poliitika. Allkiri oli algse andmepaketi peal. Mis juhtub kontrolli käigus?
3. Miks sisaldab kviitung tool_args_hash ja result_hash asemel toorargumente ja -tulemust?
4. Välja previous_receipt_hash kaudu lingib iga kviitung oma eelkäijaga. Kui ründaja kustutab ahelast vaikselt ühe kviitungi keskel, mis muutub kehtetuks?
5. Kviitung kontrollitakse õigeks. Kas see tõestab, et agendi tegevus oli õige, korrektselt tehtud või vastavuses poliitikaga?
Ava code_samples/18-signed-receipts.ipynb ja täida kõik neli osa:
Lisaväljakutse 1: pikenda kviitungiskeemi ühe lisaväljaga, mille valid ise (näiteks taotlus-ID jälgimiseks), uuenda kanonilist allkirjastamiste loogikat, et see seda sisaldaks, ja kinnita, et kviitung läbib endiselt kontrolli. Muuda välja pärast allkirjastamist ja kinnita kontrolli ebaõnnestumist. See sunnib sind mõistma, kuidas iga bait kanonilises kodeerimises allkirja panustab.
Lisaväljakutse 2: SHA-256 hash’i kaks sinu kviitungit kokku (ühenda nende kanonilised baitid deterministlikus järjekorras) ja pane tulemuslik digest kolmanda kviitungi uue väljaga enne allkirjastamist. Kontrolli, et kõik kolm kviitungit läbivad endiselt kontrolli. Sa oled just loonud ühe-käigulise kaasatatuse tõendi: kellel on kolmas kviitung, saab tõestada, et esimesed kaks olid olemas allkirjastamisajal, ilma et peaks nende sisu avaldama. See on mustrit, mida selektiivse avalikustamise kviitungid suures mahus kasutavad (Merkle kohustused, RFC 6962).
Krüptograafilised kviitungid annavad tehisintellekti agentidele auditeerimisjälje, mis on:
Need ei asenda sisendite valideerimist, poliitikate rakendamist ega identiteeditaristut. Nad on nende kihtide alus. Kui saadad agente reguleeritud töökoormatesse, mitmeorganisatsioonilistesse töövoogudesse või ükskõik millisesse olukorda, kus tulevast audiitorit ei saa eeldada usaldavat sind, siis kviitungid on see, kuidas sa teed auditeerimisjälje ausaks.
Kõige olulisem õppetund: kviitungid tõestavad, kes ütles mida, millal. Nad ei tõesta, et öeldu oli tõene või õige. Hoia seda vahet rangelt. See on vahe ausa päritolusüsteemi ja eksitava vahel.
Kui oled valmis sellest õppetükist edasi liikuma ning kasutama allkirjastatud kviitungitega agente tõelises keskkonnas:
https://your-org.example.com/.well-known/agent-keys.json.Liitu Microsoft Foundry Discordi kanaliga, et kohtuda teiste õppijatega, osaleda kontorite tundides ja saada vastuseid oma AI agentide küsimustele.
See õppetükk hõlmab ühe kviitungi allkirjastamist ja räsi ahelates järjestamist. Samad primitiivid moodustavad veel mitmeid edasijõudnute mustreid, millega võid kokku puutuda oma valitsemispoliitika küpsemisel:
authorization_*) ja järel-käivitus (result_*) poolteks iseseisvate allkirjadega, kasulik siis, kui autoriseerimisotsuse ja vaadeldud tulemuse toodavad erinevad osapooled või erinevatel aegadel. See moodustab liitmise lisaks selles õppetükis õpetatud kviitungivormingule.result_hash-i. Reaalsed andmekanded on sageli rikkalikumad kui üks tööriistakõne tulemus: otsuse-eelne põhjendus (mõtlemine, mudeli prognoos, arvestatud valikud, tõendusmaterjal ja selle täielikkus, riskipositsioon, vastutusahel, väravtulemus) võib kõik elada andmekandes, mida kinnitab üks kviitung. See hoiab kviitungi formaadi minimaalsena, võimaldades andmeskeemidel areneda domeenipõhiselt.signature.alg väli võib kanda ML-DSA-65 (NIST-i kvantarvutijärgne allkirjastamisstandard), kui vajad migreerumist. Plaani üleminekuperiood, mil kviitungid on kahekordselt allkirjastatud.Lahtiütlus: See dokument on tõlgitud kasutades AI tõlketeenust Co-op Translator. Kuigi me püüdleme täpsuse poole, palun pange tähele, et automatiseeritud tõlgetes võib esineda vigu või ebatäpsusi. Originaaldokument selle emakeeles tuleks pidada autoriteetseks allikaks. Olulise teabe puhul soovitatakse kasutada professionaalset inimtõlget. Me ei vastuta selle tõlkega seotud eksimustest või valesti mõistmistest.