Ogled video lekcije: Zavarovanje AI agentov s kriptografskimi potrdili
(Video lekcije in sličica bosta dodana s strani Microsoftovega vsebinskega tima po združitvi, skladno s predlogo lekcij 14 / 15.)
V tej lekciji bomo obravnavali:
Po zaključenem lekciji boste znali:
Predstavljajte si, da ste uvedli AI agenta za Contoso Travel. Agent bere zahteve strank, kliče API za lete, da poišče možnosti, in rezervira sedeže v imenu stranke. V preteklem četrtletju je agent obdelal 50.000 rezervacij.
Danes pride revizor in zastavi preprosto vprašanje: “Pokažite, kaj je vaš agent storil.”
Predate mu vaše dnevniške datoteke. Revizor jih pregleda in zastavi težje vprašanje: “Kako vem, da ti dnevniki niso bili urejeni?”
To je problem revizijske sledi. Večina današnjih implementacij agentov se zanaša na:
Noben od teh ne zna brez dodatnega zaupanja odgovoriti revizorju. Takšno zaupanje je za interno uporabo pogosto sprejemljivo, za regulirane delovne obremenitve (finančni sektor, zdravstvo, karkoli pod EU AI aktom) pa ni.
Kriptografska potrdila to rešujejo tako, da je vsako dejanje agenta neodvisno preverljivo. Revizor vam ne rabi zaupat. Potrebuje le vaš javni ključ in samo potrdilo.
Potrdilo je JSON objekt, ki beleži, kaj je agent storil, podpisan z digitalnim podpisom.
flowchart LR
A[Agent kliče orodje] --> B[Izgradi vsebino potrdila]
B --> C[Standardiziraj JSON RFC 8785]
C --> D[SHA-256 zgošček]
D --> E[Ed25519 podpis]
E --> F[Potrdilo s podpisom]
F --> G[Revizor preverja brez povezave]
G --> H{Je podpis veljaven?}
H -- da --> I[Dokazilo proti spreminjanju]
H -- ne --> J[Potrdilo zavrnjeno]
Minimalno potrdilo izgleda tako:
{
"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 lastnosti opravljajo delo:
Podpis. Potrdilo podpiše prehod (gateway) agenta s privatnim ključem Ed25519. Kdor ima pripadajoči javni ključ, lahko podpis potrdi brez povezave. Vsaka sprememba katerega koli polja razveljavi podpis.
Kanonično kodiranje. Pred podpisom je potrdilo serializirano s shemo kanonične JSON predstavitve (JCS, RFC 8785). To zagotavlja, da dve implementaciji, ki proizvedeta isto logično potrdilo, ustvarita bitno enak izhod. Brez kanonične predstavitve bi različni JSON serializerji ustvarili različne podpise za isto vsebino.
Veriga zgoščenk (hash chaining). Polje previous_receipt_hash povezuje vsako potrdilo s prejšnjim. Odstranitev ali premik potrdila prekine vsako potrdilo, ki sledi. Manipulacija je vidna na ravni verige, tudi če se posamezni podpisi obidejo.
Skupaj te lastnosti zagotavljajo tri jamstva:
Za izdelavo potrdila ne potrebujete posebne knjižnice. Kriptografski primitivni postopki so široko dostopni, logika je nekaj deset vrstic Pythona.
Praktične vaje v code_samples/18-signed-receipts.ipynb vodijo skozi celoten postopek. Povzetek:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # RFC 8785 kanonični 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()}"
# Ustvari ali naloži ključ za podpisovanje (v produkciji shranjuj v ključni zakladnici)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Sestavi vsebino potrdila (še brez podpisa)
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, zgoščuj, podpiši.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Priloži strukturiran objekt podpisa.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
To je celoten podpisni potek. Vaje v zvezku vodijo po vsakem koraku.
Potrditev je obratna 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:
# Podpis je strukturiran objekt: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Rekonstruirajte vsebino, ki je bila dejansko podpisana (vse razen podpisa).
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
Ta funkcija prejme potrdilo in vrne True, če je podpis veljaven, False sicer. Brez omrežnih klicev, brez storitvene odvisnosti, brez potrebe po zaupanju tretji strani.
Da vidite delovanje zaznavanja manipulacij, zvezek pokaže:
tool_args_hash.To je praktični dokaz, da so potrdila vidno zaščitena pred manipulacijo: vsaka, celo najmanjša sprememba, prekine podpis.
Eno podpisano potrdilo ščiti eno dejanje. Veriga potrdil ščiti zaporedje.
flowchart LR
R0[Prejemek 0<br/>genesis] --> R1[Prejemek 1]
R1 --> R2[Prejemek 2]
R2 --> R3[Prejemek 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Vsako potrdilo beleži zgoščenk prejšnjega. Da bi napadalec tiho odstranil potrdilo 2, bi moral:
previous_receipt_hash potrdila 3 (s tem bi podpis potrdila 3 postal neveljaven), ALIČe je zasebni ključ shranjen v strojni ključni shrambi in javni ključ objavite z vsakim potrdilom, noben napad ni izvedljiv brez zaznave.
Zvezek vodi skozi:
previous_receipt_hash vsakega potrdila ustreza dejanski zgoščeni vrednosti prejšnjega.Tako ustvarite revizijsko sled, ki jo lahko zunanji revizor preveri brez zaupanja v vas.
To je najpomembnejši del lekcije. Potrdila so močna, a njihova moč je omejena.
Potrdila dokazujejo tri stvari:
Potrdila NE dokazujejo:
policy_id dejansko ovrednotena ali bi dejansko dovolila dejanje, če bi jo preverili. Potrdilo beleži, kar se je trdilo, ne kar je bilo izvršeno.Ta meja je pomembna zaradi dveh razlogov:
Pogosta zmota je misliti, da “imamo potrdila” pomeni “imamo upravljanje in nadzor.” Ne pomeni. Potrdila so temelj. Upravljanje je sistem, ki ga zgradite na njem.
Python koda v tej lekciji je namerno minimalna, da lahko preberete vsako vrstico in razumete natanko, kaj se dogaja. V produkciji imate dve možnosti:
Gradite neposredno na kriptografskih primitivih. 50 vrstic kode, ki jih vidite zgoraj, zadostuje za številne primere uporabe. PyNaCl (Ed25519) in paket jcs (kanonični JSON) sta dobro vzdrževani in revizirani knjižnici.
Uporabite produkcijsko knjižnico za potrdila. Več odprtokodnih projektov implementira enak vzorec z dodatnimi funkcijami (rotacija ključev, množična potrditev, distribucija JWK nabora, integracija s politiko):
draft-farley-acta-signed-receipts), ki je v postopku standardizacije.protect-mcp (npm) in @veritasacta/verify (npm) zagotavljata implementacijo podpisa potrdil in potrditve brez povezave na Node.js, namenjena zavijanju kateregakoli MCP strežnika z vidnim revizijskim sledenjem.Odločitev med lastno rešitvijo in uporabo knjižnice je podobna odločitvi med pisanjem lastne knjižnice JWT ali uporabo preverjene: oba pristopa sta razumljiva; knjižnica prihrani čas in zmanjša površino za revizijo; izvorna implementacija zahteva razumevanje vsakega primitiva. Ta lekcija vas uči izvorne poti, da imate temelj za katerokoli izbiro.
Preizkusite svoje znanje pred nadaljevanjem na praktično vajo.
1. Potrdilo je podpisano z zasebnim Ed25519 ključem agenta. Revizor ima le javni ključ. Ali lahko revizor potrdi potrdilo brez povezave?
2. Napadalec spremeni polje policy_id potrdila, da trdi, da je bilo nadzorovano z bolj permisivno politiko. Podpis je bil narejen nad originalnim paketom. Kaj se zgodi pri potrditvi?
3. Zakaj potrdilo namesto surovih argumentov in rezultata vsebuje samo tool_args_hash in result_hash?
4. Polje previous_receipt_hash veže vsako potrdilo na prejšnjega. Če napadalec tiho izbriše eno potrdilo sredi verige, kaj postane neveljavno?
5. Potrdilo uspešno potrdi. Ali to dokazuje, da je dejanje agenta bilo pravilno, učinkovito ali skladno s politiko?
Odprite code_samples/18-signed-receipts.ipynb in dokončajte vseh štiri razdelke:
Dodatni izziv 1: razširite shemo potrdila z dodatnim poljem po vaši izbiri (npr. ID zahtevka za sledenje), posodobite kanonično logiko podpisa, da ga vključi, in potrdite, da potrdilo še vedno uspešno prehaja potrditve. Nato polje spremenite po podpisu in potrdite, da preverjanje ne uspe. To vas prisili, da razumete, kako vsak bajt kanonične predstavitve prispeva k podpisu. Stretch izziv 2: SHA-256-zgoščite skupaj dva svoja računa (združite njune kanonične bajte v determinističnem vrstnem redu) in vstavite nastali digest kot novo polje na tretji račun, preden ga podpišete. Preverite, ali se vsi trije računi še vedno pravilno pretvorijo. Pravkar ste ustvarili dokaz vključenosti v enem koraku: vsak, ki ima tretji račun, lahko dokaže, da sta prva dva obstajala ob času podpisa, brez potrebe po razkritju njihove vsebine. To je vzorec, ki ga računi z izborčno razkritostjo uporabljajo v velikem merilu (Merkle obveznosti, RFC 6962).
Kriptografski računi dajejo AI agentom revizijsko sled, ki je:
Niso nadomestilo za preverjanje vhodnih podatkov, izvajanje pravilnikov ali infrastrukturo identitete. So temelj za te plasti. Ko uvajate agente v regulirane delovne obremenitve, delovne tokove med več organizacijami ali v katerem koli okolju, kjer ni mogoče predpostaviti zaupanje bodočega revizorja, so računi način, kako zagotoviti pošteno revizijsko sled.
Najpomembnejši sklep: računi dokazujejo, kdo je kaj povedal in kdaj. Ne dokazujejo, da je bilo povedano resnično ali pravilno. Ta razliko vzdržujte strogo. To je razlika med poštenim sistemom izvora in zavajajočim.
Ko ste pripravljeni preiti iz tega lekcije na uvajanje agentov s podpisanimi računi v realnem okolju:
https://your-org.example.com/.well-known/agent-keys.json.Pridružite se Microsoft Foundry Discord, kjer se lahko srečate z drugimi učenci, obiskujete pisarne in dobite odgovore na vprašanja o AI agentih.
Ta lekcija pokriva enotni podpis računa in verigo hashiranih računov. Enake primitivne funkcije sestavljajo še več naprednih vzorcev, ki jih lahko srečate, ko se vaša upravljavska praktika razvija:
authorization_*) in po izvajanju (result_*) z neodvisnimi podpisi, uporabno, ko odločitev za pooblastilo in opažen rezultat ustvarjata različni akterji ali v različnih časih. To se aditivno sestavi na vrh formata računa, ki je predstavljen v tej lekciji.result_hash. Dejanske vsebine so pogosto bogatejše od rezultatov enega orodja: razlogi pred odločitvijo (napoved modela, obravnavane možnosti, dokazi in njihova popolnost, ocena tveganja, veriga odgovornosti, rezultat presoje) lahko vsi živijo znotraj vsebine, zaprti z enim računom. To ohranja format računa minimalen, hkrati pa omogoča postopno rast shem vsebine po domenah.signature.alg lahko nosi ML-DSA-65 (NIST-ov standard po kvantnem podpisa), ko morate preiti. Načrtujte prehodno obdobje, ko so računi dvojno podpisani.Gradnja agentov za uporabo računalnika (CUA)
(Določi jo curriculum vzdrževalci)
Omejitev odgovornosti: Ta dokument je bil preveden z uporabo AI prevajalske storitve Co-op Translator. Čeprav si prizadevamo za natančnost, vas prosimo, da upoštevate, da avtomatizirani prevodi lahko vsebujejo napake ali netočnosti. Izvirni dokument v njegovem izvirnem jeziku je treba obravnavati kot avtoritativni vir. Za kritične informacije je priporočljiv strokovni človeški prevod. Ne odgovarjamo za morebitna nesporazume ali napačne interpretacije, ki izhajajo iz uporabe tega prevoda.