Gledajte video lekciju: Osiguravanje AI agenata kriptografskim potvrdom
(Video lekcija i sličica bit će dodani od strane Microsoftovog sadržajnog tima nakon spajanja, u skladu s obrascem lekcija 14 / 15.)
Ova lekcija obuhvatit će:
Nakon završetka ove lekcije, znat ćete kako:
Zamislite da ste implementirali AI agenta za Contoso Travel. Agent čita zahtjeve korisnika, poziva API za letove kako bi potražio opcije i rezervira sjedala u ime korisnika. Prošli kvartal agent je obradio 50.000 rezervacija.
Danas dolazi revizor. Postavlja jednostavno pitanje: “Pokažite mi što je vaš agent radio.”
Predajete mu svoje zapisnike. Revizor ih pregleda i postavlja teže pitanje: “Kako znam da ti zapisnici nisu uređivani?”
Ovo je problem audit staze. Većina današnjih implementacija agenata oslanja se na:
Nijedan od ovih ne može odgovoriti revizorovom pitanju bez zahtjeva da revizor nekome vjeruje (vama, vašem cloud pružatelju ili dobavljaču baze podataka). Za internu upotrebu, to povjerenje je često prihvatljivo. Za regulirane poslove (financije, zdravstvo, sve prema EU AI Aktu) nije.
Kriptografske potvrde rješavaju ovaj problem tako što svaku radnju agenta čine neovisno provjerljivom. Revizoru ne treba vjerovati vama. Treba mu samo vaš javni ključ i sama potvrda.
Potvrda je JSON objekt koji bilježi što je agent napravio, potpisan digitalnim potpisom.
flowchart LR
A[Agent poziva alat] --> B[Izgraditi teretni dio računa]
B --> C[Kanonizirati JSON RFC 8785]
C --> E[Ed25519 potpisati kanoničke bajtove]
E --> F[Račun s potpisom]
F --> G[Auditor provjerava izvan mreže]
G --> H{Potpis valjan?}
H -- yes --> I[Dokaz protiv manipulacija]
H -- no --> J[Račun odbijen]
Minimalna potvrda izgleda ovako:
{
"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..."
}
}
Tri svojstva obavljaju posao:
Potpis. Potvrdu potpisuje agentov gateway koristeći Ed25519 privatni ključ. Svako tko ima odgovarajući javni ključ može provjeriti potpis offline. Svaka manipulacija bilo kojim poljem poništava potpis.
Kanonsko kodiranje. Prije potpisivanja potvrda se serijalizira koristeći JSON Canonicalization Scheme (JCS, RFC 8785). Ovo osigurava da dvije implementacije koje proizvode isti logički sadržaj daju identičan niz bajtova. Bez kanonizacije, različiti JSON serijalizatori bi proizvodili različite potpise za isti sadržaj.
Lančano hashiranje. Polje previous_receipt_hash povezuje svaku potvrdu s prethodnom. Uklanjanje ili promjena redoslijeda potvrde prekida sve potvrde koje slijede. Manipulacija postaje vidljiva na razini lanca, čak i ako se pojedinačni potpisi zaobiđu.
Zajedno ova svojstva pružaju tri jamstva:
Ne trebate posebnu biblioteku za proizvodnju potvrde. Kriptografske primitive su široko dostupne, a logika je nekoliko desetaka linija Python koda.
Praktični zadaci u code_samples/18-signed-receipts.ipynb prolaze kroz cijeli tijek. Sažetak:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # RFC 8785 kanonski 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()}"
# Generiraj ili učitaj potpisni ključ (u produkciji, spremi u spremište ključeva)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Izgradi podatke primitka (još bez potpisa)
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,
}
# Kanoniziraj i potpiši JCS bajtove izravno. PureEdDSA interno hešira.
canonical_bytes = canonicalize(payload)
signature_bytes = signing_key.sign(canonical_bytes).signature
# Priloži strukturirani objekt potpisa.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
To je cijeli pipeline potpisivanja. Zadatci u bilježnici vode kroz svaki korak.
Provjera je inverzna operacija:
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:
# Potpis je strukturirani objekt: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Rekonstruirajte sadržaj koji je zapravo potpisan (sve osim potpisa).
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
Ova funkcija prima potvrdu i vraća True ako je potpis valjan, inače False. Nema mrežnog poziva, nema ovisnosti o usluzi, ne treba vjerovati nijednoj trećoj strani.
Za demonstraciju otkrivanja manipulacije, bilježnica prolazi kroz:
tool_args_hash.Ovo je praktičan dokaz da su potvrde otporne na manipulacije: svaka promjena, ma koliko mala, prekida potpis.
Jedna potpisana potvrda štiti jednu radnju. Lanac potvrda štiti niz radnji.
flowchart LR
R0[Račun 0<br/>geneza] --> R1[Račun 1]
R1 --> R2[Račun 2]
R2 --> R3[Račun 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Svaka potvrda bilježi hash prethodne potvrde. Da bi napadač tiho uklonio potvrdu 2, morao bi:
previous_receipt_hash potvrde 3 (time se prekida potpis potvrde 3), ILIAko je privatni ključ pohranjen u hardverskom sigurnosnom uređaju, a javni ključ se objavljuje uz svaku potvrdu, nijedan od tih napada nije izvediv bez otkrivanja.
Bilježnica prolazi kroz:
previous_receipt_hash svake potvrde odgovara stvarnom hashu prethodne potvrde.Ovo je način da proizvedete audit stazu koju vanjski revizor može verificirati bez povjerenja u vas.
Ovo je najvažniji dio ove lekcije. Potvrde su moćne, ali njihova moć je ograničena.
Potvrde dokazuju tri stvari:
Potvrde NE dokazuju:
policy_id stvarno procijenjena ili da bi dopustila tu radnju ako bi se provjeravala. Potvrda bilježi ono što je tvrdnjeno, a ne ono što je provedeno.Ova je granica važna iz dva razloga:
Česta pogreška je pretpostaviti da “imamo potvrde” znači “mi smo regulirani.” Ne znači. Potvrde su temelj. Upravljački sustav je ono što gradite na tom temelju.
Stavka 3 iznad zaslužuje svoj odjeljak: potvrda radnje kaže “ovaj ključ je potpisao ovaj sadržaj,” nikada ne kaže “čovjek je odobrio ovo.” Za radnje visokog rizika (povrati, brisanja, prijenosi novca), okviri upravljanja sve češće zahtijevaju upravo tu izostalu tvrdnju, a ona se može proizvesti istim primitivima koje ste već izgradili u ovoj lekciji.
Sljedeća bilježnica code_samples/human-authorization-receipts.ipynb dodaje drugi tip potvrde, human.approval.v1, u istom omotu kao i lekcijske potvrde (tipizirani payload potpisan Ed25519 na njegovim kanonskim JCS bajtovima, s objektom signature izvan potpisanih bajtova). Nazvani odobravatelj potpisuje punu kanonsku radnju i njegov sažetak prije izvršenja; potvrda radnje agenta nosi ista sažetak radnje i parent_approval_ref, receipt_hash odobrenja, istu konvenciju kao previous_receipt_hash u lancu koji ste gore napravili. Jedan verify_chain vodi oba artefakta pod odvojenim registrima pričvršćenih ključeva (ključevi odobravatelja vs ključevi agenta), tako da je kodni put zajednički, ali autoriteti nikada nisu.
Kupljeno svojstvo, pažljivo izraženo: čovjek je odobrio točnu ovu radnju, a agent je izvršio upravo tu odobrenu radnju. Refuzni primjeri u bilježnici čine ovo svojstvo stvarnim, a ne samo tvrdnjom:
Svaki neuspjeh odbija s drugačijim razlogom, pa revizor čitajući odbijanje može reći je li autoritet istekao ili je izvršena radnja promijenjena. Pravilo koje bilježnica podučava: potpisano odobrenje samo po sebi nije autoritet. Autoritet postoji samo ako se obje potvrde još vežu za istu kanonsku radnju u vrijeme izvršenja. Potvrda ljudskog odobrenja je obrazovni sastav definiran ovom lekcijom, ne tip potvrde definiran u draft-farley-acta-signed-receipts.
Python kod u ovoj lekciji namjerno je minimalan da možete pročitati svaku liniju i razumjeti točno što se događa. U produkciji imate dvije opcije:
Graditi direktno na kriptografskim primitivima. 50 linija iznad dovoljno je za mnoge upotrebe. PyNaCl (Ed25519) i paket jcs (kanonski JSON) su dobro održavane i auditirane biblioteke.
Koristiti produkcijsku biblioteku za potvrde. Nekoliko open-source projekata implementira isti uzorak s dodatnim značajkama (rotacija ključeva, serijska provjera, distribucija JWK seta, integracija s politikama):
draft-farley-acta-signed-receipts, revizija 02). Lekcija pruža plitku edukativnu potvrdu koja se razlikuje od nacrta {payload, signature} omota i ne predstavlja konformnu implementaciju. Nacrt objavljuje zajednički niz test vektora (agent-governance-testvectors) za implementacije koje ciljaju njegov wire format.protect-mcp (npm) i @veritasacta/verify (npm) pružaju Node implementaciju potpisivanja i offline provjere potvrda, namijenjenu obavijanju bilo kojeg MCP servera s otkrivajućom audit stazom, uključujući tijek držanja za zajednički potpis u kojem pauzirana radnja emitira potvrdu odobrenja vezanu uz sažetak radnje (WebAuthn-podržan u desktop tijeku), isti obrazac potvrde odobrenja kao u ljudskom odobrenju bilježnice gore.pip install nobulex) pruža isti Ed25519 + JCS uzorak potpisivanja u Pythonu s LangChain i CrewAI integracijama, uključujući objavljene test vektore za međusobnu provjeru i mapiranje usklađenosti dodano preko OWASP PR #2210.Odluka između izrade vlastitog i korištenja biblioteke podsjeća na odluku između pisanja vlastite JWT biblioteke i korištenja testirane: oba su razumna; biblioteka štedi vrijeme i smanjuje površinu za reviziju; pristup od nule prisiljava vas da razumijete svaki primitiv. Ova lekcija podučava put od nule da biste imali temelj za oba izbora.
Testirajte svoje razumijevanje prije prelaska na praktični zadatak.
1. Potvrda je potpisana agentovim privatnim Ed25519 ključem. Revizor ima samo javni ključ. Može li revizor potvrdu verificirati offline?
2. Napadač modificira polje policy_id potvrde tvrdeći da je potvrda bila regulirana blažom politikom. Potpis je bio nad originalnim payloadom. Što se događa tijekom provjere?
3. Zašto račun uključuje tool_args_hash i result_hash umjesto sirovih argumenata i rezultata?
4. Polje previous_receipt_hash povezuje svaki račun s prethodnikom. Ako napadač tiho izbriše jedan račun iz sredine lanca, što postaje nevažeće?
5. Račun je valjano verificiran. Dokazuje li to da je akcija agenta bila ispravna, valjana ili u skladu s pravilima?
Otvorite code_samples/18-signed-receipts.ipynb i dovršite sva četiri dijela:
Izazov 1 za proširenje: proširite shemu računa dodatnim poljem po vlastitom izboru (na primjer, ID zahtjeva za praćenje), ažurirajte logiku kanonskog potpisivanja da ga uključi i potvrdite da račun i dalje prolazi kroz verifikaciju. Zatim izmijenite polje nakon potpisivanja i potvrdite da provjera ne uspijeva. Ovo vas prisiljava da shvatite kako svaki bajt kanonskog kodiranja doprinosi potpisu.
Izazov 2 za proširenje: izračunajte SHA-256 hash sažetka dva svoja računa (kombinirajte njihove kanonske bajtove u determinističkom redoslijedu) i ugurajte dobiveni sažetak kao novo polje u treći račun prije potpisivanja. Potvrdite da sva tri računa i dalje prolaze kroz potpisivanje i verifikaciju. Upravo ste izgradili dokaz uključenja u jednom koraku: svatko tko drži treći račun može dokazati da su prva dva postojala u trenutku potpisivanja, bez potrebe da otkriva njihov sadržaj. Ovo je obrazac koji računi selektivnog otkrivanja koriste u velikoj mjeri (Merkleova obećanja, RFC 6962).
Kriptografski računi daju AI agentima revizijski trag koji je:
Oni nisu zamjena za validaciju ulaza, provođenje pravila ili identitetsku infrastrukturu. Oni su temelj za te slojeve. Kada implementirate agente u regulirana okruženja, u tijekove rada s više organizacija ili u bilo kojem postavkama gdje se ne može pretpostaviti da će vas budući revizor vjerovati, računi su način kako održati revizijski trag iskrenim.
Najvažnija pouka: računi dokazuju tko je što rekao i kada. Ne dokazuju da je ono što je rečeno istinito ili ispravno. Držite tu razliku čvrsto. To je razlika između iskrenog i obmanjujućeg sustava podrijetla.
Kad ste spremni preći s ove lekcije na implementaciju agenata s potpisanim računima u stvarnom okruženju:
https://your-org.example.com/.well-known/agent-keys.json.Pridružite se Microsoft Foundry Discord da upoznate druge učenike, sudjelujete u uredu za pitanja i dobijete odgovore na pitanja o AI agentima.
Ova lekcija pokriva potpisivanje pojedinačnih računa i sekvence povezane hashom. Isti primitivni dijelovi tvore nekoliko naprednijih obrazaca koje možete susresti kako vaša upravljačka praksa sazrijeva:
authorization_*) i postizvršnu (result_*) polovicu s neovisnim potpisima, korisno kada odluku o autorizaciji i opaženi rezultat donose različiti akteri ili u različito vrijeme. Ovo se aditivno nadograđuje na format računa iz ove lekcije.result_hash. Stvarni primjeri opterećenja često su bogatiji od rezultata pojedinačnog poziva alatu: pred-racionalizacija (predviđanje modela, razmotrene opcije, dokazi i njihova potpunost, rizik, lanac odgovornosti, ishod čvora) može biti unutar opterećenja, zatvorenog jednim računom. Ovo održava format računa minimalnim dok dopušta evoluciju shema opterećenja po domenama.signature.alg može sadržavati ML-DSA-65 (NIST post-kvantni standard potpisa) kad je migracija potrebna. Planirajte razdoblje prijelaza u kojem su računi dvostruko potpisani.Napomena: Ovaj dokument je preveden korištenjem AI prevoditeljskog servisa Co-op Translator. Iako težimo točnosti, imajte na umu da automatski prijevodi mogu sadržavati greške ili netočnosti. Izvorni dokument na izvornom jeziku treba smatrati autoritativnim izvorom. Za važne informacije preporuča se profesionalni ljudski prijevod. Nismo odgovorni za bilo kakva nesporazumevanja ili pogrešne interpretacije koje proizlaze iz korištenja ovog prijevoda.