Погледајте видео лекцију: Осигурање AI агената криптографским потврдама
(Видео лекције и минијатура биће додати од стране Microsoft тима за садржај након обједињавања, у складу са обрасцем лекције 14 / 15.)
Ова лекција ће обухватити:
Након што завршите ову лекцију, знаћете како да:
Замислите да сте поставили AI агента за Contoso Travel. АгенT чита захтеве корисника, позива API за летове да погледа опције и резервише седишта у име корисника. Прошлог тромесечја, агент је обрадио 50.000 резервација.
Данас долази ревизор и поставља једноставно питање: „Покажи ми шта је твој агент радио.“
Предајете му ваше датотеке дневника. Ревизор их погледа и поставља теже питање: „Како знам да ови дневници нису измењени?“
Ово је проблем ревизорске стазе. Већина данашњих распоређивања агената ослања се на:
Никао од ових не може одговорити на питање ревизора без да ревизор верује некоме (вама, вашем провајдеру облака, произвођачу базе). За интерну употребу, то поверење је често прихватљиво. За регулисане радне оптерећења (финансије, здравство, све што подлеже EU AI Закону), није.
Криптографске потврде ово решавају тиме што сваку агенцијску акцију чине независно верификованом. Ревизору није потребно да вам верује. Потребан му је само ваш јавни кључ и сама потврда.
Потврда је JSON објекат који записује шта је агент урадио, потписан дигиталним потписом.
flowchart LR
A[Агент позива алат] --> B[Конструиши садржај рачуна]
B --> C[Канонизуј JSON RFC 8785]
C --> D[SHA-256 хеш]
D --> E[Ed25519 потпис]
E --> F[Рачун са потписом]
F --> G[Ревизор проверава ван мреже]
G --> H{Потпис је валидан?}
H -- yes --> I[Доказ против манипулације]
H -- no --> J[Рачун одбијен]
Мала потврда изгледа овако:
{
"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..."
}
}
Три својства раде посао:
Потпис. Потврду потписује агентски гатеwаy користећи Ed25519 приватни кључ. Сваки ко има одговарајући јавни кључ може офлајн верификовати потпис. Манипулација било којим пољем чини потпис неважећим.
Канонска енкодирања. Пре потписивања, потврда се сериализује користећи JSON Канонски Шема (JCS, RFC 8785). Ово обезбеђује да две имплементације које производе исту логичку потврду генеришу бајт-идентичан резултат. Без каноникализације, различити JSON серијализатори дали би различите потписе за исти садржај.
Повезивање хешевима. Поље previous_receipt_hash повезује сваку потврду са претходном. Уклањање или препоредивање потврде разбија сваки следећи запис. Манипулације постају видљиве на нивоу ланца, чак и ако се заобиђу појединачни потписи.
Заједно ова својства пружају три гаранције:
Не треба вам посебна библиотека да бисте произвели потврду. Криптографски примитиви су широко доступни и логику је могуће написати у неколико десетина линија Python кода.
Практичне вежбе у code_samples/18-signed-receipts.ipynb воде кроз цео процес. Почетни преглед:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # РФЦ 8785 канонски 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()}"
# Генеришите или учитајте потписни кључ (у продукцији, чувајте у сигурносној каси)
signing_key = signing.SigningKey.generate()
verify_key = signing_key.verify_key
# Изградите пунило потврде (још без потписа)
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,
}
# Канонизујте, хеширајте, потпишите.
canonical_bytes = canonicalize(payload)
message_hash = hashlib.sha256(canonical_bytes).digest()
signature_bytes = signing_key.sign(message_hash).signature
# Прикључите структуирани објекат потписа.
receipt = {
**payload,
"signature": {
"alg": "EdDSA",
"sig": b64url_nopad(signature_bytes),
"public_key": b64url_nopad(bytes(verify_key)),
},
}
То је цео процес потписивања. Вежбе у нотебооку објашњавају сваки корак.
Верификација је обрнути процес:
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:
# Потпис је структуирани објекат: {"alg", "sig", "public_key"}.
sig_obj = receipt.get("signature")
if not sig_obj or sig_obj.get("alg") != "EdDSA":
return False
# Реконструишите садржај који је заправо потписан (све осим потписа).
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
Ова функција прима потврду и враћа True ако је потпис валидан, иначе False. Без позива мрежи, без зависности од сервиса, без потребе да се било коме верује.
Да бисте видели како се откривају манипулације у пракси, нотебоок иде кроз:
tool_args_hash.Ово је практична демонстрација да су потврде доказиве против манипулација: свака измена, ма колико мала, разбија потпис.
Једна потписана потврда штити једну акцију. Ланац потврда штити низ акција.
flowchart LR
R0[Рачун 0<br/>генеза] --> R1[Рачун 1]
R1 --> R2[Рачун 2]
R2 --> R3[Рачун 3]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
Свака потврда записује хеш претходне. Да би нападач тихо уклонио потврду 2, морао би или:
previous_receipt_hash потврде 3 (разбија потпис потврде 3), ИЛИАко је приватни кључ у хардуерском кључном сефу и објавите јавни кључ уз сваку потврду, ниједан напад није изводљив без откривања.
Нотебоок показује:
previous_receipt_hash одговара стварном хешу претходне потврде.Ово вам омогућава да произвежете ревизорску стазу коју спољни ревизор може верификовати без потребе да вам верује.
Ово је најважнији део ове лекције. Потврде су моћне, али њихова моћ је ограничена.
Потврде доказују три ствари:
Потврде НЕ доказују:
policy_id заиста процењена или да би дозволила ову акцију ако би се проверила. Потврда бележи што је тврђено, не што је примењено.Ова граница је важна из два разлога:
Уобичајена грешка је мислити да „имамо потврде“ значи „имамо управљање.“ Нису. Потврде су темељ. Управљање је систем који градите на тој основи.
Тачка 3 изнад заслужује посебан поднаслов: потврда радње каже „овој кључ је потписао овај садржај“, никад „човек је овластио“. За ризичне радње (повраћај новца, брисања, банковни трансфери), оквири управљања све чешће захтевају баш ту изостављену изјаву, коју је могуће произвести истим примитивима које сте већ изградили у овој лекцији.
Следећи нотебоок code_samples/human-authorization-receipts.ipynb додаје другу врсту потврде, human.approval.v1, у истом облику коверте као потврде из лекције (типизовани садржај потписан Ed25519 преко канонског SHA-256, са signature објектом ван потписаних бајтова). Названи оверилац потписује целу канонску радњу и њен дигест пре извршења; агенцијска потврда носи исти дигест акције и parent_approval_ref, receipt_hash овере, исту конвенцију као previous_receipt_hash из претходног ланца. Један verify_chain процес у исто време проверава оба артефакта под одвојеним фиксним регистрима кључева (кључеви оверилаца против кључева агената), тако да је код за верификацију заједнички, али власти никада нису.
Особина коју ово купује, пажљиво изражена: човек је одобрио ову тачну акцију и агент је извршио баш ту одобрену акцију. Нотебоок користи фиксе одбијања који овај императив чине стварним, а не само тврдњом:
Сваки неуспех одбија са јединственим разлогом, тако да ревизор који чита одбијање може рећи да ли је власт застарела или је извршена акција промењена. Правило које нотебоок учи: потписано одобрење само по себи није власт. Власт постоји само ако обе потврде још увек обавезују исту канонску акцију у тренутку извршења. Пут са ко-потписом у истом Internet-Draft-у на који се ова лекција односи (draft-farley-acta-signed-receipts) је стандардни облик овог модела.
Python код у овој лекцији је намерно минималан да бисте могли да прочитате сваки ред и тачно разумете шта се дешава. У продукцији имате две опције:
Градите директно на криптографским примитивима. 50 линија кода које сте видели горе је довољно за многе употребе. PyNaCl (Ed25519) и пакет jcs (канонски JSON) су добро одржаване и ревидиране библиотеке.
Користите производну библиотеку за потврде. Неколико пројеката отвореног кода имплементира исти образац са додатним функцијама (ротација кључева, верификација у серији, дистрибуција JWK скупа, интеграција са покретачима политика):
draft-farley-acta-signed-receipts, ревизија 02) који је тренутно у процесу стандардизације, са заједничким набором конформности (agent-governance-testvectors) који независне имплементације међусобно проверавају за идентичан канонски резултат.protect-mcp (npm) и @veritasacta/verify (npm) пружају Node.js имплементацију потписивања потврда и офлајн верификацију, намењену за омотавање било ког MCP сервера са доказивом ревизорском стазом, укључујући радни ток задржаног коскаталошког потписа у коме паузирана акција емитује потврду о одобрењу везану за дигест акције (WebAuthn подржан у десктоп протоку), исти образац потврде одобрења као у горе поменутом нотебооку за људску ауторизацију.pip install nobulex) пружа исти Ed25519 + JCS образац потписивања у Python-у са интеграцијама LangChain и CrewAI, укључујући објављене тест векторе за проверу крос-контроле и мапирање усаглашености које је допринело путем OWASP PR #2210.Одлука између писања свог и коришћења библиотеке подсећа на избор између писања своје JWT библиотеке и коришћења оне која је тестирана: оба приступа су разумна; библиотека штеди време и смањује површину за ревизију; приступ од почетка принуђује вас да разумете сваки примитив. Ова лекција учи пут од почетка тако да имате темеље за било који избор.
Испитајте ваше разумевање пре него што пређете на практичну вежбу.
1. Потврда је потписана приватним Ed25519 кључем агента. Ревизор има само јавни кључ. Може ли ревизор верификовати потврду офлајн?
2. Нападач измењује поље policy_id потврде да би тврдио да је била регулисана попустљивијом политиком. Потпис се односио на оригинални садржај. Шта се догађа током верификације?
3. Зашто примљени документ садржи tool_args_hash и result_hash уместо неуређених аргумената и резултата?
4. Поље previous_receipt_hash повезује сваки примљени документ са претходним. Ако нападач тиха уклони један примљени документ из средине ланца, шта постаје неважеће?
5. Примљени документ се чисто верификује. Да ли то доказује да је деловање агента било исправно, ваљано или у складу са политиком?
Отворите code_samples/18-signed-receipts.ipynb и завршите сва четири дела:
Допунски изазов 1: проширите шему примљених докумената додатним пољем по свом избору (на пример, ИД захтева за праћење), ажурирајте канонску логику потписивања да га укључује, и потврдите да примљени документ и даље пролази верификацију. Затим измените поље после потписа и потврдите да верификација не успева. Ово вас приморава да разумете како сваки бајт канонског кодирања доприноси потпису.
Допунски изазов 2: SHA-256-хеширајте два своја примљена документа заједно (конкатенирајући њихове канонске бајтове у детерминистичком редоследу) и уградите добијени сажеци као ново поље на трећи примљени документ пре потписивања. Проверите да сва три примљена документа и даље пролазе верификацију. Управо сте направили доказ укључивања у једном кораку: сваки ко поседује трећи примљени документ може доказати да су прва два постојала у време када је тај документа потписан, без потребе да открива њихов садржај. Ово је образац који примљени документи са селективним откривањем користе у великом обиму (Merkle комити, RFC 6962).
Криптографски примљени документи дају АИ агентима евиденцију која је:
Они нису замена за проверу уноса, спровођење политика или инфраструктуру идентитета. Они су темељ за те слојеве. Када распоређујете агенте у регулисане радне оптерећења, мултиорганизационе процесе, или било које окружење где се не може претпоставити да вам будући ревизор верује, примљени документи су начин на који евиденција остаје поштена.
Најважнија поука: примљени документи доказују ко је шта рекао и када. Они не доказују да је оно што је речено било истина или исправно. Држите ту разлику чврсто. То је разлика између поштованог система порекла и збуњујућег.
Када будете спремни да прелазите са ове лекције на распоређивање агената који потписују примљене документе у стварном окружењу:
https://your-org.example.com/.well-known/agent-keys.json.Придружите се Microsoft Foundry Discord да се упознате са другим ученницима, присуствујете канцеларијским сатима и добијете одговоре на питања о АИ агентима.
Ова лекција покрива потписивање појединачног примљеног документа и низове са хеш-ланцем. Исти примитиви чине неколико напреднијих образаца који се могу појавити како ваш положај управљања сазрева:
authorization_*) и после-извршне (result_*) половине са независним потписима, корисно када одлуку о овласти и посматрани резултат производе различити актери или у различито време. Ово се адитивно надовезује на формат примљених докумената представљен у овој лекцији.result_hash. Реални садржаји су често богатији од резултата једног позива алата: размишљање пре одлуке (прогноза модела, разматране опције, доказ и његова потпуност, ризик, ланац одговорности, исход контролне тачке) све може бити унутар садржаја, запечаћено једним примљеним документом. Ово држи формат примљеног документа минималним док дозвољава еволуцију шема по доменима.signature.alg може носити ML-DSA-65 (NIST стандард за постквантни потпис) када вам затреба миграција. Планирајте период транзиције са двоструко потписаним примљеним документима.Изјава о одрицању одговорности: Овај документ је преведен коришћењем услуге за аутоматски превод Co-op Translator. Иако тежимо тачности, имајте у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на његовом изворном језику треба сматрати ауторитативним извором. За критичне информације препоручује се професионални људски превод. Нисмо одговорни за било каква неспоразума или погрешна тумачења која произилазе из коришћења овог превода.