ai-agents-for-beginners

تماشای ویدیو درس: ایمن‌سازی عامل‌های هوش مصنوعی با رسیدهای رمزنگاری‌شده

(ویدیو درس و تصویر بندانگشتی توسط تیم محتوای مایکروسافت پس از ادغام افزوده خواهد شد، مطابق الگوی درس ۱۴ / ۱۵.)

ایمن‌سازی عامل‌های هوش مصنوعی با رسیدهای رمزنگاری‌شده

مقدمه

این درس موارد زیر را پوشش می‌دهد:

اهداف آموزشی

پس از پایان این درس، شما خواهید دانست چگونه:

مسئله: ردپای حسابرسی عامل شما

تصور کنید یک عامل هوش مصنوعی را برای 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..."
  }
}

سه ویژگی اصلی کار را انجام می‌دهند:

  1. امضا. رسید توسط دروازه عامل با کلید خصوصی Ed25519 امضا می‌شود. هر کسی که کلید عمومی مربوطه را داشته باشد می‌تواند امضا را به صورت آفلاین بررسی کند. هر دستکاری در هر فیلد امضا را نامعتبر می‌کند.

  2. کدگذاری کاننیکال. قبل از امضا، رسید با استفاده از طرح کاننیکال‌سازی JSON (JCS, RFC 8785) سریالایز می‌شود. این تضمین می‌کند که دو پیاده‌سازی که همان رسید منطقی را تولید می‌کنند، خروجی کاملاً بایتی یکسان ارائه می‌دهند. بدون کاننیکال‌سازی، سریالایزرهای مختلف JSON امضاهای متفاوتی برای همان محتوا تولید می‌کردند.

  3. زنجیره کردن هش. فیلد 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 برمی‌گرداند. بدون تماس شبکه، بدون وابستگی به سرویس، بدون نیاز به اعتماد به شخص ثالثی.

برای دیدن تشخیص دستکاری، دفترچه یادداشت مراحل زیر را طی می‌کند:

  1. تولید یک رسید معتبر و تایید صحت آن.
  2. تغییر یک بایت از فیلد tool_args_hash.
  3. اجرای دوباره بررسی و دیدن شکست آن.

این نشان عملی است که رسیدها دستکاری‌پذیر نیستند: هر تغییر، هر چند کوچک، امضا را می‌شکند.

زنجیره کردن رسیدها برای عامل‌های چندمرحله‌ای

یک رسید امضا شده تنها یک عمل را محافظت می‌کند. زنجیره‌ای از رسیدها دنباله‌ای از اعمال را محافظت می‌کند.

flowchart LR
    R0[رسید ۰<br/>تولد] --> R1[رسید ۱]
    R1 --> R2[رسید ۲]
    R2 --> R3[رسید ۳]
    R1 -. previous_receipt_hash .-> R0
    R2 -. previous_receipt_hash .-> R1
    R3 -. previous_receipt_hash .-> R2

هر رسید هش رسید قبلی را ثبت می‌کند. برای حذف بی‌صدا رسید شماره ۲، یک مهاجم باید یا:

اگر کلید خصوصی در یک گنجینه سخت‌افزاری باشد و شما کلید عمومی را با هر رسید منتشر کنید، هیچ‌یک از این حملات بدون شناسایی ممکن نیست.

دفترچه یادداشت موارد زیر را بررسی می‌کند:

  1. ساخت یک زنجیره سه رسیدی. ۲. تایید اینکه previous_receipt_hash هر رسید با هش واقعی رسید قبلی مطابقت دارد. ۳. دستکاری یک رسید در وسط و مشاهده شکست زنجیره دقیقاً در آن نقطه.

این روش تولید ردپایی است که حسابرس خارجی می‌تواند بدون اعتماد به شما تایید کند.

رسیدها چه چیزی را اثبات می‌کنند (و چه چیزی را اثبات نمی‌کنند)

این مهم‌ترین بخش این درس است. رسیدها قدرتمند هستند اما قدرتشان محدود است.

رسیدها سه چیز را اثبات می‌کنند:

۱. نسبت‌دهی: یک کلید خاص یک بارگذاری خاص را امضا کرده است. ۲. یکپارچگی: بارگذاری از زمان امضا تغییر نکرده است. ۳. ترتیب: این رسید بعد از آن رسید در زنجیره هش آمده است.

رسیدها اثبات نمی‌کنند:

۱. درستی: که عملکرد عامل عملکرد درست بوده است. یک رسید می‌تواند برای پاسخ نادرست به همان وضوحی که برای پاسخ درست امضا شود. ۲. انطباق با سیاست: اینکه سیاست ذکر شده در policy_id واقعاً ارزیابی شده باشد، یا اینکه اگر بررسی می‌شد اجازه این عمل را می‌داد. رسید آنچه ادعا شده را ثبت می‌کند، نه آنچه اجرا شده. ۳. هویت فراتر از کلید: رسید می‌گوید «این کلید این محتوا را امضا کرده.» نمی‌گوید «این انسان این را مجاز کرده.» وصل کردن کلید به یک شخص یا سازمان نیازمند زیرساخت هویت جداگانه (دایرکتوری، رجیستری کلید عمومی و غیره) است. ۴. درستی ورودی‌ها: اگر عامل یک درخواست دستکاری شده دریافت کند و بر اساس آن عمل کند، رسید عمل را دقیقاً ثبت می‌کند. رسیدها بعد از اعتبارسنجی ورودی هستند، نه جایگزین آن.

این مرز به دو دلیل اهمیت دارد:

یک اشتباه رایج این است که فرض کنیم «ما رسید داریم» یعنی «ما قانون‌مندیم.» اینطور نیست. رسیدها پایه هستند. قانون‌گذاری سیستمی است که روی آن می‌سازید.

اثبات اینکه یک انسان دقیقاً این عمل را تأیید کرده است

بند ۳ بالا شایان بخش جداگانه است: رسید عمل می‌گوید «این کلید این محتوا را امضا کرده» هرگز نمی‌گوید «یک انسان این را مجاز کرده.» برای اعمال پرخطر (بازپرداخت‌ها، حذف‌ها، انتقال‌های بانکی)، چارچوب‌های حاکمیتی به طور فزاینده به همین بیان جاافتاده نیاز دارند که این درس همین پایه‌ها را به شما آموزش داده است.

دفترچه یادداشت بعدی code_samples/human-authorization-receipts.ipynb یک نوع رسید دوم، human.approval.v1، اضافه می‌کند که شکل پاکتی مشابه رسیدهای این درس دارد (یک بارگذاری تایپ شده که با Ed25519 روی SHA-256 کاننیکال آن امضا شده، با شیء signature خارج از بایت‌های امضا شده). یک تاییدکننده نامدار قبل از اجرا کل عمل کاننیکال و هش آن را امضا می‌کند؛ رسید عمل عامل همان هش عمل و یک parent_approval_ref دارد که receipt_hash تایید است، همان قراردادی که previous_receipt_hash در زنجیره بالا داشت. یک تابع verify_chain هر دو سند را تحت رجیستری‌های کلید پین‌شده جداگانه (کلیدهای تاییدکننده در مقابل کلیدهای عامل) بررسی می‌کند، بنابراین مسیر کد مشترک است اما نهادها هیچ‌گاه یکی نیستند.

خاصیتی که این می‌خرد، به دقت بیان شده: انسان دقیقا این عمل را تایید کرده و عامل دقیقا همان عمل تایید شده را اجرا کرده است. واکنش‌های رد دفترچه یادداشت آنچه را که این خاصیت را واقعی می‌کند نه صرفاً ادعا شده:

هر خرابی با دلیلی متمایز رد می‌شود، بنابراین یک حسابرس با خواندن رد می‌تواند بگوید آیا قدرت منقضی شده یا عمل اجرا شده تغییر کرده است. قانون دفترچه یادداشت: امضای تایید به خودی خود قدرت نیست. قدرت فقط زمانی وجود دارد که هر دو رسید هنوز به همان عمل کاننیکال در زمان اجرا متصل باشند. مسیر امضای مشترک در همان پیش‌نویس اینترنتی که این درس دنبال می‌کند (draft-farley-acta-signed-receipts) شکل استاندارد این الگو است.

منابع تولید

کد پایتون در این درس عمداً حداقلی است تا بتوانید هر خط را بخوانید و دقیقاً بفهمید چه اتفاقی می‌افتد. در تولید، دو گزینه دارید:

۱. مستقیماً روی ابتدایی‌های رمزنگاری بسازید. ۵۰ خطی که دیدید برای بسیاری از موارد کافی است. PyNaCl (Ed25519) و بسته jcs (JSON کاننیکال) کتابخانه‌های خوب نگهداری شده و ممیزی‌شده هستند.

۲. از کتابخانه تولید رسید استفاده کنید. چند پروژه متن‌باز همان الگو را با ویژگی‌های اضافی (چرخش کلید، بررسی دسته‌ای، توزیع JWK Set، ادغام با موتورهای سیاست) پیاده‌سازی می‌کنند:

انتخاب بین ساختن از صفر و استفاده از کتابخانه شبیه انتخاب بین نوشتن کتابخانه JWT خودتان یا استفاده از کتابخانه تست شده است: هر دو منطقی است؛ کتابخانه وقت صرفه‌جویی می‌کند و سطح ممیزی را کاهش می‌دهد؛ رویکرد از صفر شما را وادار می‌کند هر ابتدایی را بفهمید. این درس مسیر از صفر را آموزش می‌دهد تا پایه برای هر انتخاب داشته باشید.

آزمون دانسته‌ها

قبل از رفتن به تمرین، درک خود را آزمایش کنید.

۱. رسید با کلید خصوصی Ed25519 عامل امضا شده است. حسابرس فقط کلید عمومی را دارد. آیا حسابرس می‌تواند رسید را به صورت آفلاین بررسی کند؟

پاسخ بله. بررسی Ed25519 تنها کلید عمومی و بایت‌های امضا شده را نیاز دارد. بدون تماس شبکه، بدون وابستگی به سرویس. این خاصیت، رسیدها را در محیط‌های بدون اتصال به شبکه، چندسازمانی، یا کم‌اعتماد قابل استفاده می‌کند.

۲. یک مهاجم فیلد policy_id یک رسید را تغییر می‌دهد تا ادعا کند تحت سیاستی با مجوز بیشتر بوده است. امضا روی بارگذاری اصلی بوده است. در هنگام بررسی چه اتفاقی می‌افتد؟

پاسخ تأیید ناموفق است. امضا بر روی بایت‌های قانونی محتوای اصلی محاسبه شده بود؛ تغییر هر فیلدی باعث تغییر بایت‌های قانونی می‌شود، که هَش SHA-256 را تغییر می‌دهد و امضا را نامعتبر می‌کند. حمله‌کننده برای تولید امضای جدید و معتبر به کلید خصوصی نیاز دارد، که در اختیار ندارد.

۳. چرا رسید شامل tool_args_hash و result_hash است به جای آرگومان‌ها و نتیجه خام؟

پاسخ دو دلیل وجود دارد. اولاً، ممکن است لازم باشد رسید در محیط‌هایی بایگانی یا منتقل شود که افشای محتوای خام (اطلاعات شخصی، داده‌های تجاری) مشکل‌ساز است. هش کردن باعث کوچک ماندن رسید و حفظ محرمانگی محتوا می‌شود؛ ممیز اطمینان حاصل می‌کند که هش با نسخه‌ی جداگانه‌ی ذخیره‌شده‌ی محتوای واقعی مطابقت دارد. دوم، هش‌ها اندازه ثابت دارند؛ رسیدی با هَش‌ها اندازه محدودی دارد فارغ از بزرگی ورودی‌ها و خروجی‌ها.

۴. فیلد previous_receipt_hash هر رسید را به رسید قبلی متصل می‌کند. اگر حمله‌کننده بی‌صدا یکی از رسیدها را از وسط هر زنجیره حذف کند، چه چیزی نامعتبر می‌شود؟

پاسخ هر رسیدی که بعد از رسید حذف شده آمده است. فیلدهای `previous_receipt_hash` آنها دیگر با زنجیره واقعی مطابقت ندارند (زیرا رسید مرجع دیگر وجود ندارد یا زنجیره اکنون به پیش‌درآمد متفاوتی اشاره می‌کند). برای پنهان کردن این حذف، حمله‌کننده باید همه رسیدهای بعدی را دوباره امضا کند که نیاز به کلید خصوصی دارد.

۵. یک رسید به درستی تأیید می‌شود. آیا این اثبات می‌کند که اقدام عامل درست، صحیح یا مطابق سیاست بوده است؟

پاسخ خیر. یک رسید معتبر سه چیز را اثبات می‌کند: انتساب (این کلید این محتوا را امضا کرده است)، یکپارچگی (محتوا تغییر نکرده است)، و ترتیب (این رسید بعد از آن رسید آمده است). این اثبات نمی‌کند که اقدام درست بوده یا سیاست ذکر شده در `policy_id` واقعاً ارزیابی شده یا عامل همه قوانین را رعایت کرده است. رسیدها رفتار عامل را قابل حسابرسی می‌کنند، نه لزوماً درست. این مهم‌ترین مرز این درس است.

تمرین عملی

فایل code_samples/18-signed-receipts.ipynb را باز کنید و همه چهار بخش را کامل کنید:

۱. بخش ۱: اولین رسید خود را امضا کنید و تأییدش کنید. ۲. بخش ۲: با رسید دستکاری کنید و مشاهده کنید که تأیید ناموفق می‌شود. ۳. بخش ۳: زنجیره‌ای از سه رسید بسازید و یکپارچگی زنجیره را تأیید کنید. ۴. بخش ۴: الگو را برای عاملی ساخته‌شده با Microsoft Agent Framework اعمال کنید: یک فراخوان ابزار را در امضای رسید بپیچید، سپس رسید را به‌طور مستقل تأیید کنید.

چالش توسعه ۱: ساختار رسید را با یک فیلد اضافی دلخواه (مثلاً شناسه درخواست برای ردیابی) گسترش دهید، منطق امضای قانونی را برای آن به‌روزرسانی کنید و تأیید کنید که رسید هنوز هم به درستی توسط تأیید عبور می‌کند. سپس پس از امضا فیلد را تغییر داده و تأیید ناموفق شود. این باعث می‌شود بفهمید هر بایت از کدگذاری قانونی چگونه به امضا کمک می‌کند.

چالش توسعه ۲: دو رسید را با هم به صورت هش SHA-256 ترکیب کنید (بایت‌های قانونی آنها را با ترتیب تعیین شده به هم بچسبانید) و هش حاصل را به صورت فیلد جدید روی رسید سومی وارد کنید قبل از امضا. تأیید کنید هر سه رسید هنوز هم به درستی می‌چرخند. شما اکنون یک اثبات شمول یک مرحله‌ای ساخته‌اید: هرکسی که رسید سوم را دارد می‌تواند اثبات کند دو رسید اول هنگام امضا وجود داشته‌اند، بدون نیاز به افشای محتوایشان. این الگو در رسیدهای با افشاء انتخابی در مقیاس بزرگ استفاده می‌شود (تعهدات مرکِل، RFC 6962).

نتیجه‌گیری

رسیدهای رمزنگاری‌شده به عوامل هوش مصنوعی یک رد حسابرسی می‌دهند که:

آنها جایگزینی برای اعتبارسنجی ورودی، اجرای سیاست، یا زیرساخت هویتی نیستند. بلکه پایه‌ای برای این لایه‌ها هستند. هنگام استقرار عامل‌ها در بارهای کاری تنظیم شده، جریان‌های کاری چندسازمانی یا هر محیطی که ممیزی‌کننده آتی به شما اعتماد نمی‌کند، رسیدها راهی برای درست بودن رد حسابرسی هستند.

مهم‌ترین نکته: رسیدها اثبات می‌کنند چه کسی چه چیزی را کی گفته است. آنها اثبات نمی‌کنند که گفته‌شده درست یا صحیح است. این تمایز را محکم نگه دارید. تفاوت بین یک سیستم منشاء صحیح و یک سیستم گمراه‌کننده است.

چک‌لیست تولید

هنگام آماده شدن برای گذر از این درس به استقرار عامل‌های امضاشده در محیط واقعی:

سوالات بیشتر درباره امنیت عامل‌های هوش مصنوعی؟

به Microsoft Foundry Discord بپیوندید تا با دیگر یادگیرندگان ملاقات کنید، در ساعات حضور شرکت کنید و سوالات خود درباره عامل‌های هوش مصنوعی را پاسخ بگیرید.

فراتر از این درس

این درس امضای تک‌رسید و توالی‌های زنجیره‌ای هش‌شده را پوشش می‌دهد. همان ابتدایی‌ها در چند الگوی پیشرفته‌تر ترکیب می‌شوند که ممکن است با پیشرفت موضع حاکمیت خود با آنها مواجه شوید:

منابع بیشتر

درس قبلی

ساخت عامل‌های محلی هوش مصنوعی


سلب مسئولیت: این سند با استفاده از سرویس ترجمه هوش مصنوعی Co-op Translator ترجمه شده است. در حالی که ما در تلاش برای دقت هستیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است شامل خطاها یا نادرستی‌هایی باشند. سند اصلی به زبان مادری خود باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حیاتی، ترجمه حرفه‌ای انسانی توصیه می‌شود. ما در قبال هرگونه سوء تفاهم یا برداشت نادرست ناشی از استفاده از این ترجمه مسئولیتی نداریم.