تماشای ویدیو درس: ایمنسازی عاملهای هوش مصنوعی با رسیدهای رمزنگاریشده
(ویدیو درس و تصویر شاخص پس از ادغام توسط تیم محتوای مایکروسافت افزوده خواهند شد، مطابق با الگوی درس 14 / 15.)
این درس موارد زیر را پوشش میدهد:
پس از گذراندن این درس، شما خواهید دانست چگونه:
فرض کنید یک عامل هوش مصنوعی برای شرکت Contoso Travel مستقر کردهاید. این عامل درخواستهای مشتریان را میخواند، از API پروازها برای جستجوی گزینهها استفاده میکند و هرز صندلیها را به نمایندگی از مشتری رزرو میکند. در سه ماه گذشته، عامل 50,000 رزرو پردازش کرده است.
امروز یک حسابرس میآید. او یک سوال ساده میپرسد: “به من بگو عامل شما چه کرده است.”
شما فایلهای لاگ خود را تحویل میدهید. حسابرس به آنها نگاه میکند و سوال سختتری میپرسد: “چگونه میدانم این لاگها ویرایش نشدهاند؟”
این همان مشکل مسیر حسابرسی است. بیشتر استقرارهای عامل امروزه بر موارد زیر تکیه دارند:
هیچکدام از اینها نمیتوانند بدون نیاز به اعتماد حسابرس به شخصی (شما، ارائهدهنده ابری، فروشنده بانک اطلاعاتی) به سوال حسابرس پاسخ دهند. برای استفاده داخلی، آن اعتماد معمولاً قابل قبول است. برای بارهای کاری تنظیمشده (مالی، بهداشت و درمان، هر چیزی که مشمول قانون هوش مصنوعی اتحادیه اروپا است) اینطور نیست.
رسیدهای رمزنگاری شده این مشکل را با مستقل کردن تأیید هر اقدام عامل حل میکنند. حسابرس نیازی ندارد که به شما اعتماد کند. فقط کلید عمومی شما و خود رسید نیاز دارد.
رسید یک شیء JSON است که آنچه عامل انجام داده را ثبت میکند و با یک امضای دیجیتال امضا شده است.
flowchart LR
A[عامل یک ابزار را فراخوانی میکند] --> B[ساخت بار داده رسید]
B --> C[استانداردسازی JSON مطابق با RFC 8785]
C --> 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..."
}
}
سه ویژگی در اینجا کار میکنند:
امضا. رسید توسط درگاه عامل با استفاده از کلید خصوصی Ed25519 امضا شده است. هر کسی که کلید عمومی متناظر را داشته باشد، میتواند امضا را به صورت آفلاین تأیید کند. دستکاری در هر فیلد، امضا را نامعتبر میکند.
رمزگذاری کاننیکال. قبل از امضا، رسید با استفاده از طرح کاننیکالسازی JSON (JCS، RFC 8785) سریالیزه میشود. این تضمین میکند که دو پیادهسازی که رسید منطقی یکسان تولید میکنند خروجی بایت-یکسان تولید میکنند. بدون کاننیکالسازی، سریالایزرهای JSON مختلف امضاهای متفاوتی برای یک محتوا تولید میکردند.
زنجیره هش. فیلد previous_receipt_hash هر رسید را به رسید قبلی وصل میکند. حذف یا ترتیبدهی مجدد یک رسید، هر رسیدی که بعد از آن آمده است را میشکند. دستکاری حتی اگر امضاهای فردی دور زده شوند در سطح زنجیره قابل مشاهده است.
این ویژگیها با هم سه تضمین ارائه میدهند:
شما به کتابخانه خاصی برای تولید رسید نیاز ندارید. ابزارهای رمزنگاری به طور گسترده در دسترس هستند و منطق چند ده خط پایتون است.
تمرینهای عملی در code_samples/18-signed-receipts.ipynb روند کامل را قدم به قدم توضیح میدهند. نسخه خلاصه:
import json
import hashlib
import base64
from nacl import signing
from jcs import canonicalize # JSON قانونی RFC 8785
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,
}
# مستقیم بایتهای JCS را قانونیسازی و امضا کنید. PureEdDSA به صورت داخلی هش میکند.
canonical_bytes = canonicalize(payload)
signature_bytes = signing_key.sign(canonical_bytes).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)
try:
verify_key = signing.VerifyKey(b64url_decode(sig_obj["public_key"]))
verify_key.verify(canonical_bytes, 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
هر رسید هش رسید قبلی را ثبت میکند. برای حذف بیصدا رسید شماره ۲، مهاجم باید یا:
previous_receipt_hash رسید ۳ را تغییر دهد (امضای رسید ۳ را میشکند)، یااگر کلید خصوصی در یک صندوق کلید سختافزاری نگهداری شود و کلید عمومی همراه هر رسید منتشر شود، هیچکدام از این حملات بدون شناسایی امکانپذیر نیست.
دفترچه یادداشت موارد زیر را توضیح میدهد:
previous_receipt_hash هر رسید با هش واقعی رسید قبلی مطابقت دارد.این راهی است که شما یک مسیر حسابرسی تولید میکنید که حسابرس خارجی بدون نیاز به اعتماد به شما میتواند تأیید کند.
این مهمترین بخش این درس است. رسیدها قدرتمندند ولی قدرت آنها محدود است.
رسیدها سه چیز را اثبات میکنند:
رسیدها اثبات نمیکنند:
policy_id ذکر شده، واقعاً ارزیابی شده یا اینکه اگر بررسی میشد این عمل را مجاز میدانست. رسید آنچه ادعا شده، نه آنچه اجرا شده ثبت میکند.این مرز به دو دلیل اهمیت دارد:
اشتباه رایج این است که تصور شود “ما رسید داریم” یعنی “ما تحت حاکمیت هستیم.” اینطور نیست. رسیدها پایهاند. حاکمیت همان سیستمی است که روی آن میسازید.
مورد ۳ بالا لایق یک بخش مستقل است: یک رسید عمل میگوید “این کلید این محتوا را امضا کرده است”، هرگز نمیگوید “یک انسان این را مجاز کرده است.” برای عملیات پرخطر (بازپرداخت، حذف، انتقال بانکی) چارچوبهای حاکمیتی بیشتر به این بیان گمشده نیاز دارند و این با همان ابتداییاتی که در این درس ساختهاید قابل تولید است.
دفترچه یادداشت بعدی code_samples/human-authorization-receipts.ipynb نوع دوم رسید، human.approval.v1 را اضافه میکند، در همان قالب پاکت موجود در این درس (یک داده تایپشده که با Ed25519 بر روی بایتهای JCS کاننیکال امضا شده، با شیء signature بیرون از بایتهای امضا شده). یک تصویبکننده نامدار، کل عمل کاننیکال و خلاصه آن را قبل از اجرا امضا میکند؛ رسید عمل عامل، همان خلاصه عمل را حمل میکند و یک parent_approval_ref، که receipt_hash تصویب است، همان قرارداد previous_receipt_hash در زنجیرهای که ساختید. یک verify_chain هر دو اثر را زیر رجیستریهای کلید جداگانه پینشده (کلیدهای تصویبکننده در برابر کلیدهای عامل) بررسی میکند، بنابراین مسیر کد مشترک است اما نهادهای صادرکننده هیچگاه مشترک نیستند.
خاصیتی که این روش میخرد، با دقت بیان شده: انسان دقیقاً همین عمل را تصویب کرد و عامل دقیقاً همان عمل تصویبشده را اجرا کرد. قطعات رد کردن دفترچه یادداشت همان چیزی هستند که این خاصیت را واقعی میکند نه صرفاً ادعا:
هر خطا با دلیلی مجزا رد میشود، بنابراین یک حسابرس که رد را میخواند میتواند بفهمد آیا نهاد صادرکننده منقضی شده یا عمل اجرا شده تغییر کرده است. قانونی که دفترچه یادداشت آموزش میدهد: یک تصویب امضا شده به خودی خود نهاد نیست. نهاد زمانی هست که هر دو رسید هنوز به همان عمل کاننیکال در زمان اجرا متعهد باشند. رسید تصویب انسانی ترکیبی آموزشی است که توسط این درس تعریف شده، نه نوع رسید تعریف شده در draft-farley-acta-signed-receipts.
کد پایتون در این درس عمدتاً حداقلی است تا بتوانید هر خط را بخوانید و دقیقاً بفهمید چه اتفاقی میافتد. در تولید، دو گزینه دارید:
مستقیماً بر پایه ابزارهای رمزنگاری بسازید. ۵۰ خط بالا برای بسیاری از موارد کافی است. PyNaCl (Ed25519) و بسته jcs (JSON کاننیکال) کتابخانههای خوب نگهداریشده و ممیزی شده هستند.
از کتابخانه رسید در تولید استفاده کنید. چند پروژه متنباز همین الگو را با ویژگیهای اضافی (چرخش کلید، تأیید دستهای، توزیع JWK Set، ادغام با موتورهای سیاست) پیادهسازی میکنند:
draft-farley-acta-signed-receipts، نسخه ۰۲) استفاده میکند. رسید آموزشی این درس یک ساختار تخت دارد که با پاکت {payload, signature} پروپوزال تفاوت دارد و به عنوان پیادهسازی سازگار ارائه نمیشود. پیشنویس یک مجموعه تست مشترک انتشار میدهد (agent-governance-testvectors) برای پیادهسازیهایی که به فرمت سیمی آن هدف دارند.protect-mcp (npm) و @veritasacta/verify (npm) پیادهسازی Node-based از امضا و تأیید آفلاین رسید را ارائه میکنند، هدف برای پوشش دادن هر سرور MCP با مسیر حسابرسی دارای قابلیت مشاهده دستکاری، شامل جریان نگهداری برای امضای همکاری که یک عمل متوقفشده رسید تصویب به آن ارسال میکند (پشتیبانی WebAuthn در جریان دسکتاپ)، همان الگوی رسید تصویب انسانی در دفترچه یادداشت بالا.pip install nobulex) همان الگوی امضای Ed25519 + JCS را با ادغامهای LangChain و CrewAI ارائه میدهد، شامل بردارهای آزمایش متقاطع منتشر شده و نقشهبرداری تطبیق ارائه شده از طریق OWASP PR #2210.تصمیم میان خودسازی و استفاده از کتابخانه مانند تصمیم بین نوشتن کتابخانه JWT خودتان یا استفاده از کتابخانه تست شده است: هر دو معقولاند؛ کتابخانه زمان صرفهجویی میکند و سطح حسابرسی را کاهش میدهد؛ روش از صفر به شما مجبور میکند هر ابزار را بفهمید. این درس مسیر از صفر را آموزش میدهد تا پایهای برای هر انتخاب داشته باشید.
پیش از رفتن به تمرین عملی، دانش خود را بسنجید.
1. یک رسید با کلید خصوصی Ed25519 عامل امضا میشود. حسابرس فقط کلید عمومی دارد. آیا حسابرس میتواند رسید را به صورت آفلاین تأیید کند؟
2. یک مهاجم فیلد policy_id یک رسید را تغییر میدهد تا ادعا کند تحت سیاستی permissive تر بوده است. امضا روی داده اصلی بود. در تأیید چه اتفاقی میافتد؟
۳. چرا رسید شامل tool_args_hash و result_hash است به جای آرگومانها و نتیجه خام؟
۴. فیلد previous_receipt_hash هر رسید را به پیشدستی آن پیوند میدهد. اگر مهاجمی یک رسید را بهطور مخفیانه از میانه زنجیره حذف کند، چه چیزی نامعتبر میشود؟
۵. یک رسید بهدرستی تأیید میشود. آیا این اثبات میکند که اقدام عامل درست، منطقی یا مطابق سیاست بوده است؟
فایل code_samples/18-signed-receipts.ipynb را باز کنید و چهار بخش را کامل کنید:
۱. بخش ۱: اولین رسید خود را امضا کرده و تأیید کنید. ۲. بخش ۲: رسید را دستکاری کنید و مشاهده کنید که تأیید شکست میخورد. ۳. بخش ۳: زنجیره سهتایی رسید بسازید و یکپارچگی زنجیره را تأیید کنید. ۴. بخش ۴: این الگو را روی عاملی ساخته شده با Microsoft Agent Framework اعمال کنید: فراخوانی ابزار را در امضای رسید بپیچید، سپس رسید را جداگانه تأیید کنید.
چالش اضافی ۱: طرح رسید را با فیلد اضافی دلخواه خود (مثلاً شناسه درخواست برای ردیابی) گسترش دهید، منطق امضای متعارف را برای شامل کردن آن بهروز کنید و تأیید کنید که رسید همچنان بهدرستی تأیید میشود. سپس پس از امضا فیلد را تغییر دهید و ببینید تأیید شکست میخورد. این شما را مجبور میکند بفهمید هر بایت رمزگذاری متعارف چگونه به امضا کمک میکند.
چالش اضافی ۲: دو رسید خود را SHA-256 هش کرده (بایتهای متعارف آنها را به ترتیب قطعی به هم بچسبانید) و digest حاصل را بهعنوان فیلد جدید روی رسید سوم قبل از امضا قرار دهید. تأیید کنید که هر سه رسید همچنان بهدرستی تایید میشوند. این اثبات گنجایش یکمرحلهای است: هر کسی رسید سوم را داشته باشد میتواند اثبات کند که دو رسید اول در زمان امضا وجود داشتهاند، بدون نیاز به افشای محتویات آنها. این الگوی رسیدهای اطلاعرسانی انتخابی در مقیاس است (تعهدات مرکلی، RFC 6962).
رسیدهای رمزنگاریشده برای عوامل هوش مصنوعی ردپای حسابرسی فراهم میکنند که:
آنها جایگزین اعتبارسنجی ورودی، اعمال سیاست، یا زیرساخت هویت نیستند. آنها پایهای برای آن لایهها هستند. وقتی عوامل را در بارکاریهای دارای مقررات، جریانهای کاری چندسازمانی، یا هر محیطی که نمیتوان به ممیز آینده اعتماد کرد مستقر میکنید، رسیدها راهی برای درست و صادقانه نگه داشتن رد حسابرسی هستند.
مهمترین نکته: رسیدها ثابت میکنند که چه کسی چه چیزی گفته و کی. آنها ثابت نمیکنند که گفتهها درست یا صحیح بودهاند. این تمایز را محکم نگه دارید. تفاوت بین یک سیستم اصالت صادقانه و یک سیستم گمراهکننده است.
وقتی آماده رفتن از این درس به استقرار عوامل امضاشده با رسید در محیط واقعی هستید:
https://your-org.example.com/.well-known/agent-keys.json.به Microsoft Foundry Discord بپیوندید تا با سایر یادگیرندگان ملاقات کنید، در ساعات اداری شرکت کنید و سوالهای خود درباره عوامل هوش مصنوعی را پاسخ بگیرید.
این درس امضای تکرسید و دنبالههای هششده را پوشش میدهد. همان اصول اولیه در چند الگوی پیشرفتهتر که ممکن است با بلوغ موضع حاکمیتتان مواجه شوید، ترکیب میشوند:
authorization_*) و پس از اجرا (result_*) با امضاهای مستقل تقسیم میکنند، وقتی تصمیم مجوز و نتیجه مشاهده شده توسط بازیگران متفاوت یا در زمانهای متفاوت تولید میشوند مفید است. این به صورت افزودنی روی فرمت رسید آموزشداده شده اعمال میشود.result_hash قرار میدهید مهر و موم میکند. payload دنیای واقعی اغلب غنیتر از نتیجه یک فراخوان ابزار است: استدلال قبل از تصمیم (پیشبینی مدل، گزینههای بررسی شده، شواهد و کامل بودن آن، وضعیت ریسک، زنجیره مسئولیت، نتیجهٔ دروازه) همگی میتوانند داخل payload باشند و توسط یک رسید مهر شوند. این فرمت رسید را حداقلی نگه میدارد در حالی که اجازه میدهد طرحهای payload به صورت حوزهای تکامل یابند.signature.alg میتواند ML-DSA-65 (استاندارد امضای پساکوانتومی NIST) را حمل کند وقتی نیاز به مهاجرت دارید. دوره انتقال که رسیدها دوگانه امضا میشوند را برنامهریزی کنید.سلب مسئولیت: این سند با استفاده از سرویس ترجمه هوش مصنوعی Co-op Translator ترجمه شده است. در حالی که ما در تلاش برای دقت هستیم، لطفاً توجه داشته باشید که ترجمههای خودکار ممکن است شامل خطاها یا نادرستیهایی باشند. سند اصلی به زبان مادری خود باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حیاتی، ترجمه حرفهای انسانی توصیه میشود. ما در قبال هرگونه سوء تفاهم یا برداشت نادرست ناشی از استفاده از این ترجمه مسئولیتی نداریم.