Vaadake õppetunni videot: AI agentide turvamine krüptograafiliste kviitungitega
(Õppetunni video ja pisipilt lisab Microsofti sisutiim pärast liitmist, vastavalt õppetunni 14 / 15 mustrile.)
Selles õppetunnis käsitletakse:
Pärast selle õppetunni läbimist oskad:
Kujuta ette, et oled juurutanud AI agendi Contoso Travel jaoks. Agent loeb kliendi päringuid, kutsub lennupiletite API-d valikute leidmiseks ja broneerib kohad kliendi nimel. Eelmisel kvartalil töötles agent 50 000 broneeringut.
Täna tuleb auditeerija. Ta esitab lihtsa küsimuse: “Näidake, mida teie agent tegi.”
Sa annad üle oma logifailid. Auditeerija vaatab neid ja küsib keerulisemat küsimust: “Kuidas ma tean, et neid logisid ei ole muudetud?”
See on auditeerimise tee probleem. Enamus agentide juurutusi tänapäeval tuginevad:
Ükski neist ei suuda auditeerija küsimust vastata ilma, et auditeerija peaks kedagi usaldama (sind, sinu pilvepakkujat või andmebaasi müüjat). Sisemiseks kasutuseks on see usaldus sageli vastuvõetav. Reguleeritud koormuste (finantsid, tervishoid, midagi EL AI määruse all) puhul mitte.
Krüptograafilised kviitungid lahendavad selle, muutes iga agendi tegevuse iseseisvalt kinnitatavaks. Auditeerija ei pea sind usaldama. Tal on vaja ainult sinu avalikku võtit ja kviitungit ennast.
Kviitung on JSON-objekt, mis salvestab, mida agent tegi, allkirjastatud digitaalallkirjaga.
flowchart LR
A[Agent kutsub tööriista] --> B[Koosta kviitungi koormus]
B --> C[JSON RFC 8785 kanoniseerimine]
C --> D[SHA-256 räsi]
D --> E[Ed25519 allkirjastamine]
E --> F[Kviitung allkirjaga]
F --> G[Audiitor kontrollib offline'is]
G --> H{Allkiri kehtib?}
H -- jah --> I[Manipulatsioonikindel tõend]
H -- ei --> J[Kviitung lükati tagasi]
Minimaalne kviitung näeb välja nii:
{
"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..."
}
}
Tööd teevad kolm omadust:
Allkiri. Kviitung on allkirjastatud agendi värava poolt, kasutades Ed25519 privaatvõtit. Keegi, kellel on vastav avalik võti, saab allkirja võrguühenduseta kontrollida. Väärtuse muutmine tühistab allkirja kehtivuse.
Kanoniline kodeerimine. Enne allkirjastamist serialiseeritakse kviitung JSON Kanoniseerimise skeemi (JCS, RFC 8785) abil. See tagab, et kaks implementatsiooni, mis genereerivad sama loogilise sisu, annavad bait-baidilt identsed väljundid. Ilma kanoniseerimiseta toodaks sama sisu jaoks erineva allkirja erinevate JSON-serialiseerijatega.
Räsi-ahel. Väli previous_receipt_hash seob iga kviitungi eelmisega. Kviitungi eemaldamine või ümberpaigutamine katkestab kõik pärast seda tulevad kviitungid. Muutmine muutub nähtavaks terviku ahela tasandil isegi siis, kui individuaalseid allkirju suudetakse mööda hiilida.
Need kolm omadust annavad kolm garantiid:
Kviitungi tootmiseks pole vaja eraldi teeki. Krüptograafilised põhimõisted on laialt kättesaadavad ja loogika on mõnes kümnes realses Pythonis.
Praktilised harjutused failis code_samples/18-signed-receipts.ipynb selgitavad kogu protsessi. Kokkuvõte:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # RFC 8785 kanooniline 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õtmehoidlasse)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Koosta tšeki andmepakett (eespool allkirja pole)
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,
}
# Kanooniline, räsi, allkirjasta.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Lisa struktureeritud allkirja objekt.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
See on kogu allkirjastamise torujuhe. Märkmete harjutused lähevad iga sammu läbi.
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
# Rekonstrueeri laad, mis tegelikult allkirjastati (kõik peale allkirja).
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
See funktsioon võtab kviitungi ja tagastab True, kui allkiri on kehtiv, muul juhul False. Puudub võrgukõne, teenuse sõltuvus ega vajadus usaldada kolmandat osapoolt.
Muudatuste tuvastust demonstreerimiseks teeb märkmik:
tool_args_hash ühe baiti.See on praktiline näide, et kviitungid on muutmiskindlad: iga muutus, olgu kui väike tahes, katkestab allkirja.
Üks allkirjastatud kviitung kaitseb ühte tegevust. Kviitungite ahel 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. Kui ründaja tahaks vaikides eemaldada kviitungi nr 2, peaks ta kas:
previous_receipt_hash (katkestab kviitungi 3 allkirja), VÕIKui privaatvõti on riistvaralises võtmehoidlas ja avalikku võtit avaldatakse iga kviitungiga, ei ole kumbki rünnak avastamata teostatav.
Märkmik läbib:
previous_receipt_hash vastab eelmise kviitungi tegelikule räsidele.See on viis, kuidas luua auditeerimistee, mida väline auditeerija saab kontrollida ilma sind usaldamata.
See on õppetunni kõige olulisem osa. Kviitungid on võimsad, kuid nende võimekus on piiratud.
Kviitungid tõendavad kolme asja:
Kviitungid EI tõenda:
policy_id viidatud poliitikat hinnati või et see oleks selle tegevuse lubanud, kui seda kontrolliti. Kviitung salvestab, mida väideti, mitte mida rakendati.See piir on oluline kahe põhjusel:
Tavaline viga on arvata, et “meil on kviitungid” tähendab “meil on juhtimine.” Ei tähenda. Kviitungid on alus. Juhtimine on süsteem, mille sa sellele peale ehitad.
Selles õppetunnis on Python-kood meelega minimaalne, et saaksid iga rea läbi lugeda ja täielikult mõista. Tootmiskeskkonnas on sul kaks valikut:
Ehita otse krüptograafiliste primitiivide peale. Ülal näidatud 50 rida on paljude kasutusjuhtumite jaoks piisav. PyNaCl (Ed25519) ja jcs pakett (kanoniline JSON) on hästi hooldatud ja auditeeritud teegid.
Kasuta tootmiskõlblikku kviitungite teeki. Mitmed avatud lähtekoodiga projektid rakendavad sama mustrit lisafunktsioonidega (võtme pööramine, partii kontroll, JWK komplekti jaotamine, integreerimine poliitikamasinatesse):
draft-farley-acta-signed-receipts), mis on hetkel standardimisprotsessis.protect-mcp (npm) ja @veritasacta/verify (npm) pakuvad Node-põhist lahendust kviitunge allkirjastamiseks ja võrguühenduseta kontrolliks, mõeldud mis tahes MCP serveri ümber pakkimiseks muutmiskindla auditeerimisteega.Otsus, kas ehitada ise või kasutada teeki, sarnaneb otsusele kirjutada oma JWT teek või kasutada testitud teeki: mõlemad on mõistlikud; teek säästab aega ja vähendab auditeerimise pinda; algusest peale kirjutamine sunnib mõistma iga primitiivi. See õppetund õpetab algusest, et sul oleks alus ükskõik kumma valiku jaoks.
Testi oma arusaamist enne praktilisse harjutusse minekut.
1. Kviitung on allkirjastatud agendi privaat-ed25519 võtmega. Auditeerijal on ainult avalik võti. Kas auditeerija saab kviitungit võrguühenduseta kontrollida?
2. Ründaja muudab kviitungi välja policy_id, väites, et seda valitses lubavam poliitika. Allkiri oli tehtud originaalse maketi üle. Mis juhtub kontrollimise käigus?
3. Miks kviitung sisaldab tool_args_hash ja result_hash selle asemel, et katta otse argumendid ja tulemuse?
4. Väli previous_receipt_hash seob iga kviitungi eelmisega. Kui ründaja vaikides kustutab ühe kviitungi ahela keskelt, mis muutub kehtetuks?
5. Kviitung kontrollib korrektselt. Kas see tõendab, et agendi tegevus oli õige, loogiline või poliitikaga kooskõlas?
Ava code_samples/18-signed-receipts.ipynb ja lõpeta kõik neli osa:
Lisaväljakutse 1: laienda kviitungi skeemi omavalitud lisaväljaga (näiteks päringu ID jälgimiseks), uuenda kanonilise allkirjastamise loogikat, et see sisaldaks seda, ja kinnita, et kviitung läbib kontrolli hästi. Seejärel muuda välja pärast allkirjastamist ja kinnita, et kontroll ebaõnnestub. See sunnib mõistma, kuidas iga bait kanonilises kodeeringus allkirjale kaasa aitab. Väljakutse 2: SHA-256-tehke kahe oma tšeki räsi kokku (ühendades nende kanonilised baidid deterministlikus järjekorras) ja lisage saadud digesto kolmanda tšeki uue väljana enne selle allkirjastamist. Kontrollige, et kõik kolm tšeki ikka ümberringi käivad. Olete just loonud üheastmelise kaasamise tõendi: igaüks, kellel on kolmas tšekk, suudab tõestada, et kaks esimest eksisteerisid selle allkirjastamise ajal, ilma nende sisu avaldamata. See on mustrit, mida kasutatakse selektiivse avalikustamise tšekkidel suuremas mahus (Merkle kohustused, RFC 6962).
Krüptograafilised tšekid annavad tehisintellekti agentidele auditeerimise jälje, mis on:
Need ei asenda sisendi valideerimist, poliitika täitmist ega identiteedistruktuuri. Nad on nende kihtide alus. Kui rakendate agente reguleeritud töökoormatesse, mitmeorganisatsioonilistesse töövoogudesse või igasse keskkonda, kus tulevikus auditeerijat ei saa eeldada teid usaldavat, siis tšekid on see, kuidas muuta auditeerimise jälg ausaks.
Kõige olulisem järeldus: tšekid tõestavad, kes ütles mida ja millal. Need ei tõesta, et öeldu oli tõene või õige. Hoidke seda erinevust kindlalt. See on ausa päritolusüsteemi ja eksitava vahel vahe.
Kui olete valmis sellest tunnist edasi minema ja rakendama tšekkidega signeeritud agente reaalses keskkonnas:
https://your-org.example.com/.well-known/agent-keys.json.Liituge Microsoft Foundry Discordiga, et kohtuda teiste õppijatega, osaleda töötubades ja saada oma AI agentide küsimustele vastused.
See tund käsitleb ühe tšeki allkirjastamist ja räsi-ahelaga järjestusi. Samad primitiivid koonduvad mitmeks keerukamaks mustriks, millega võite kokku puutuda, kui teie juhtimispraktika areneb:
authorization_*) ja pärast täitmist (result_*) sõltumatuteks osadeks, mõlemas oma allkirjaga, mis sobib olukordades, kus volituse otsus ja täidetud tulemus on tehtud erinevate osapoolte või erineval ajal. See kombineerub lisaks selle tunni tšekiivormingule.result_hash-i. Reaalmaailma koormused on sageli rikkalikumad kui ühe tööriista kõne tulemus: eelloogika (mudeli prognoos, kaalutud valikud, tõendid ja nende täielikkus, riskipositsioon, vastutusahela otsus) võib kõik elada koormuses, mida lukustab üks tšekk. See hoiab tšeki formaadi minimaalsena ja võimaldab koormuse skeemidel areneda domeen järgi.signature.alg võib kanda ML-DSA-65 (NISTi postkvantallkirjastandard), kui on tarvis migratsiooni. Planeerige üleminiperiood, kus tšekid on kaheahelalised.Arvutikasutusagentide loomine (CUA)
(Määrab õppekava haldur)
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.