Sledujte video lekce: Zabezpečení AI agentů pomocí kryptografických potvrzení
(Video lekce a náhledový obrázek budou přidány týmem Microsoftu po sloučení, odpovídající vzoru lekcí 14 / 15.)
Tato lekce pokryje:
Po dokončení této lekce budete umět:
Představte si, že jste nasadili AI agenta pro Contoso Travel. Agent čte požadavky zákazníků, volá API letenek pro hledání možností a rezervuje místa jménem zákazníka. Minulý čtvrtletí agent zpracoval 50 000 rezervací.
Dnes přichází auditor. Položí jednoduchou otázku: „Ukažte mi, co váš agent udělal.“
Předáte mu své logy. Auditor je prohlíží a položí obtížnější otázku: „Jak vím, že tyto logy nebyly upravovány?“
To je problém auditní stopy. Dnešní většina nasazení agentů spoléhá na:
Žádný z těchto způsobů nemůže odpovědět auditorovi bez toho, aby auditor někomu důvěřoval (vám, vašemu poskytovateli cloudu, dodavateli databáze). Pro interní použití je tato důvěra často přijatelná. Pro regulované úlohy (finance, zdravotnictví, cokoliv podléhající EU AI zákonu) nikoliv.
Kryptografická potvrzení řeší tento problém tím, že každou akci agenta dělají nezávisle ověřitelnou. Auditor vám nemusí důvěřovat. Potřebuje pouze váš veřejný klíč a samotné potvrzení.
Potvrzení je JSON objekt, který zaznamenává, co agent udělal, podepsaný digitálním podpisem.
flowchart LR
A[Agent vyvolá nástroj] --> B[Sestavte užitečná data účtenky]
B --> C[Kanonizace JSON RFC 8785]
C --> D[SHA-256 hash]
D --> E[Podepište Ed25519]
E --> F[Účtenka s podpisem]
F --> G[Auditorka ověří offline]
G --> H{Platný podpis?}
H -- yes --> I[Důkaz odolný proti manipulaci]
H -- no --> J[Účtenka zamítnuta]
Minimalistické potvrzení vypadá takto:
{
"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ři vlastnosti vykonávají práci:
Podpis. Potvrzení je podepsané branou agenta pomocí Ed25519 privátního klíče. Kdokoli s odpovídajícím veřejným klíčem může offline ověřit podpis. Jakákoliv manipulace s polem zneplatní podpis.
Kanonické kódování. Než je potvrzení podepsáno, je serializováno pomocí JSON Canonicalization Scheme (JCS, RFC 8785). To zajišťuje, že dvě implementace vytvářející stejný logický záznam produkovat stejný přesně identický byteřad.
Hašovací řetězec. Pole previous_receipt_hash propojuje každé potvrzení s tím předchozím. Odebrání nebo přeuspořádání potvrzení zlomí každé potvrzení, které na něj navazuje. Manipulace je tak viditelná na úrovni řetězce i při obejití jednotlivých podpisů.
Tyto vlastnosti dohromady poskytují tři záruky:
K vytvoření potvrzení nepotřebujete speciální knihovnu. Kryptografické primitiva jsou široce dostupná a logika je pár desítek řádků Pythonu.
Praktické cvičení v code_samples/18-signed-receipts.ipynb vede úplným procesem. Shrnutí:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # RFC 8785 kanonický 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()}"
# Vygenerujte nebo načtěte podepisovací klíč (v produkci uložit do klíčového skladu)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Sestavte obsah účtenky (ještě bez podpisu)
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,
}
# Kanonizujte, zahashujte, podepište.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Připojte strukturovaný podpisový objekt.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
To je celý proces podepisování. Cvičení v poznámkovém bloku procházejí každý krok.
Ověření je opačná operace:
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 strukturovaný objekt: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Obnovte užitečné zatížení, které bylo skutečně podepsáno (vše kromě podpisu).
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
Tato funkce vezme potvrzení a vrátí True, pokud je podpis platný, jinak False. Žádný síťový hovor, žádná závislost na službě, žádná důvěra v třetí stranu není potřeba.
Pro zobrazení detekce manipulace poznámkový blok společně ukazuje:
tool_args_hash.Toto je praktická ukázka toho, že potvrzení jsou odolná proti manipulaci: jakákoliv změna, byť sebemenší, zlomí podpis.
Jedno podepsané potvrzení chrání jednu akci. Řetězec potvrzení chrání sekvenci.
flowchart LR
R0[Doklad 0<br/>genesis] --> R1[Doklad 1]
R1 --> R2[Doklad 2]
R2 --> R3[Doklad 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Každé potvrzení zaznamenává hash potvrzení předchozího. K tichému odstranění potvrzení 2 by útočník musel:
previous_receipt_hash potvrzení 3 (zničí podpis potvrzení 3), NEBOJe-li privátní klíč v hardwarovém klíčovém trezoru a veřejný klíč publikujete s každým potvrzením, žádný útok není proveditelný bez odhalení.
Poznámkový blok ukazuje:
previous_receipt_hash každého potvrzení odpovídá skutečnému hashi předchozího potvrzení.Takto vytvoříte auditní stopu, kterou může externí auditor ověřit bez nutnosti vám důvěřovat.
Toto je nejdůležitější část lekce. Potvrzení jsou silná, ale jejich síla je omezená.
Potvrzení prokazují tři věci:
Potvrzení neprokazují:
policy_id byla skutečně vyhodnocena nebo že by akci povolila, kdyby to bylo kontrolováno. Potvrzení zaznamenává to, co bylo tvrzeno, ne to, co bylo vynuceno.Tato hranice je důležitá ze dvou důvodů:
Častou chybou je předpokládat, že „máme potvrzení“ znamená „jsme řízeni.“ Neznamená to tak. Potvrzení jsou základ. Řízení je systém, který na tomto základě stavíte.
Bod 3 výše stojí za vlastní sekci: potvrzení o akci říká „tento klíč podepsal tento obsah,“ nikdy „člověk to autorizoval.“ Pro akce s vysokým rizikem (vrácení peněz, mazání, převody peněz) rámce řízení stále častěji vyžadují právě toto chybějící prohlášení, a je vytvořitelné se stejnými primitivy, které jste již v této lekci vybudovali.
Doprovodný poznámkový blok code_samples/human-authorization-receipts.ipynb přidává druhý typ potvrzení, human.approval.v1, ve stejné obálce jako potvrzení v lekci (typový payload podepsaný Ed25519 přes jeho kanonický SHA-256, s objektem signature mimo podepsaná data). Pojmenovaný schvalovatel podepisuje celou kanonickou akci a její digest před provedením; potvrzení akce agenta nese stejný digest akce a parent_approval_ref, což je receipt_hash schválení, ve stejném konvenci jako previous_receipt_hash v řetězci, který jste výše sestavili. Jedno verify_chain vyhodnocuje oba artefakty pod oddělenými registrovanými klíči (klíče schvalovatele vs klíče agenta), takže kódová cesta je sdílená, ale pravomoci nikdy.
Vlastnost, kterou toto zajišťuje, formulováno opatrně: člověk schválil tuto přesnou akci a agent provedl přesně tu schválenou akci. Odepření v poznámkovém bloku jsou to, co dělá vlastnost skutečnou, nikoli jen tvrzenou:
Každá chyba odmítá s jiným důvodem, takže auditor čtoucí odmítnutí pozná, zda pravomoc vypršela, nebo se akce změnila. Pravidlo, které poznámkový blok učí: podepsané schválení samo o sobě není pravomocí. Pravomoc existuje jen pokud oba potvrzení stále v době vykonání odkazují na stejnou kanonickou akci. Cesta spolupodpisu v témže Internet-Draftu jako tato lekce sleduje (draft-farley-acta-signed-receipts) je standardizovaná verze tohoto vzoru.
Python kód v této lekci je záměrně minimalistický, aby si každý řádek mohl přečíst a přesně pochopit, co se děje. V produkci máte dvě možnosti:
Budovat přímo na kryptografických primitivech. Padesát řádků, které jste viděli výše, stačí pro mnoho případů použití. PyNaCl (Ed25519) a balíček jcs (kanonický JSON) jsou dobře udržované a auditované knihovny.
Použít produkční knihovnu pro potvrzení. Několik open-source projektů implementuje stejný vzor s dalšími vlastnostmi (rotace klíčů, dávkové ověření, distribuce JWK Set, integrace s politikami):
draft-farley-acta-signed-receipts, revize 02), který je aktuálně ve standardizačním procesu, se sadou sdílených testů souladu (agent-governance-testvectors), jež nezávislé implementace používají k porovnávání identických kanonických výstupů.protect-mcp (npm) a @veritasacta/verify (npm) poskytují Node-based implementaci podepisování potvrzení a offline ověření, určené pro obalení jakéhokoli MCP serveru s auditní stopou odolnou vůči manipulaci, včetně režimu čekání na spolupodpis, kdy pozastavená akce vydá schvalovací potvrzení spojené s digestem akce (WebAuthn-backend v desktopovém režimu), totéž schéma jako v poznámkovém bloku o lidské autorizaci výše.pip install nobulex) poskytuje stejný vzor podepisování Ed25519 + JCS s LangChain a integrací CrewAI v Pythonu, včetně publikovaných testovacích vektorů a mapování souladu přispěného přes OWASP PR #2210.Rozhodnutí mezi vlastním řešením a knihovnou je podobné rozhodnutí mezi napsáním vlastní JWT knihovny a použitím otestované knihovny: obě varianty jsou rozumné; knihovna šetří čas a snižuje auditní plochu; vlastní cesta vás nutí rozumět každému primitivu. Tato lekce učí vlastní cestu, abyste měli základy pro obě volby.
Otestujte své pochopení před přechodem k praktickému cvičení.
1. Potvrzení je podepsáno soukromým Ed25519 klíčem agenta. Auditor má pouze veřejný klíč. Může auditor potvrzení ověřit offline?
2. Útočník změní pole policy_id v potvrzení tak, že tvrdí, že bylo řízeno benevolentnější politikou. Podpis byl vytvořen nad původním obsahem. Co se stane při ověření?
3. Proč potvrzení obsahuje tool_args_hash a result_hash namísto surových argumentů a výsledku?
4. Pole previous_receipt_hash propojuje každé potvrzení s jeho předchůdcem. Pokud útočník potichu vymaže jedno potvrzení uprostřed řetězce, co se stane neplatným?
5. Potvrzení projde ověřením. Dokazuje to, že akce agenta byla správná, platná nebo v souladu s politikou?
Otevřete code_samples/18-signed-receipts.ipynb a dokončete všechny čtyři části:
Náročný úkol 1: rozšiřte schéma potvrzení o vlastní pole (například ID požadavku pro trasování), aktualizujte kanonickou logiku podepisování tak, aby pole zahrnovala, a potvrďte, že potvrzení stále projde ověřením. Poté pole po podepsání změňte a potvrďte, že ověření selže. Tím pochopíte, jak každý bajt kanonického kódování přispívá k podpisu.
Náročný úkol 2: Zkombinujte dva své potvrzení SHA-256 hashem (spojte jejich kanonické bajty v deterministickém pořadí) a vložte výsledný digest jako nové pole na třetí potvrzení před jeho podepsáním. Ověřte, že všechna tři potvrzení stále projdou ověřením. Právě jste vytvořili jednu úroveň důkazu začlenění: kdokoli držící třetí potvrzení může dokázat, že první dvě existovala v době jeho podepsání, aniž by bylo potřeba odhalit jejich obsah. Tento vzor používají potvrzení s výběrovým zveřejněním ve velkém měřítku (Merkleho závazky, RFC 6962).
Kryptografická potvrzení dávají AI agentům auditní stopu, která je:
Není náhradou za validaci vstupu, vynucování politik nebo identifikační infrastrukturu. Jsou základem pro tyto vrstvy. Při nasazování agentů do regulovaných systémů, meziorganizovaných workflow nebo jakéhokoli prostředí, kde budoucí auditor nemůže být předpokládán jako důvěryhodný, jsou potvrzení cestou, jak zajistit poctivou auditní stopu.
Nejdůležitější poznatek: potvrzení dokazují, kdo co kdy řekl. Nedokazují, že to, co bylo řečeno, bylo pravdivé nebo správné. Držte tento rozdíl pevně. Je to rozdíl mezi poctivým systémem původu a zavádějícím.
Až budete připraveni přejít od této lekce k nasazení agentů podepisujících potvrzení v reálném prostředí:
https://your-org.example.com/.well-known/agent-keys.json.Připojte se k Microsoft Foundry Discordu, kde se setkáte s ostatními studenty, můžete navštívit konzultační hodiny a dostanete odpovědi na své otázky týkající se AI agentů.
Tato lekce pokrývá podepisování jednoho potvrzení a sekvence řetězených hashů. Stejné primitiva se skládají do několika pokročilejších vzorů, které můžete potkat, jak vaše správa dozrává:
authorization_*) a po vykonání (result_*) s nezávislými podpisy, užitečné, když rozhodnutí o autorizaci a pozorovaný výsledek vydávají různí aktéři nebo v různých časech. To se skládá navíc na formát potvrzení vyučovaný v této lekci.result_hash. Reálné obsahy jsou často bohatší než jediný výsledek volání nástroje: předběžné uvažování (predikce modelu, uvažované možnosti, důkazy a jejich úplnost, riziková situace, řetězec odpovědnosti, výsledek brány) může být celý obsažen v payloadu a zabezpečen jediným potvrzením. To udržuje formát potvrzení minimalistický, zatímco schémata obsahu se mohou vyvíjet podle domény.signature.alg může nést hodnotu ML-DSA-65 (postkvantový standard NIST) pokud potřebujete migrovat. Plánujte přechodné období, kdy budou potvrzení podepisována dvojitě.Prohlášení o omezení odpovědnosti: Tento dokument byl přeložen pomocí AI překladatelské služby Co-op Translator. Přestože usilujeme o co největší přesnost, mějte prosím na paměti, že automatizované překlady mohou obsahovat chyby nebo nepřesnosti. Originální dokument v jeho mateřském jazyce by měl být považován za autoritativní zdroj. Pro kritické informace se doporučuje profesionální lidský překlad. Nejsme odpovědní za jakékoli nedorozumění nebo nesprávné interpretace vzniklé použitím tohoto překladu.