Sledujte video lekce: Zabezpečení AI agentů pomocí kryptografických potvrzení
(Video lekce a náhledový obrázek budou přidány týmem Microsoft 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 letů k vyhledání možností a rezervuje místa jménem zákazníka. Za poslední č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é log soubory. Auditor je prohlédne a položí složitější otázku: „Jak vím, že tyto záznamy nebyly upraveny?“
To je problém auditní stopy. Většina dnešních nasazení agentů spoléhá na:
Žádný z těchto přístupů nemůže odpovědět auditorovi bez požadavku důvěry v někoho (vás, vašeho cloudového poskytovatele, dodavatele databáze). Pro interní použití je tato důvěra často přijatelná. Pro regulované oblasti (finance, zdravotnictví, cokoli podléhající EU AI Act) není.
Kryptografická potvrzení tento problém řeší tím, že každou akci agenta dělají nezávisle ověřitelnou. Auditor nemusí důvěřovat vám. 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[Vytvořit obsah účtenky]
B --> C[Kanonicizovat JSON RFC 8785]
C --> D[Hash SHA-256]
D --> E[Podpis Ed25519]
E --> F[Účtenka s podpisem]
F --> G[Auditor ověřuje offline]
G --> H{Platnost podpisu?}
H -- ano --> I[Důkaz viditelnosti manipulace]
H -- ne --> J[Účtenka zamítnuta]
Minimální 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 zajišťují funkci:
Podpis. Potvrzení je podepsané bránou agenta pomocí privátního klíče Ed25519. Každý, kdo má odpovídající veřejný klíč, může offline ověřit podpis. Jakákoli manipulace s jakýmkoli polem podpis zneplatní.
Kanonické kódování. Před podpisem je potvrzení serializováno podle JSON Canonicalization Scheme (JCS, RFC 8785). To zajišťuje, že dvě implementace vytvářející stejný logický dokument mají bytově identický výstup. Bez kanonizace by různí JSON serializéři vytvořili pro stejný obsah různé podpisy.
Hashové řetězení. Pole previous_receipt_hash propojuje každé potvrzení s předchozím. Odstranění nebo přeuspořádání jednoho potvrzení přeruší každé potvrzení, které po něm přišlo. Manipulace je viditelná na úrovni řetězce i v případě obejití individuálních podpisů.
Tyto vlastnosti dohromady poskytují tři záruky:
K vytvoření potvrzení nepotřebujete žádnou speciální knihovnu. Kryptografické primitivy jsou široce dostupné a logika je jen několik desítek řádků Pythonu.
Cvičení v code_samples/18-signed-receipts.ipynb detailně projdou celý proces. 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žte do trezoru klíčů)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Sestavte datový rámec úč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ý objekt podpisu.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
To je celý proces podepsání. V cvičeních v sešitě projdete každý krok.
Ověření je opačný proces:
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
# Zrekonstruujte užitečné zatížení, které bylo skutečně podepsáno (všechno 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ý požadavek, žádná závislost na službě, žádná důvěra v třetí stranu není potřeba.
Pro ukázku detekce manipulace se v sešitě projde:
tool_args_hash.To je praktický důkaz, že potvrzení jsou odolná vůči manipulaci: jakákoli úprava, byť malá, podpis zneplatní.
Jedno podepsané potvrzení chrání jednu akci. Řetězec potvrzení chrání posloupnost.
flowchart LR
R0[Příjmový doklad 0<br/>genesis] --> R1[Příjmový doklad 1]
R1 --> R2[Příjmový doklad 2]
R2 --> R3[Příjmový doklad 3]
R1 -. předchozí_hash_příjmového_dokladu .-> R0
R2 -. předchozí_hash_příjmového_dokladu .-> R1
R3 -. předchozí_hash_příjmového_dokladu .-> R2
Každé potvrzení zaznamenává hash potvrzení před ním. Aby útočník potichu odstranil potvrzení č. 2, musel by:
previous_receipt_hash v potvrzení 3 (to zneplatní podpis potvrzení 3), NEBOPokud je privátní klíč uložen v hardwarovém klíčovém úložišti a veřejný klíč publikujete s každým potvrzením, žádný útok není bez odhalení možný.
Sešit projde:
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 důvěry ve vás.
Toto je nejdůležitější část lekce. Potvrzení jsou mocná, ale jejich moc je omezená.
Potvrzení dokazují tři věci:
Potvrzení NEdokazují:
policy_id byla skutečně vyhodnocena, nebo že by tuto akci povolila. Potvrzení zaznamenává to, co bylo tvrzeno, ne co bylo skutečně vynuceno.Tato hranice je důležitá ze dvou důvodů:
Častá chyba je předpokládat, že „máme potvrzení“ znamená „jsme řízeni.“ Neznamená. Potvrzení jsou základ. Řízení je systém, který na tom postavíte.
Kód v Pythonu v této lekci je záměrně minimalistický, aby bylo možné každý řádek přečíst a přesně pochopit, co se děje. V produkci máte dvě možnosti:
Postavit se přímo na kryptografických primitivech. Oněch 50 řádků výše je dostačujících pro mnohé případy už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 funkcemi (rotace klíčů, dávkové ověřování, distribuce JWK Set, integrace s policy enginy):
draft-farley-acta-signed-receipts), který je v procesu standardizace.protect-mcp (npm) a @veritasacta/verify (npm) poskytují implementaci podepisování a offline ověřování potvrzení pro Node, určenou pro zabalení jakéhokoli MCP serveru s nezměnitelnou auditní stopou.Volba mezi vlastní implementací a knihovnou je podobná rozhodování mezi psaním vlastní JWT knihovny a použitím otestované knihovny: obě jsou rozumné; knihovna ušetří čas a omezí auditní plochu; vlastní cesta vás přinutí rozumět každému primitivu. Tato lekce učí vlastní cestu, abyste měli základy pro obě varianty.
Ověřte si porozumění před přechodem na praktické cvičení.
1. Potvrzení je podepsáno privátním klíčem Ed25519 agenta. Auditor má pouze veřejný klíč. Může auditor potvrzení ověřit offline?
2. Útočník upraví pole policy_id potvrzení, aby tvrdil, že bylo řízeno volnější zásadou. Podpis byl však spočítán nad původním payloadem. Co se stane při ověření?
3. Proč potvrzení zahrnuje tool_args_hash a result_hash místo surových argumentů a výsledku?
4. Pole previous_receipt_hash propojuje každé potvrzení s předchozím. Co se stane, když útočník potichu odstraní jedno potvrzení uprostřed řetězce?
5. Potvrzení bylo ověřeno bez chyby. Dokazuje to, že akce agenta byla správná, rozumná nebo vyhovující zásadám?
Otevřete code_samples/18-signed-receipts.ipynb a dokončete všechny čtyři sekce:
Rozšiřující výzva 1: rozšiřte schéma potvrzení o další pole dle vlastního výběru (například ID požadavku pro trasování), aktualizujte kanonickou logiku podepisování tak, aby pole zahrnovala, a potvrďte, že potvrzení projde ověřením. Pak pole po podpisu upravte a ověřte, že ověření selže. Tento postup vás donutí pochopit, jak každý byte kanonického kódování přispívá k podpisu. Výzva k rozšíření 2: SHA-256-hashujte spolu dva své účtenky (spojte jejich kanonické bajty v deterministickém pořadí) a vložte výsledný digest jako nové pole do třetí účtenky před jejím podepsáním. Ověřte, že všechny tři účtenky stále projdou zpětnou kontrolou. Právě jste vytvořili jednostupňový důkaz začlenění: kdokoli s třetí účtenkou může dokázat, že první dvě existovaly v době jejího podepsání, aniž by bylo třeba odhalovat jejich obsah. Toto je vzor, který selektivně-odhalovací účtenky používají v měřítku (Merkleho závazky, RFC 6962).
Kryptografické účtenky poskytují AI agentům auditní stopu, která je:
Nejsou náhradou za validaci vstupu, vynucování politiky nebo identitní infrastrukturu. Jsou základem těchto vrstev. Když nasazujete agenty do regulovaných pracovních zátěží, vícestupňových pracovních procesů nebo jakéhokoliv prostředí, kde nelze předpokládat důvěru budoucího auditora, účtenky jsou způsob, jak udržet auditní stopu poctivou.
Nejdůležitější poznatek: účtenky dokazují, kdo co řekl a kdy. Nedokazují, že to, co bylo řečeno, je pravda nebo správné. Držte tuto odlišnost pevně. Je to rozdíl mezi poctivým systémem provenience a klamavým.
Když jste připraveni postoupit z této lekce na nasazení agentů podepsaných účtenkami do reálného prostředí:
https://your-org.example.com/.well-known/agent-keys.json.Připojte se k Microsoft Foundry Discord, kde se setkáte s ostatními studenty, zúčastníte se konzultačních hodin a získáte odpovědi na své otázky ohledně AI agentů.
Tato lekce pokrývá podepisování jedné účtenky a sekvence řetězených hashů. Stejná primitiva se skládají do několika pokročilejších vzorů, se kterými se můžete setkat, až vaše správa dozraje:
authorization_*) a po-vykonávací (result_*) poloviny s nezávislými podpisy, užitečné pokud rozhodnutí o autorizaci a pozorovaný výsledek jsou vytvářeny různými aktéry nebo v různých časech. Toto se skládá navíc k formátu účtenky z této lekce.result_hash. Reálné obsahy jsou často bohatší než výsledek jediného nástroje: předrozhodovací úvahy (predikce modelu, uvažované možnosti, důkazy a jejich úplnost, postoj k riziku, řetězec odpovědnosti, výsledek brány) mohou být všechny uvnitř, zapečetěné jedinou účtenkou. To udržuje formát účtenky minimalistický a umožňuje doménově specifický vývoj schémat obsahu.signature.alg může nést ML-DSA-65 (kvantově odolný podpisový standard NIST), když přecházíte. Plánujte přechodové období, kdy budou účtenky podepsány dvojím podpisem.Budování agentů pro používání počítače (CUA)
(Bude určeno správci kurikula)
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.