ai-agents-for-beginners

شاهد فيديو الدرس: تأمين وكلاء الذكاء الاصطناعي باستخدام إيصالات تشفيرية

(فيديو الدرس والصورة المصغرة ستتم إضافتهما بواسطة فريق محتوى مايكروسوفت بعد الدمج، متطابقان مع نمط الدرس 14 / 15.)

تأمين وكلاء الذكاء الاصطناعي باستخدام إيصالات تشفيرية

مقدمة

سيغطي هذا الدرس:

أهداف التعلم

بعد إكمال هذا الدرس، ستكون قادرًا على:

المشكلة: سجل تدقيق الوكيل الخاص بك

تخيل أنك نشرت وكيل ذكاء اصطناعي لشركة Contoso Travel. يقرأ الوكيل طلبات العملاء، ويستخدم واجهة برمجة تطبيقات الرحلات للبحث عن الخيارات، ويحجز المقاعد نيابةً عن العميل. في الربع الماضي، عالج الوكيل 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..."
  }
}

ثلاث خصائص تؤدي العمل:

  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,
}

# توحيد وقّع بايتات 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 خلاف ذلك. لا حاجة إلى اتصال شبكة، لا تبعية خدمة، ولا ثقة بأي طرف ثالث.

لرؤية اكتشاف التلاعب عمليًا، يستعرض الدفتر:

  1. إنتاج إيصال صالح وتأكيد أنه يتحقق.
  2. تعديل بايت واحد في حقل tool_args_hash.
  3. إعادة تشغيل التحقق وملاحظة فشله.

هذا هو الدليل العملي على أن الإيصالات مقاومة للتلاعب: أي تعديل مهما كان صغيرًا يكسر التوقيع.

ربط الإيصالات لوكلاء متعددين الخطوات

يحمي إيصال واحد موقع إجراءً واحدًا. تحمي سلسلة الإيصالات تتابعًا من الإجراءات.

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 بصمت، يحتاج المهاجم إلى إما:

إذا كان المفتاح الخاص محفوظًا في خزنة مفاتيح مادية ونشرت المفتاح العام مع كل إيصال، لا يكون أي هجوم ممكنًا دون الكشف.

يستعرض الدفتر:

  1. بناء سلسلة من ثلاثة إيصالات.
  2. التحقق من أن previous_receipt_hash لكل إيصال يطابق التجزئة الفعلية للإيصال السابق.
  3. التلاعب بإيصال في الوسط ورؤية السلسلة تنكسر عند تلك النقطة بالضبط.

هذه هي الطريقة لإنتاج سجل تدقيق يمكن لمدقق خارجي التحقق منه دون الحاجة إلى الوثوق بك.

ما تثبته الإيصالات (وما لا تثبته)

هذا هو القسم الأهم في هذا الدرس. الإيصالات قوية ولكن قوتها محدودة.

الإيصالات تثبت ثلاثة أشياء:

  1. النسبة: مفتاح محدد وقع حمولة محددة.
  2. السلامة: الحمولة لم تتغير منذ التوقيع.
  3. الترتيب: جاء هذا الإيصال بعد ذاك الإيصال في سلسلة التجزئة.

الإيصالات لا تثبت:

  1. الصحة: أن الإجراء الذي قام به الوكيل هو الإجراء الصحيح. يمكن توقيع إيصال لإجابة خاطئة فقط كما يمكن لجواب صحيح.
  2. الامتثال للسياسة: أن السياسة المشار إليها في policy_id قد تم تقييمها فعليًا، أو أنها كانت ستسمح بهذا الإجراء إذا تم التحقق منها. الإيصال يسجل ما تم الادعاء به، لا ما تم فرضه.
  3. الهوية بما يتجاوز المفتاح: الإيصال يقول “هذا المفتاح وقع هذا المحتوى.” لا يقول “هذا الإنسان وافق على ذلك.” ربط المفتاح بشخص أو منظمة يتطلب بنية هوية منفصلة (دليل، سجل مفتاح عام، إلخ).
  4. صدق المدخلات: إذا استقبل الوكيل مطلبًا مصنوعًا وتصرف بناءً عليه، فإن الإيصال يسجل الإجراء بدقة. الإيصالات تلي التحقق من المدخلات، وليست بديلاً عنه.

هذه الحدود مهمة لسببين:

خطأ شائع هو الافتراض أن “لدينا إيصالات” يعني “نحن محكومون.” هذا غير صحيح. الإيصالات هي الأساس. الحكم هو النظام الذي تبنيه فوقه.

إثبات أن شخصًا بشريًا وافق على الإجراء بالضبط

البند 3 أعلاه يستحق قسمه الخاص: إيصال الإجراء يقول “هذا المفتاح وقع هذا المحتوى”، وليس “إنسانًا وافق على ذلك.” للإجراءات عالية الخطورة (رد المبالغ، الحذف، تحويل الأموال)، تتطلب أطر الحكم بشكل متزايد هذا البيان الناقص بالضبط، ويمكن إنتاجه باستخدام نفس الأدوات التي بنيتها في هذا الدرس.

يضيف الدفتر التتبعي 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.

مراجع الإنتاج

إن كود بايثون في هذا الدرس بسيط عمدًا لتتمكن من قراءة كل سطر وفهم ما يحدث بالضبط. في الإنتاج، لديك خياران:

  1. البناء مباشرة على الأدوات التشفيرية. الخطوط الخمسون التي رأيتها أعلاه كافية للعديد من حالات الاستخدام. PyNaCl (Ed25519) وحزمة jcs (JSON المعياري) من المكتبات المدعومة جيدًا والمراجعة.

  2. استخدام مكتبة إيصالات إنتاجية. تنفذ عدة مشاريع مفتوحة المصدر نفس النمط مع ميزات إضافية (تدوير المفاتيح، التحقق المجمّع، توزيع مجموعة JWK، التكامل مع محركات السياسات):

    • تستخدم سلسلة التوقيع الاتفاقيات JCS ونطاق التوقيع في مسودة IETF مستقلة (draft-farley-acta-signed-receipts، المراجعة 02). يختلف الإيصال التعليمي المسطح في هذا الدرس عن الظرف {payload, signature} في المسودة ولا يُعرض كتنفيذ مطابق. تنشر المسودة مجموعة مطابقة مشتركة (agent-governance-testvectors) للتنفيذات التي تستهدف تنسيق السلك الخاص بها.
    • تتألف مجموعة أدوات حوكمة الوكلاء من مايكروسوفت الإيصالات مع قرارات السياسة القائمة على سيدار؛ انظر الدرس 33 في ذلك المستودع لمثال شامل.
    • توفر حزم protect-mcp (npm) و @veritasacta/verify (npm) تنفيذًا قائمًا على Node لتوقيع الإيصالات والتحقق دون اتصال، مخصصًا لتغليف أي خادم MCP بسجل تدقيق مقاوم للتلاعب، بما في ذلك تدفق موافقة مع تعليق العمل يصدر إيصال موافقة مرتبط بهضم الإجراء (يتم دعم WebAuthn في تدفق سطح المكتب)، نفس نمط إيصال الموافقة البشري في الدفتر أعلاه.
    • توفر حزمة Python SDK nobulex (pip install nobulex) نفس نمط التوقيع Ed25519 + JCS في Python مع تكاملات LangChain و CrewAI، بما في ذلك متجهات اختبار تصديق منشورة ورسم خرائط الامتثال المساهمة عبر OWASP PR #2210.

القرار بين بناء الخاص بك أو استخدام مكتبة يشبه القرار بين كتابة مكتبة JWT خاصة بك أو استخدام مكتبة مختبرة: كلاهما مقبول؛ توفر المكتبة الوقت وتقلل سطح المراجعة؛ الحل من الصفر يجبرك على فهم كل أداة. يعلم هذا الدرس المسار من الصفر حتى يكون لديك الأساس لأي خيار.

اختبار المعرفة

اختبر فهمك قبل الانتقال إلى تمرين الممارسة.

1. يتم توقيع الإيصال بمفتاح Ed25519 الخاص بالوكيل. يمتلك المدقق المفتاح العام فقط. هل يمكن للمدقق التحقق من الإيصال دون اتصال؟

الجواب نعم. يتطلب التحقق Ed25519 مفتاحًا عامًا وبايتات موقعة فقط. لا مكالمة شبكة، لا تبعية خدمة. هذه الخاصية تجعل الإيصالات مفيدة في البيئات المغلقة، متعددة المنظمات، أو منخفضة الثقة.

2. يقوم مهاجم بتعديل حقل policy_id في إيصال ليزعم أنه خضع لسياسة أكثر تساهلًا. كان التوقيع على الحمولة الأصلية. ماذا يحدث أثناء التحقق؟

الجواب فشل التحقق. تم حساب التوقيع على البايتات الكانونية للحمل الأصلي؛ تعديل أي حقل يغير تلك البايتات، مما يجعل التوقيع غير صالح. سيحتاج المهاجم إلى المفتاح الخاص لإنتاج توقيع جديد صالح، وهو ما لا يملكه.

3. لماذا يتضمن الإيصال tool_args_hash و result_hash بدلاً من الوسائط والنتيجة الخام؟

الإجابة لسببين. أولاً، قد يحتاج الإيصال إلى الأرشفة أو الإرسال في بيئات يكون فيها تسريب المحتوى الخام (المعلومات الشخصية، بيانات الأعمال) مشكلة. التجزئة تحافظ على صغر حجم الإيصال وسرية المحتوى؛ يقوم المدقق بالتحقق من تطابق التجزئة مع نسخة مخزنة بشكل منفصل من المحتوى الفعلي. ثانيًا، التجزئات لها حجم ثابت؛ الإيصال الذي يحتوي على تجزئات يكون محدود الحجم بغض النظر عن حجم المدخلات والمخرجات.

4. يربط الحقل previous_receipt_hash كل إيصال بسابقه. إذا حذف مهاجم إيصالاً من وسط سلسلة بصمت، ما الذي يصبح غير صالح؟

الإجابة كل إيصال جاء بعد الإيصال المحذوف. لم تعد حقول `previous_receipt_hash` الخاصة بهم تتطابق مع السلسلة الفعلية (لأن الإيصال الذي أشاروا إليه لم يعد موجوداً، أو أصبحت السلسلة تشير الآن إلى سلف مختلف). لإخفاء الحذف، سيكون على المهاجم إعادة توقيع كل إيصال لاحق، وهذا يتطلب المفتاح الخاص.

5. يتم التحقق من الإيصال بنجاح. هل هذا يثبت أن إجراء الوكيل كان صحيحاً أو سليماً أو متوافقًا مع السياسة؟

الإجابة لا. الإيصال الصالح يثبت ثلاثة أشياء: النسبة (أن هذا المفتاح وقع على هذا المحتوى)، السلامة (المحتوى لم يتغير)، والترتيب (هذا الإيصال جاء بعد ذلك الإيصال). لكنه لا يثبت أن الإجراء كان صحيحًا، أو أن السياسة المسماة في `policy_id` قد تم تقييمها فعلاً، أو أن الوكيل اتبع كل القواعد. الإيصالات تجعل سلوك الوكيل قابلًا للتدقيق، وليس بالضرورة صحيحًا. هذه هي الحدود الأهم في الدرس.

تمرين عملي

افتح code_samples/18-signed-receipts.ipynb وأكمل الأقسام الأربعة كلها:

  1. القسم 1: وقع إيصالك الأول وتحقق منه.
  2. القسم 2: العبث بالإيصال ولاحظ فشل التحقق.
  3. القسم 3: أنشئ سلسلة من ثلاثة إيصالات وتحقق من سلامة السلسلة.
  4. القسم 4: طبق النمط على وكيل مبني باستخدام Microsoft Agent Framework: لف استدعاء أداة بتوقيع الإيصال، ثم تحقق من الإيصال بشكل مستقل.

تحدي إضافي 1: مدد مخطط الإيصال بحقل إضافي من اختيارك (مثلاً، معرف طلب للتتبع)، حدّث منطق التوقيع الكانوني ليشمله، وتأكد من أن الإيصال لا يزال يعبر التحقق. ثم عدل الحقل بعد التوقيع وتأكد من فشل التحقق. هذا يجبرك على فهم كيف يساهم كل بايت من الترميز الكانوني في التوقيع.

تحدي إضافي 2: قم بتجزئة SHA-256 لاثنين من إيصالاتك معاً (اجمع البايتات الكانونية بترتيب حتمي) وادمج الخلاصة الناتجة كحقل جديد في إيصال ثالث قبل توقيعه. تحقق من أن الثلاثة إيصالات لا تزال تمر بالتحقق. لقد أنشأت لتوك إثبات إدراج خطوة واحدة: يمكن لأي شخص يحمل الإيصال الثالث إثبات وجود الإيصالين الأولين وقت توقيعهما، دون الحاجة لكشف محتوياتهم. هذا هو النمط الذي تستخدمه إيصالات الكشف الانتقائي على نطاق واسع (التزامات ميركل، RFC 6962).

خاتمة

تمنح الإيصالات المشفرة لوكلاء الذكاء الاصطناعي مسار تدقيق يكون:

إنها ليست بديلاً عن التحقق من المدخلات، أو تطبيق السياسات، أو بنية الهوية. إنها أساس لتلك الطبقات. عند نشر وكلاء في أعباء عمل منظمة، أو في سير عمل متعدد المؤسسات، أو أي بيئة لا يمكن افتراض ثقة مدقق في المستقبل بك، الإيصالات هي كيف تجعل مسار التدقيق صادقًا.

الدرس الأهم: تثبت الإيصالات من قال ماذا ومتى. لكنها لا تثبت أن ما قيل كان صحيحًا أو صائبًا. تمسك بهذا التمييز بقوة. إنه الفرق بين نظام أصالة صادق وآخر مضلل.

قائمة التحقق للإنتاج

عندما تكون مستعدًا للانتقال من هذا الدرس إلى نشر وكلاء موقّعين بإيصالات في بيئة حقيقية:

هل لديك المزيد من الأسئلة حول تأمين وكلاء الذكاء الاصطناعي؟

انضم إلى Discord مايكروسوفت فاوندري لتلتقي بمتعلمين آخرين، تحضر ساعات العمل، وتحصل على إجابات لأسئلتك عن وكلاء الذكاء الاصطناعي.

ما بعد هذا الدرس

يغطي هذا الدرس توقيع الإيصال الواحد وتسلسلات السلاسل المترابطة بالتجزئة. التركيبات نفسها تتشكل في عدة أنماط متقدمة قد تواجهها مع نضوج وضع الحوكمة لديك:

موارد إضافية

الدرس السابق

إنشاء وكلاء ذكاء اصطناعي محليين


تنويه: تمت ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي Co-op Translator. بينما نسعى للدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو عدم دقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الرسمي والمعتمد. للمعلومات الهامة، يُنصح بالاستعانة بترجمة بشرية محترفة. نحن غير مسؤولين عن أي سوء فهم أو تفسير ناتج عن استخدام هذه الترجمة.