Гледайте видео урока: Защита на AI агенти с криптографски разписки
(Видео урок и миниизображение ще бъдат добавени от екипа за съдържание на Microsoft след сливането, съответстващи на шаблона за урок 14 / 15.)
Този урок ще обхване:
След завършване на този урок, ще знаете как да:
Представете си, че сте разположили AI агент за Contoso Travel. Агентът чете клиентски заявки, извиква API за полети за търсене на опции и резервира места от името на клиента. Миналото тримесечие агентът обработи 50 000 резервации.
Днес пристига одитор. Той задава прост въпрос: „Покажете ми какво направи вашият агент.“
Вие предоставяте лог файловете. Одиторът ги разглежда и задава сложния въпрос: „Как да знам, че тези логове не са редактирани?“
Това е проблемът с одитния път. Повечето внедрявания на агенти днес разчитат на:
Нито едно от тези не може да отговори на въпроса на одитора без да изисква доверие в някого (във вас, вашия доставчик на облачни услуги, вашия доставчик на база данни). За вътрешна употреба това доверие често е приемливо. За регулирани натоварвания (финанси, здравеопазване, всичко подложено на Закона за 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 -- да --> I[Доказателство за защитена манипулация]
H -- не --> 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..."
}
}
Три свойства вършат работата:
Подписът. Разписката е подписана от шлюза на агента с частен ключ Ed25519. Всеки с съответния публичен ключ може да провери подписа офлайн. Подправянето на някое поле прави подписа невалиден.
Канонично кодиране. Преди подписване разписката се сериализира с JSON Canonicalization Scheme (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 # RFC 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, е била наистина оценена или че би разрешила действието, ако е проверена. Разписката записва какво е твърдено, не какво е наложено.Тази граница има значение по две причини:
Често срещана грешка е да се предполага, че „имаме разписки“ означава „управляваме се“. Не е така. Разписките са основата. Управлението е системата, която изграждате върху тях.
Python кодът в този урок е умишлено минимален, за да можете да четете всеки ред и да разбирате точно какво се случва. В продукция имате две опции:
Изграждане директно върху криптографските примитиви. 50-те реда, които видяхте, са достатъчни за много случаи на употреба. PyNaCl (Ed25519) и пакетът jcs (каноничен JSON) са добре поддържани и проверени библиотеки.
Използване на библиотека за производствени разписки. Няколко отворени проекта имплементират същия модел с допълнителни функции (ротация на ключове, пакетна проверка, разпространение на JWK Set, интеграция с политики):
draft-farley-acta-signed-receipts), който в момента е в процес на стандартизация.protect-mcp (npm) и @veritasacta/verify (npm) предоставят Node-базирана имплементация на подписване на разписки и офлайн проверка, предназначени за обвиване на всеки MCP сървър с одитен път, доказващ неприкосновеното му състояние.Изборът между собствена имплементация и използване на библиотека е като избор между писане на собствена 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).
Криптографските разписки дават на AI агентите аудиторска следа, която е:
Те не са заместител на валидирането на входа, прилагането на политики или инфраструктурата за идентичност. Те са основа за тези слоеве. Когато внедрявате агенти в регулирани работни натоварвания, мултиорганизационни работни потоци или във всяка среда, в която бъдещ одитор не може да бъде приет безрезервно като доверен, разписките са начинът да направите аудиторската следа честна.
Най-важното послание: разписките доказват кой какво е казал и кога. Те не доказват, че казаното е вярно или правилно. Задръжте това разграничение здраво. Това е разликата между честна система за произход и подвеждаща такава.
Когато сте готови да преминете от този урок към внедряване на агенти, подписани с разписки в реална среда:
https://your-org.example.com/.well-known/agent-keys.json.Присъедини се към Microsoft Foundry Discord, за да се срещнеш с други учащи, да посетиш консултации и да получиш отговори на въпросите си за AI агенти.
Този урок покрива подписване на една разписка и последователности с хеширана верига. Същите примитиви формират няколко по-напреднали модела, които може да срещнете при развитието на политиката ви:
authorization_*) и след изпълнение (result_*) с отделни подписи, полезно когато решението за разрешение и резултатът се произвеждат от различни участници или в различно време. Това се надгражда допълнително върху формата на разписка от този урок.result_hash. Реалните полезни товари често са по-богати от един резултат на инструмент: предварителна логика (прогноза на модел, разгледани опции, доказателства и пълнотата им, рискова позиция, верига на отчетност, изход на гейт) могат всички да живеят вътре в полезния товар, защитен от една разписка. Това поддържа формата минимална, докато схемите на полезния товар могат да се развиват домейн по домейн.signature.alg може да носи ML-DSA-65 (квантово-сигнатурен стандарт на NIST), когато трябва да мигрирате. Планирайте преходен период, в който разписките са с двоен подпис.Изграждане на агенти за използване на компютър (CUA)
(Ще бъде определен от кураторите на учебната програма)
Отказ от отговорност: Този документ е преведен с помощта на AI преводачески услуга Co-op Translator. Въпреки че се стремим към точност, моля имайте предвид, че автоматизираните преводи могат да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Ние не носим отговорност за каквито и да е недоразумения или неправилни тълкувания, произтичащи от използването на този превод.