تماشای ویدیو درس: ایمنسازی عوامل هوش مصنوعی با رسیدهای رمزنگاریشده
(ویدیو درس و تصویر کوچک پس از ادغام توسط تیم محتوای مایکروسافت اضافه خواهد شد، مطابق با الگوی درس ۱۴ / ۱۵.)
این درس شامل موارد زیر است:
پس از اتمام این درس، میتوانید:
تصور کنید یک عامل هوش مصنوعی برای شرکت Contoso Travel مستقر کردهاید. این عامل درخواستهای مشتری را میخواند، API پروازها را برای یافتن گزینهها فراخوانی میکند و به نمایندگی از مشتری جایگاهها را رزرو مینماید. در سه ماهه گذشته، این عامل ۵۰,۰۰۰ رزرو را پردازش کرده است.
امروز یک حسابرس میآید. پرسش سادهای میپرسد: «به من نشان دهید عامل شما چه کرده است.»
شما فایلهای گزارش خود را تحویل میدهید. حسابرس آنها را میبیند و پرسش دشوارتر میپرسد: «چگونه بدانم این گزارشها ویرایش نشدهاند؟»
این همان مشکل ردپای حسابرسی است. بیشتر استقرارهای فعلی عامل متکی به موارد زیر هستند:
هیچیک از این موارد نمیتوانند پرسش حسابرس را بدون الزام به اعتماد به کسی (شما، ارائهدهنده ابر، فروشنده پایگاه داده) پاسخ دهند. برای استفاده داخلی، آن اعتماد معمولاً قابل قبول است. برای بارهای کاری دارای مقررات (مالی، بهداشت، هر چیز مشمول قانون هوش مصنوعی اتحادیه اروپا) قابل قبول نیست.
رسیدهای رمزنگاری شده این مشکل را حل میکنند با اینکه هر عمل عامل را به صورت مستقل قابل تأیید میسازند. حسابرس نیازی به اعتماد به شما ندارد. تنها کلید عمومی شما و رسید کافی است.
رسید یک شیء 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..."
}
}
سه ویژگی این کار را انجام میدهند:
امضا. رسید توسط درگاه عامل با استفاده از کلید خصوصی Ed25519 امضا شده است. هر کسی که کلید عمومی متناظر را دارد میتواند امضا را به صورت آفلاین تأیید کند. دستکاری در هر فیلد، امضا را نامعتبر میکند.
کدگذاری کاننیکال. پیش از امضا، رسید با استفاده از طرح کاننیکالسازی JSON (JCS، RFC 8785) سریالیزه میشود. این تضمین میکند که دو پیادهسازی که همان رسید منطقی را تولید میکنند، خروجی بایت-شناساییشده (byte-identical) میسازند. بدون کاننیکالسازی، serializerهای مختلف 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,
}
# استانداردسازی، هش، امضا.
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[رسید ۰<br/>ابتدایی] --> R1[رسید ۱]
R1 --> R2[رسید ۲]
R2 --> R3[رسید ۳]
R1 -. previous_receipt_hash .-> R0
R2 -. previous_receipt_hash .-> R1
R3 -. previous_receipt_hash .-> R2
هر رسید هَش رسید قبلی را ثبت میکند. برای حذف بیصدا رسید شماره ۲، یک مهاجم باید یا:
previous_receipt_hash رسید شماره ۳ را تغییر دهد (امضای رسید ۳ را میشکند)، یااگر کلید خصوصی در یک خزانه کلید سختافزاری باشد و شما کلید عمومی را با هر رسید منتشر کنید، هیچیک از این حملات بدون کشف امکانپذیر نیست.
دفترچه مراحل زیر را طی میکند:
previous_receipt_hash با هَش واقعی رسید قبلی تطابق دارد.اینگونه ردپای حسابرسی ایجاد میشود که یک حسابرس خارجی میتواند بدون اعتماد به شما آن را تأیید کند.
این مهمترین بخش این درس است. رسیدها قدرتمندند اما قدرت آنها محدود است.
رسیدها سه چیز را اثبات میکنند:
رسیدها اثبات نمیکنند:
policy_id واقعاً ارزیابی شده باشد، یا اگر ارزیابی میشد این عمل را مجاز میدانست. رسید آنچه ادعا شده را ثبت میکند، نه آنچه اجرا شده است.این مرز اهمیت دارد از دو جهت:
اشتباه رایج این است که فرض شود «رسید داریم» یعنی «حکمرانی داریم.» این درست نیست. رسیدها بنیادند. حکمرانی سیستمی است که روی آنها میسازید.
کد پایتون در این درس عمداً بسیار کم است تا هر خط را بتوانید بخوانید و دقیقاً بفهمید چه اتفاقی میافتد. در تولید، دو گزینه دارید:
مستقیماً روی ابتداییات رمزنگاری بسازید. ۵۰ خط کدی که دیدید برای بسیاری از موارد کافی است. PyNaCl (Ed25519) و بسته jcs (برای JSON کاننیکال) کتابخانههای خوب نگهداریشده و ممیزی شده هستند.
از یک کتابخانه تولید رسید استفاده کنید. چندین پروژه متنباز همان الگو را با ویژگیهای اضافی (چرخش کلید، تأیید دستهای، توزیع مجموعه JWK، ادغام با موتورهای سیاست) پیادهسازی میکنند:
draft-farley-acta-signed-receipts) منشأ میگیرد که هماکنون در فرایند استانداردسازی است.protect-mcp (npm) و @veritasacta/verify (npm) پیادهسازی Node برای امضای رسید و تأیید آفلاین ارائه میدهند که برای بستهبندی هر سرور MCP با ردپای حسابرسی ضد تغییر طراحی شدهاند.تصمیم بین ساختن از ابتدا و استفاده از کتابخانه مانند انتخاب بین نوشتن کتابخانه JWT خودتان و استفاده از یک کتابخانه آزمودهشده است: هر دو منطقیاند؛ کتابخانه در زمان صرفهجویی میکند و دامنه ممیزی را کاهش میدهد؛ ساختن از ابتدا شما را مجبور میکند هر جزئیات را بفهمید. این درس مسیر ساختن از ابتدا را آموزش میدهد تا پایه را برای هر دو گزینه داشته باشید.
قبل از رفتن به تمرین عملی، دانش خود را بسنجید.
۱. رسید با کلید خصوصی Ed25519 عامل امضا میشود. حسابرس فقط کلید عمومی دارد. آیا حسابرس میتواند رسید را به صورت آفلاین تأیید کند؟
۲. یک مهاجم فیلد policy_id رسید را تغییر میدهد تا ادعا کند توسط سیاستی با اجازه بیشتر حکمرانی شده است. امضا روی بارگذاری اصلی بوده است. در تأیید چه اتفاقی میافتد؟
۳. چرا رسید به جای آرگومانها و نتایج خام، tool_args_hash و result_hash را شامل میشود؟
۴. فیلد previous_receipt_hash هر رسید را به قبلی آن متصل میکند. اگر مهاجمی ساکتانه یک رسید از وسط زنجیره را حذف کند، چه چیزی نامعتبر میشود؟
۵. یک رسید به درستی تأیید شد. آیا این اثبات میکند که فعل عامل درست، منطقی یا مطابق سیاست بوده است؟
دفترچه code_samples/18-signed-receipts.ipynb را باز کرده و همه چهار بخش را کامل کنید:
چالش اضافی ۱: طرح رسید را با یک فیلد اضافی دلخواه گسترش دهید (برای مثال، شناسه درخواست برای ردیابی)، منطق امضای کاننیکال را بهروزرسانی کنید و تأیید کنید که رسید همچنان به درستی از پسوارد (round-trip) تأیید برمیآید. سپس فیلد را پس از امضا تغییر داده و تأیید شکست را مشاهده کنید. این باعث میشود هر بایت از کدگذاری کاننیکال که به امضا کمک میکند را بفهمید. چالش کششی ۲: دو رسید خود را با SHA-256 هش کنید (بایتهای canonical آنها را به ترتیب قطعی به هم متصل کنید) و هش حاصل را به عنوان یک فیلد جدید در رسید سوم قرار دهید قبل از امضا کردن آن. تایید کنید که هر سه رسید هنوز به درستی انتقال پیدا میکنند. شما همین حالا یک اثبات شمول یک مرحلهای ساختهاید: هر کسی که رسید سوم را در دست داشته باشد میتواند اثبات کند که دو رسید اول در زمانی که رسید سوم امضا شده وجود داشتهاند، بدون اینکه محتویات آنها را لو بدهد. این همان الگوی استفاده شده در رسیدهای افشای انتخابی در مقیاس است (تعهدهای مرکلی، RFC 6962).
رسیدهای رمزنگاریشده به عاملهای هوش مصنوعی یک رد حسابرسی ارائه میدهند که:
آنها جایگزینی برای اعتبارسنجی ورودی، اجرای سیاستها یا زیرساخت هویت نیستند. آنها پایهای برای آن لایهها هستند. وقتی عاملهایی را در بارکاریهای تنظیمشده، جریانهای کاری چندسازمانی، یا هر جایی که نمیتوان فرض کرد حسابرس آینده به شما اعتماد داشته باشد، مستقر میکنید، رسیدها راهی هستند که رد حسابرسی را صادقانه نگه میدارند.
مهمترین نکته: رسیدها ثابت میکنند چه کسی چه چیزی گفته، و کی گفته است. آنها ثابت نمیکنند چیزی که گفته شده درست یا صحیح بوده است. این تمایز را محکم نگه دارید. این تفاوت بین یک سیستم اصیل منشأ و یک سیستم گمراهکننده است.
وقتی آماده بودید تا از این درس فارغالتحصیل شده و عاملهایی با رسیدهای امضا شده را در یک محیط واقعی مستقر کنید:
https://your-org.example.com/.well-known/agent-keys.json.به دیسکورد Microsoft Foundry بپیوندید تا با دیگر یادگیرندگان ملاقات کنید، در ساعات اداری شرکت کنید و سوالات خود را درباره عاملهای هوش مصنوعی مطرح کنید.
این درس شامل امضای یک رسید و توالیهای هش زنجیرهای است. همان پرایمیتیوها در چند الگوی پیشرفتهتر که ممکن است با توسعه حکومت شما مواجه شوید، ترکیب میشوند:
authorization_*) و پس از اجرا (result_*) تقسیم میکنند که هر کدام امضای مستقل دارند، مفید زمانی که تصمیم مجوز و نتیجه مشاهده شده توسط بازیگران یا در زمانهای مختلف تولید میشوند. این به صورت افزایشی بر قالب رسید آموزش داده شده این درس افزوده میشود.result_hash قرار دهید مهر میزند. بارهای واقعی اغلب غنیتر از نتیجه یک فراخوان ابزار منفرد هستند: استدلال قبل از تصمیم (پیشبینی مدل، گزینههای مد نظر، شواهد و کامل بودن آن، وضعیت ریسک، زنجیره مسئولیت، نتیجه گیت) همه میتوانند داخل بار قرار داشته باشند، مهر شده با یک رسید واحد. این قالب رسید را کمینه نگه میدارد در حالی که اجازه میدهد اسکیماهای بار بر اساس دامنه تکامل یابند.signature.alg میتواند ML-DSA-65 (استاندارد امضای پساکوانتومی NIST) را حمل کند وقتی نیاز به مهاجرت باشد. برای دوره انتقالی که رسیدها دوگانه امضا شدهاند برنامهریزی کنید.ساخت عاملهای استفاده از رایانه (CUA)
(توسط نگهداران برنامه درسی تعیین خواهد شد)
سلب مسئولیت: این سند با استفاده از سرویس ترجمه هوش مصنوعی Co-op Translator ترجمه شده است. در حالی که ما در تلاش برای دقت هستیم، لطفاً توجه داشته باشید که ترجمههای خودکار ممکن است شامل خطاها یا نادرستیهایی باشند. سند اصلی به زبان مادری خود باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حیاتی، ترجمه حرفهای انسانی توصیه میشود. ما در قبال هرگونه سوء تفاهم یا برداشت نادرست ناشی از استفاده از این ترجمه مسئولیتی نداریم.