Watch the lesson video: Osiguravanje AI agenata pomoću kriptografskih potvrda
(Video lekcije i sličica bit će dodani od strane Microsoftova sadržajnog tima nakon spajanja, u skladu sa šablonom lekcija 14 / 15.)
Ova lekcija će obuhvatiti:
Nakon završetka ove lekcije znat ćete kako:
Zamislite da ste implementirali AI agenta za Contoso Travel. Agent čita korisničke zahtjeve, poziva API za letove da pronađe opcije i rezervira sjedala u ime korisnika. Prošlog kvartala agent je obradio 50.000 rezervacija.
Danas dolazi revizor. Postavlja jednostavno pitanje: „Pokažite mi što je vaš agent napravio.“
Vi predajete zapisnike. Revizor ih pregleda i postavlja teže pitanje: „Kako znam da zapisnici nisu uređivani?“
To je problem audit-traila. Većina današnjih implementacija agenata oslanja se na:
Nijedan od ovih ne može odgovoriti revizoru bez da on mora nekome vjerovati (vama, vašem cloud pružatelju usluge, dobavljaču baze podataka). Za internu uporabu često je povjerenje prihvatljivo. Za regulirane radne opterećenja (financije, zdravstvo, sve pod EU AI Aktom), nije.
Kriptografske potvrde rješavaju ovaj problem tako što svaku akciju agenta čine neovisno provjerljivom. Revizor vam ne mora vjerovati. 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[Izgradi teret računa]
B --> C[Kanoniciraj JSON RFC 8785]
C --> D[SHA-256 hash]
D --> E[Ed25519 potpis]
E --> F[Racun s potpisom]
F --> G[Revizor provjerava izvan mreže]
G --> H{Potpis važi?}
H -- da --> I[Dokaz zaštićen od manipulacije]
H -- ne --> J[Racun 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 ključni posao:
Potpis. Potvrdu potpisuje gateway agenta koristeći Ed25519 privatni ključ. Svako tko ima odgovarajući javni ključ može offline provjeriti potpis. Svaka promjena polja poništava potpis.
Kanoničko kodiranje. Prije potpisivanja potvrda se serijalizira koristeći JSON Canonicalization Scheme (JCS, RFC 8785). To osigurava da dvije implementacije koje proizvode istu logičku potvrdu daju identičan bajt-izlaz. Bez kanonizacije različiti JSON serijalizatori proizveli bi različite potpise za isti sadržaj.
Hash povezivanje. Polje previous_receipt_hash povezuje svaku potvrdu sa prethodnom. Uklanjanje ili promjena redoslijeda jedne potvrde razbija svaku kasniju potvrdu. Manipulacija postaje vidljiva na razini lanca čak i ako se pojedinačni potpisi zaobiđu.
Zajedno ova svojstva daju tri jamstva:
Ne trebate posebnu biblioteku za proizvodnju potvrde. Kriptografski primitivci su široko dostupni, a logika je nekoliko desetaka linija Pythona.
Praktične vježbe u code_samples/18-signed-receipts.ipynb vode vas kroz cijeli proces. Rezimirano:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # RFC 8785 kanonički 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()}"
# Generirajte ili učitajte ključ za potpisivanje (u produkciji, spremite u ključni trezor)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Izgradite teret računa (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,
}
# Kanonizirajte, hashirajte, potpišite.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Priložite strukturirani objekt potpisa.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
To je cijeli tok potpisivanja. Vježbe u bilježnici vode kroz svaki korak.
Provjera je obrnuta 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 teret koji je zapravo potpisan (sve osim potpisa).
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
Ova funkcija prima potvrdu i vraća True ako je potpis valjan, inače False. Nema mrežnih poziva, nema ovisnosti o uslugama, ni potrebe za pouzdanjem u treću stranu.
Da vidite otkrivanje manipulacije u praksi, bilježnica vodi kroz:
tool_args_hash.Ovo je praktičan dokaz da su potvrde otporne na manipulaciju: bilo koja promjena, koliko god mala, razbija potpis.
Jedna potpisana potvrda štiti jednu akciju. Lanac potvrda štiti niz.
flowchart LR
R0[Potvrda 0<br/>geneza] --> R1[Potvrda 1]
R1 --> R2[Potvrda 2]
R2 --> R3[Potvrda 3]
R1 -. prethodni_hash_potvrde .-> R0
R2 -. prethodni_hash_potvrde .-> R1
R3 -. prethodni_hash_potvrde .-> R2
Svaka potvrda bilježi hash prethodne potvrde. Da napadač tiho ukloni potvrdu 2, morao bi:
previous_receipt_hash u potvrdi 3 (to narušava potpis potvrde 3), ILIAko je privatni ključ u hardverskom sigurnosnom spremištu i ako objavljujete javni ključ uz svaku potvrdu, nijedan od tih napada nije izvediv bez otkrivanja.
Bilježnica vodi kroz:
previous_receipt_hash svake potvrde odgovara stvarnom hashu prethodne potvrde.Tako proizvodite audit-trail koji vanjski revizor može provjeriti bez potrebe za povjerenjem u vas.
Ovo je najvažniji dio ove lekcije. Potvrde su moćne, ali moć im je ograničena.
Potvrde dokazuju tri stvari:
Potvrde NE dokazuju:
policy_id stvarno evaluirana ili da bi dopustila ovu akciju ako bi se provjeravala. Potvrda bilježi što je tvrdnjeno, a ne što je provođeno.Ova granica je važna iz dva razloga:
Česta je pogreška pretpostaviti da „imamo potvrde“ znači „podliježemo upravljanju“. Ne znači. Potvrde su temelj. Upravljanje je sustav koji gradite na njemu.
Python kod u ovoj lekciji je namjerno minimalan kako biste mogli pročitati svaku liniju i razumjeti točno što se događa. U produkciji imate dvije opcije:
Graditi direktno na kriptografskim primitivima. Spomenutih 50 redaka je često dovoljno za mnoge slučajeve. PyNaCl (Ed25519) i paket jcs (kanonički JSON) su dobro održavane i revidirane biblioteke.
Koristiti produkcijsku biblioteku za potvrde. Nekoliko open-source projekata implementira isti obrazac s dodatnim značajkama (rotacija ključeva, serijska provjera, distribucija JWK seta, integracija s policijskim motorima):
draft-farley-acta-signed-receipts) koji je u procesu standardizacije.protect-mcp (npm) i @veritasacta/verify (npm) pružaju Node implementaciju potpisivanja potvrda i offline provjere, namijenjene za omatanje bilo kojeg MCP servera tamper-evident audit trailom.Odluka između vlastite implementacije i biblioteke slična je odluci između pisanja vlastite JWT biblioteke i korištenja testirane: oba su prikladna; biblioteka štedi vrijeme i smanjuje površinu revizije; vlastita implementacija tjera vas da razumijete svaki primitiv. Ova lekcija podučava vlastiti pristup da imate temelj za bilo koji izbor.
Testirajte razumijevanje prije prelaska na vježbu.
1. Potvrda je potpisana privatnim Ed25519 ključem agenta. Revizor ima samo javni ključ. Može li revizor verificirati potvrdu offline?
2. Napadač izmijeni polje policy_id potvrde kako bi tvrdio da je nadzirana permisivnijom politikom. Potpis je bio nad originalnim sadržajem. Što se dogodi pri provjeri?
3. Zašto potvrda uključuje tool_args_hash i result_hash umjesto sirovih argumenata i rezultata?
4. Polje previous_receipt_hash povezuje svaku potvrdu s prethodnom. Ako napadač tiho izbriše jednu potvrdu iz sredine lanca, što postaje nevažeće?
5. Potvrda se uspješno verificira. Dokazuje li to da je akcija agenta bila točna, valjana ili u skladu s politikom?
Otvorite code_samples/18-signed-receipts.ipynb i dovršite sva četiri dijela:
Izazov za dodatni rad 1: proširite shemu potvrde s dodatnim poljem po vlastitom izboru (npr. ID zahtjeva za praćenje), ažurirajte kanoničku logiku potpisivanja da ga uključi i potvrdite da potvrda i dalje prolazi provjeru bez problema. Zatim izmijenite polje nakon potpisivanja i potvrdite da provjera ne uspijeva. Ovo vas prisiljava da razumijete kako svaki bajt kanoničkog kodiranja doprinosi potpisu. Izazov za rastezanje 2: SHA-256-hash-ajte zajedno dva svoja računa (spojite njihove kanonske bajtove u determinističkom redoslijedu) i ugurajte dobiveni sažetak kao novo polje na treći račun prije potpisivanja. Provjerite da sva tri računa i dalje prolaze provjeru. Upravo ste izgradili dokaz uključivanja u jednom koraku: bilo tko tko posjeduje treći račun može dokazati da su prva dva postojala u vrijeme njezinog potpisivanja, bez potrebe da otkriva njihov sadržaj. Ovo je obrazac koji računi s selektivnim otkrivanjem koriste u velikom opsegu (Merkle obveze, RFC 6962).
Kriptografski računi daju AI agentima zapisnik revizije koji je:
Nisu zamjena za validaciju ulaza, provođenje politike ili infrastrukturu identiteta. Oni su temelj za te slojeve. Kada uvodite agente u regulirane radne zadatke, višestruke organizacijske tokove rada ili bilo koje okruženje gdje se ne može pretpostaviti povjerenje budućeg revizora, računi su način na koji činite zapisnik revizije poštenim.
Najvažnija poruka: 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 poštenog sustava podrijetla i zavaravajućeg.
Kada ste spremni prijeći iz ovog poglavlja u implementaciju agenata potpisanih računima u stvarnom okruženju:
https://your-org.example.com/.well-known/agent-keys.json.Pridružite se Microsoft Foundry Discordu za susret s drugim polaznicima, sudjelovanje na radnim satima i dobivanje odgovora na pitanja o AI agentima.
Ovo poglavlje pokriva potpisivanje pojedinačnih računa i nizove hashiranih lanaca. Isti primitivni elementi čine nekoliko naprednijih obrazaca na koje možete naići kako vaš upravljački okvir sazrijeva:
authorization_*) i poslije izvršenja (result_*) s neovisnim potpisima, korisno kada odluku o ovlaštenju i promatrani rezultat donose različiti akteri ili u različito vrijeme. Ovo se može aditivno složiti na format računa naučen u ovom poglavlju.result_hash. Pravi sadržaji često su bogatiji od rezultata jednog poziva alata: razlozi pred donošenjem odluke (predviđanje modela, razmotrene opcije, dokazi i njihova potpunost, položaj rizika, lanac odgovornosti, rezultat vrata) mogu svi živjeti unutar sadržaja, zatvoreni jednim računom. Ovo drži format računa minimalnim dok dopušta da se sheme sadržaja razvijaju ovisno o domenu.signature.alg može sadržavati ML-DSA-65 (NIST standard za potpise nakon kvantnog doba) kada trebate migrirati. Planirajte prijelazno razdoblje u kojem se računi potpisuju dvostruko.Izgradnja agenata za korištenje računala (CUA)
(Bit će određeno od strane održavatelja kurikuluma)
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.