Urmăriți videoclipul lecției: Securizarea agenților AI cu chitanțe criptografice
(Videoclipul lecției și miniatura vor fi adăugate de echipa Microsoft de conținut după îmbinare, potrivindu-se cu modelul lecțiilor 14 / 15.)
Această lecție va acoperi:
După ce parcurgeți această lecție, veți ști cum să:
Imaginați-vă că ați implementat un agent AI pentru Contoso Travel. Agentul citește solicitările clienților, apelează un API de zboruri pentru a căuta opțiuni și rezervă locuri în numele clientului. În ultimul trimestru, agentul a procesat 50.000 de rezervări.
Astăzi sosește un auditor. El pune o întrebare simplă: “Arătați-mi ce a făcut agentul dvs.”
Îi oferiți fișierele dvs. de jurnal. Auditorul le analizează și pune o întrebare mai dificilă: “Cum știu că aceste jurnale nu au fost modificate?”
Aceasta este problema traseului de audit. Majoritatea implementărilor agenților astăzi se bazează pe:
Niciuna dintre acestea nu poate răspunde la întrebarea auditorului fără ca auditorul să aibă încredere în cineva (dumneavoastră, furnizorul cloud, un furnizor de baze de date). Pentru uz intern, această încredere este adesea acceptabilă. Pentru sarcini reglementate (finanțe, sănătate, orice supus Regulamentului AI al UE), nu este.
Chitanțele criptografice rezolvă această problemă făcând fiecare acțiune a agentului verificabilă independent. Auditorul nu trebuie să aibă încredere în dumneavoastră. Are nevoie doar de cheia dvs. publică și de chitanță.
O chitanță este un obiect JSON care înregistrează ce a făcut agentul, semnat cu o semnătură digitală.
flowchart LR
A[Agentul invocă un instrument] --> B[Construiește încărcătura chitantei]
B --> C[Canonizează JSON RFC 8785]
C --> D[Hash SHA-256]
D --> E[Semnează Ed25519]
E --> F[Chitanță cu semnătură]
F --> G[Auditorul verifică offline]
G --> H{Semnătura este validă?}
H -- da --> I[Dovadă evidentă de manipulare]
H -- nu --> J[Chitanță respinsă]
O chitanță minimală arată astfel:
{
"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..."
}
}
Trei proprietăți fac întreaga muncă:
Semnătura. Chitanța este semnată de gateway-ul agentului folosind o cheie privată Ed25519. Oricine are cheia publică corespunzătoare poate verifica semnătura offline. Orice modificare a unui câmp invalidă semnătura.
Codificare canonică. Înainte de semnare, chitanța este serializată folosind JSON Canonicalization Scheme (JCS, RFC 8785). Acest lucru asigură că două implementări care produc aceeași chitanță logică produc ieșire identică la nivel de octeți. Fără canonicizare, diferite serializatoare JSON ar produce semnături diferite pentru același conținut.
Lanțuire prin hash. Câmpul previous_receipt_hash leagă fiecare chitanță de cea precedentă. Ștergerea sau reordonarea unei chitanțe rupe toate chitanțele care vin după ea. Modificările neautorizate devin vizibile la nivel de lanț chiar dacă semnăturile individuale sunt ocolite.
Împreună, aceste proprietăți oferă trei garanții:
Nu aveți nevoie de o bibliotecă specială pentru a produce o chitanță. Primitivele criptografice sunt larg disponibile, iar logica este doar câteva zeci de linii de Python.
Exercițiile practice din code_samples/18-signed-receipts.ipynb parcurg întregul flux. Versiunea rezumată:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # JSON canonic 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()}"
# Generează sau încarcă o cheie de semnare (în producție, stochează într-un seif pentru chei)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Construiește sarcina utilă a chitanței (încă fără semnătură)
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,
}
# Canonicalizează, aplică hash, semnează.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Atașează un obiect de semnătură structurat.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
Aceasta este întreaga linie de semnare. Exercițiile din notebook parcurg fiecare pas.
Verificarea este operația inversă:
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:
# Semnătura este un obiect structurat: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Reconstruiește sarcina utilă care a fost de fapt semnată (totul în afară de semnătură).
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
Această funcție primește o chitanță și returnează True dacă semnătura este validă, False altfel. Fără apel rețea, fără dependență de serviciu, fără nevoie de încredere într-o terță parte.
Pentru a vedea detectarea modificărilor în acțiune, notebook-ul parcurge:
tool_args_hash.Aceasta este demonstrația practică că chitanțele sunt evidente pentru modificări: orice modificare, oricât de mică, rupe semnătura.
O singură chitanță semnată protejează o singură acțiune. Un lanț de chitanțe protejează o secvență.
flowchart LR
R0[Chitanță 0<br/>genesis] --> R1[Chitanță 1]
R1 --> R2[Chitanță 2]
R2 --> R3[Chitanță 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Fiecare chitanță înregistrează hashul chitanței anterioare. Pentru a elimina silențios chitanța 2, un atacator ar trebui să:
previous_receipt_hash al chitanței 3 (care rupe semnătura chitanței 3), SAUDacă cheia privată este stocată într-un hardware key vault și publicați cheia publică cu fiecare chitanță, niciunul dintre atacuri nu este fezabil fără detectare.
Notebook-ul parcurge:
previous_receipt_hash al fiecărei chitanțe corespunde cu hashul real al chitanței anterioare.Așa produceți un traseu de audit pe care un auditor extern îl poate verifica fără să aibă încredere în dumneavoastră.
Aceasta este cea mai importantă secțiune a lecției. Chitanțele sunt puternice, dar puterea lor este limitată.
Chitanțele dovedesc trei lucruri:
Chitanțele NU dovedesc:
policy_id a fost evaluată sau că ar fi permis această acțiune dacă ar fi fost verificată. Chitanța înregistrează ce s-a pretins, nu ce a fost aplicat.Această limită contează din două motive:
O greșeală frecventă este să asumați că “avem chitanțe” înseamnă “suntem guvernați.” Nu este așa. Chitanțele sunt o fundație. Guvernanța este sistemul pe care îl construiți deasupra.
Codul Python din această lecție este intenționat minimal pentru ca să puteți citi fiecare linie și să înțelegeți exact ce se întâmplă. În producție, aveți două opțiuni:
Construiți direct pe primitivele criptografice. Cele 50 de linii pe care le-ați văzut mai sus sunt suficiente pentru multe cazuri de utilizare. PyNaCl (Ed25519) și pachetul jcs (JSON canonic) sunt biblioteci bine întreținute și auditate.
Folosiți o bibliotecă de producție pentru chitanțe. Mai multe proiecte open-source implementează același model cu funcționalități suplimentare (rotirea cheilor, verificare în batch, distribuție JWK Set, integrare cu motoare de politici):
draft-farley-acta-signed-receipts) aflat în proces de standardizare.protect-mcp (npm) și @veritasacta/verify (npm) oferă o implementare Node de semnare a chitanțelor și verificare offline, destinată să învăluie orice server MCP cu un traseu de audit evident modificărilor.Decizia între a vă face singur și a folosi o bibliotecă seamănă cu decizia de a scrie propria bibliotecă JWT sau de a folosi una testată: ambele sunt rezonabile; biblioteca economisește timp și reduce suprafața de audit; abordarea from-scratch vă forțează să înțelegeți fiecare primitiv. Această lecție predă calea from-scratch astfel încât să aveți baza pentru oricare alegere.
Testați-vă înțelegerea înainte de a trece la exercițiul practic.
1. O chitanță este semnată cu cheia privată Ed25519 a agentului. Auditorul are doar cheia publică. Poate auditorul să verifice chitanța offline?
2. Un atacator modifică câmpul policy_id al unei chitanțe pentru a pretinde că a fost guvernat de o politică mai permisivă. Semnătura a fost făcută peste payload-ul original. Ce se întâmplă la verificare?
3. De ce include chitanța un tool_args_hash și un result_hash în loc să conțină argumentele și rezultatul brute?
4. Câmpul previous_receipt_hash leagă fiecare chitanță de precedenta sa. Dacă un atacator șterge silențios o chitanță din mijlocul lanțului, ce devine invalid?
5. O chitanță se verifică corect. Dovedește asta că acțiunea agentului a fost corectă, solidă sau conformă cu politica?
Deschideți code_samples/18-signed-receipts.ipynb și finalizați toate cele patru secțiuni:
Provocare suplimentară 1: extinde schema chitanței cu un câmp suplimentar ales de tine (de exemplu, un ID de solicitare pentru trasabilitate), actualizează logica canonică de semnare să îl includă și confirmă că chitanța încă trece prin verificare. Apoi modifică câmpul după semnare și confirmă că verificarea eșuează. Aceasta te forțează să înțelegi cum contribuie fiecare octet din codificarea canonică la semnătură. Provocare extinsă 2: Aplicați SHA-256 la două dintre chitanțele dvs. împreună (concatenați octeții canonici într-o ordine deterministă) și încorporați digestul rezultat ca un câmp nou pe o a treia chitanță înainte de a o semna. Verificați că toate cele trei chitanțe se pot verifica printr-un proces round-trip. Tocmai ați construit o probă de includere într-un singur pas: oricine deține a treia chitanță poate demonstra că primele două existau la momentul semnării, fără a fi nevoie să divulge conținutul lor. Acesta este modelul pe care îl folosesc chitanțele cu dezvăluire selectivă la scară (angajamente Merkle, RFC 6962).
Chitanțele criptografice oferă agenților AI un traseu de audit care este:
Ele nu sunt un substitut pentru validarea inputului, aplicarea politicii sau infrastructura de identitate. Ele sunt o bază pentru aceste straturi. Când implementați agenți în sarcini reglementate, fluxuri de lucru multi-organizaționale sau orice mediu în care un auditor viitor nu poate presupune că vă are încredere, chitanțele sunt modul în care faceți traseul de audit onest.
Cel mai important aspect: chitanțele dovedesc cine a spus ce și când. Ele nu demonstrează că ceea ce s-a spus este adevărat sau corect. Păstrați această distincție strictă. Este diferența dintre un sistem de proveniență onest și unul înșelător.
Când sunteți gata să treceți de la această lecție la implementarea agenților semnați cu chitanțe într-un mediu real:
https://your-org.example.com/.well-known/agent-keys.json.Alăturați-vă serverului Microsoft Foundry Discord pentru a întâlni alți cursanți, a participa la ore de consultanță și a vă clarifica întrebările despre Agenții AI.
Această lecție acoperă semnarea cu o singură chitanță și secvențe cu lanț hash. Aceleași primitive compun mai multe modele avansate pe care le puteți întâlni pe măsură ce postura dvs. de guvernanță se maturizează:
authorization_*) și post-execuție (result_*) cu semnături independente, utile când decizia de autorizare și rezultatul observat sunt produse de actori diferiți sau în momente diferite. Aceasta se adaugă peste formatul de chitanță predat în această lecție.result_hash. Încărcăturile din lumea reală sunt adesea mai bogate decât un simplu rezultat de apel: raționamente pre-decisionale (predicția modelului, opțiunile considerate, dovezile și gradul lor de completitudine, postura de risc, lanțul de responsabilitate, rezultatul blocajului) pot trăi toate în încărcătură, sigilate de o singură chitanță. Aceasta păstrează formatul chitanței minimal în timp ce permite evoluții ale schemelor de încărcătură pe domenii.signature.alg poate purta ML-DSA-65 (standardul NIST pentru semnături post-cuantic) când trebuie să migrați. Planificați o perioadă de tranziție în care chitanțele sunt semnate dublu.Construirea agenților pentru utilizarea calculatorului (CUA)
(Va fi decisă de administratorii curricula)
Declinare a responsabilității: Acest document a fost tradus folosind serviciul de traducere AI Co-op Translator. În timp ce ne străduim pentru acuratețe, vă rugăm să rețineți că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa nativă trebuie considerat sursa autorizată. Pentru informații critice, se recomandă traducerea profesională realizată de un om. Nu ne asumăm responsabilitatea pentru eventualele neînțelegeri sau interpretări greșite care decurg din utilizarea acestei traduceri.