إيصالات معاملات كتابة دفتر الأستاذ السري من Azure

لفرض ضمانات تكامل المعاملات، يستخدم Azure Confidential Ledger بنية بيانات شجرة Merkle لتسجيل تجزئة جميع كتل المعاملات الملحقة بدفتر الأستاذ غير القابل للتغيير. بعد تنفيذ معاملة كتابة، يمكن لمستخدمي Azure Confidential Ledger الحصول على إثبات Merkle مشفر، أو إيصال، عبر الإدخال الذي تم إنتاجه في Confidential Ledger للتحقق من حفظ عملية الكتابة بشكل صحيح. إيصال معاملة الكتابة هو دليل على أن النظام قد ارتكب المعاملة المقابلة ويمكن استخدامه للتحقق من أن الإدخال قد تم إلحاقه بدفتر الأستاذ بشكل فعال.

يمكن العثور على مزيد من التفاصيل حول كيفية استخدام شجرة Merkle في دفتر الأستاذ السري في وثائق CCF.

الحصول على إيصالات معاملات الكتابة

الإعداد والمتطلبات الأساسية

يمكن لمستخدمي Azure Confidential Ledger الحصول على إيصال معاملة معينة باستخدام مكتبة عميل Azure Confidential Ledger. يوضح المثال التالي كيفية الحصول على إيصال كتابة باستخدام مكتبة العميل ل Python، ولكن الخطوات هي نفسها مع أي SDK مدعومة أخرى ل Azure Confidential Ledger.

نفترض أنه تم بالفعل إنشاء مورد Confidential Ledger باستخدام مكتبة Azure Confidential Ledger Management. إذا لم يكن لديك مورد دفتر الأستاذ موجود حتى الآن، فقم بإنشاء مورد باستخدام الإرشادات التالية.

معاينة التعليمات البرمجية

نبدأ بإعداد عمليات الاستيراد لبرنامج Python الخاص بنا.

import json 

# Import the Azure authentication library 
from azure.identity import DefaultAzureCredential 

# Import the Confidential Ledger Data Plane SDK 
from azure.confidentialledger import ConfidentialLedgerClient 
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient 

فيما يلي القيم الثابتة المستخدمة لإعداد عميل Azure Confidential Ledger. تأكد من تحديث ledger_name الثابت بالاسم الفريد لمورد Confidential Ledger.

# Constants for our program 
ledger_name = "<your-unique-ledger-name>" 
identity_url = "https://identity.confidential-ledger.core.azure.com" 
ledger_url = "https://" + ledger_name + ".confidential-ledger.azure.com" 

نقوم بالمصادقة باستخدام فئة DefaultAzureCredential.

# Setup authentication 
credential = DefaultAzureCredential() 

بعد ذلك، نحصل على شهادة خدمة Confidential Ledger ونحفظها باستخدام عميل الشهادة من عنوان URL لهوية دفتر الأستاذ السري. شهادة الخدمة هي شهادة مفتاح عام لهوية الشبكة تستخدم كجذر للثقة لمصادقة خادم TLS . بمعنى آخر، يتم استخدامه كمرجع مصدق (CA) لإنشاء اتصال TLS مع أي من العقد في شبكة CCF.

# Create a Certificate client and use it to 
# get the service identity for our ledger 
identity_client = ConfidentialLedgerCertificateClient(identity_url) 
network_identity = identity_client.get_ledger_identity( 
     ledger_id=ledger_name 
)

# Save network certificate into a file for later use 
ledger_tls_cert_file_name = "network_certificate.pem" 

with open(ledger_tls_cert_file_name, "w") as cert_file: 
    cert_file.write(network_identity["ledgerTlsCertificate"]) 

بعد ذلك، يمكننا استخدام بيانات الاعتماد الخاصة بنا وشهادة الشبكة التي تم جلبها وعنوان URL الفريد لدفتر الأستاذ لإنشاء عميل Confidential Ledger.

# Create Confidential Ledger client 
ledger_client = ConfidentialLedgerClient( 
     endpoint=ledger_url,  
     credential=credential, 
     ledger_certificate_path=ledger_tls_cert_file_name 
) 

باستخدام عميل Confidential Ledger، يمكننا تشغيل أي عمليات مدعومة على مثيل Azure Confidential Ledger. على سبيل المثال، يمكننا إلحاق إدخال جديد بدفتر الأستاذ والانتظار حتى يتم الالتزام بمعاملة الكتابة المقابلة.

# The method begin_create_ledger_entry returns a poller that  
# we can use to wait for the transaction to be committed 
create_entry_poller = ledger_client.begin_create_ledger_entry( 
    {"contents": "Hello World!"} 
)

create_entry_result = create_entry_poller.result() 

بعد تنفيذ المعاملة، يمكننا استخدام العميل للحصول على إيصال عبر الإدخال الملحق بدفتر الأستاذ في الخطوة السابقة باستخدام معرف المعاملة المعني.

# The method begin_get_receipt returns a poller that  
# we can use to wait for the receipt to be available by the system 
get_receipt_poller = ledger_client.begin_get_receipt( 
    create_entry_result["transactionId"] 
)

get_receipt_result = get_receipt_poller.result() 

عينة التعليمات البرمجية

يتم توفير نموذج التعليمات البرمجية الكامل المستخدم في معاينة التعليمات البرمجية.

import json 

# Import the Azure authentication library 
from azure.identity import DefaultAzureCredential 

# Import the Confidential Ledger Data Plane SDK 
from azure.confidentialledger import ConfidentialLedgerClient 
from azure.confidentialledger.certificate import ConfidentialLedgerCertificateClient 

from receipt_verification import verify_receipt 

# Constants 
ledger_name = "<your-unique-ledger-name>" 
identity_url = "https://identity.confidential-ledger.core.azure.com" 
ledger_url = "https://" + ledger_name + ".confidential-ledger.azure.com" 

# Setup authentication 
credential = DefaultAzureCredential() 

# Create Ledger Certificate client and use it to 
# retrieve the service identity for our ledger 
identity_client = ConfidentialLedgerCertificateClient(identity_url) 
network_identity = identity_client.get_ledger_identity(ledger_id=ledger_name) 

# Save network certificate into a file for later use 
ledger_tls_cert_file_name = "network_certificate.pem" 

with open(ledger_tls_cert_file_name, "w") as cert_file: 
    cert_file.write(network_identity["ledgerTlsCertificate"]) 

# Create Confidential Ledger client 
ledger_client = ConfidentialLedgerClient( 
    endpoint=ledger_url, 
    credential=credential, 
    ledger_certificate_path=ledger_tls_cert_file_name, 
) 

# The method begin_create_ledger_entry returns a poller that 
# we can use to wait for the transaction to be committed 
create_entry_poller = ledger_client.begin_create_ledger_entry( 
    {"contents": "Hello World!"} 
) 
create_entry_result = create_entry_poller.result() 

# The method begin_get_receipt returns a poller that 
# we can use to wait for the receipt to be available by the system 
get_receipt_poller = ledger_client.begin_get_receipt( 
    create_entry_result["transactionId"] 
) 
get_receipt_result = get_receipt_poller.result() 

# Save fetched receipt into a file
with open("receipt.json", "w") as receipt_file: 
    receipt_file.write(json.dumps(get_receipt_result, sort_keys=True, indent=2)) 

كتابة محتوى إيصال المعاملة

فيما يلي مثال على حمولة استجابة JSON التي تم إرجاعها بواسطة مثيل Azure Confidential Ledger عند استدعاء GET_RECEIPT نقطة النهاية.

{
    "receipt": {
        "cert": "-----BEGIN CERTIFICATE-----\nMIIB0jCCAXmgAwIBAgIQPxdrEtGY+SggPHETin1XNzAKBggqhkjOPQQDAjAWMRQw\nEgYDVQQDDAtDQ0YgTmV0d29yazAeFw0yMjA3MjAxMzUzMDFaFw0yMjEwMTgxMzUz\nMDBaMBMxETAPBgNVBAMMCENDRiBOb2RlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\nQgAEWy81dFeEZ79gVJnfHiPKjZ54fZvDcFlntFwJN8Wf6RZa3PaV5EzwAKHNfojj\noXT4xNkJjURBN7q+1iE/vvc+rqOBqzCBqDAJBgNVHRMEAjAAMB0GA1UdDgQWBBQS\nwl7Hx2VkkznJNkVZUbZy+TOR/jAfBgNVHSMEGDAWgBTrz538MGI/SdV8k8EiJl5z\nfl3mBTBbBgNVHREEVDBShwQK8EBegjNhcGljY2lvbmUtdGVzdC1sZWRnZXIuY29u\nZmlkZW50aWFsLWxlZGdlci5henVyZS5jb22CFWFwaWNjaW9uZS10ZXN0LWxlZGdl\ncjAKBggqhkjOPQQDAgNHADBEAiAsGawDcYcH/KzF2iK9Ldx/yABUoYSNti2Cyxum\n9RRNKAIgPB/XGh/FQS3nmZLExgBVXkDYdghQu/NCY/hHjQ9AvWg=\n-----END CERTIFICATE-----\n",
        "leafComponents": {
            "claimsDigest": "0000000000000000000000000000000000000000000000000000000000000000",
            "commitEvidence": "ce:2.40:f36ffe2930ec95d50ebaaec26e2bec56835abd051019eb270f538ab0744712a4",
            "writeSetDigest": "8452624d10bdd79c408c0f062a1917aa96711ea062c508c745469636ae1460be"
        },
        "nodeId": "70e995887e3e6b73c80bc44f9fbb6e66b9f644acaddbc9c0483cfc17d77af24f",
        "proof": [
            {
                "left": "b78230f9abb27b9b803a9cae4e4cec647a3be1000fc2241038867792d59d4bc1"
            },
            {
                "left": "a2835d4505b8b6b25a0c06a9c8e96a5204533ceac1edf2b3e0e4dece78fbaf35"
            }
        ],
        "signature": "MEUCIQCjtMqk7wOtUTgqlHlCfWRqAco+38roVdUcRv7a1G6pBwIgWKpCSdBmhzgEdwguUW/Cj/Z5bAOA8YHSoLe8KzrlqK8="
    },
    "state": "Ready",
    "transactionId": "2.40"
}

تحتوي استجابة JSON على الحقول التالية على مستوى الجذر.

  • الإيصال: يحتوي على القيم التي يمكن استخدامها للتحقق من صحة الإيصال معاملة الكتابة المقابلة.

  • الحالة: حالة استجابة JSON التي تم إرجاعها. فيما يلي القيم المحتملة المسموح بها:

    • Ready: الإيصال الذي تم إرجاعه في الاستجابة متاح
    • Loading: الإيصال غير متوفر بعد لاسترداده ويجب إعادة محاولة الطلب
  • transactionId: معرف المعاملة المقترن بإيصال معاملة الكتابة.

receipt يحتوي الحقل على الحقول التالية.

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

  • nodeId: سلسلة سداسية عشرية تمثل ملخص التجزئة SHA-256 للمفتاح العام لعقدة توقيع CCF.

  • leafComponents: مكونات تجزئة العقدة الطرفية في شجرة Merkle المقترنة بالمعاملة المحددة. شجرة Merkle هي بنية بيانات شجرة تسجل تجزئة كل معاملة وتضمن تكامل دفتر الأستاذ. لمزيد من المعلومات حول كيفية استخدام شجرة Merkle في CCF، راجع وثائق CCF ذات الصلة.

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

  • serviceEndorsements: قائمة سلاسل الشهادات المشفرة من PEM التي تمثل شهادات هويات الخدمة السابقة. من المحتمل أن هوية الخدمة التي أيدت عقدة التوقيع ليست هي نفسها التي أصدرت الإيصال. على سبيل المثال، يتم تجديد شهادة الخدمة بعد الإصلاح بعد كارثة لدفتر الأستاذ السري. تسمح قائمة شهادات الخدمة السابقة للمدققين ببناء سلسلة الثقة من عقدة توقيع CCF إلى شهادة الخدمة الحالية.

  • التوقيع: سلسلة Base64 التي تمثل توقيع جذر شجرة Merkle في المعاملة المحددة، عن طريق عقدة توقيع CCF.

leafComponents يحتوي الحقل على الحقول التالية.

  • claimsDigest: سلسلة سداسية عشرية تمثل ملخص التجزئة SHA-256 لمطالبة التطبيق المرفقة بتطبيق Confidential Ledger في وقت تنفيذ المعاملة. مطالبات التطبيق غير مدعومة حاليا لأن تطبيق Confidential Ledger لا يرفق أي مطالبة عند تنفيذ معاملة كتابة.

  • commitEvidence: سلسلة فريدة يتم إنتاجها لكل معاملة، مشتقة من معرف المعاملة وأسرار دفتر الأستاذ. لمزيد من المعلومات حول دليل التثبيت، راجع وثائق CCF ذات الصلة.

  • writeSetDigest: سلسلة سداسية عشرية تمثل ملخص التجزئة SHA-256 لمخزن Key-Value، والذي يحتوي على جميع المفاتيح والقيم المكتوبة في وقت اكتمال المعاملة. لمزيد من المعلومات حول مجموعة الكتابة، راجع وثائق CCF ذات الصلة.

مطالبات التطبيق

يمكن لتطبيقات Azure Confidential Ledger إرفاق بيانات عشوائية، تسمى مطالبات التطبيق، لكتابة المعاملات. تمثل هذه المطالبات الإجراءات التي تم تنفيذها أثناء عملية الكتابة. عند إرفاقه بمعاملة، يتم تضمين ملخص SHA-256 لكائن المطالبات في دفتر الأستاذ ويتم تثبيته كجزء من معاملة الكتابة. يضمن تضمين المطالبة في معاملة الكتابة تسجيل ملخص المطالبة في مكانه ولا يمكن العبث به.

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

مطالبات التطبيق مدعومة حاليا في إصدار 2023-01-18-previewواجهة برمجة تطبيقات المعاينة .

كتابة محتوى إيصال المعاملة مع مطالبات التطبيق

فيما يلي مثال على حمولة استجابة JSON التي تم إرجاعها بواسطة مثيل Azure Confidential Ledger الذي سجل مطالبات التطبيق، عند استدعاء GET_RECEIPT نقطة النهاية.

{
  "applicationClaims": [
    {
      "kind": "LedgerEntry",
      "ledgerEntry": {
        "collectionId": "subledger:0",
        "contents": "Hello world",
        "protocol": "LedgerEntryV1",
        "secretKey": "Jde/VvaIfyrjQ/B19P+UJCBwmcrgN7sERStoyHnYO0M="
      }
    }
  ],
  "receipt": {
    "cert": "-----BEGIN CERTIFICATE-----\nMIIBxTCCAUygAwIBAgIRAMR89lUNeIghDUfpyHi3QzIwCgYIKoZIzj0EAwMwFjEU\nMBIGA1UEAwwLQ0NGIE5ldHdvcmswHhcNMjMwNDI1MTgxNDE5WhcNMjMwNzI0MTgx\nNDE4WjATMREwDwYDVQQDDAhDQ0YgTm9kZTB2MBAGByqGSM49AgEGBSuBBAAiA2IA\nBB1DiBUBr9/qapmvAIPm1o3o3LRViSOkfFVI4oPrw3SodLlousHrLz+HIe+BqHoj\n4nBjt0KAS2C0Av6Q+Xg5Po6GCu99GQSoSfajGqmjy3j3bwjsGJi5wHh1pNbPmMm/\nTqNhMF8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUCPaDohOGjVgQ2Lb8Pmubg7Y5\nDJAwHwYDVR0jBBgwFoAU25KejcEmXDNnKvSLUwW/CQZIVq4wDwYDVR0RBAgwBocE\nfwAAATAKBggqhkjOPQQDAwNnADBkAjA8Ci9myzieoLoIy+7mUswVEjUG3wrEXtxA\nDRmt2PK9bTDo2m3aJ4nCQJtCWQRUlN0CMCMOsXL4NnfsSxaG5CwAVkDwLBUPv7Zy\nLfSh2oZ3Wn4FTxL0UfnJeFOz/CkDUtJI1A==\n-----END CERTIFICATE-----\n",
    "leafComponents": {
      "claimsDigest": "d08d8764437d09b2d4d07d52293cddaf40f44a3ea2176a0528819a80002df9f6",
      "commitEvidence": "ce:2.13:850a25da46643fa41392750b6ca03c7c7d117c27ae14e3322873de6322aa7cd3",
      "writeSetDigest": "6637eddb8741ab54cc8a44725be67fd9be390e605f0537e5a278703860ace035"
    },
    "nodeId": "0db9a22e9301d1167a2a81596fa234642ad24bc742451a415b8d653af056795c",
    "proof": [
      {
        "left": "bcce25aa51854bd15257cfb0c81edc568a5a5fa3b81e7106c125649db93ff599"
      },
      {
        "left": "cc82daa27e76b7525a1f37ed7379bb80f6aab99f2b36e2e06c750dd9393cd51b"
      },
      {
        "left": "c53a15cbcc97e30ce748c0f44516ac3440e3e9cc19db0852f3aa3a3d5554dfae"
      }
    ],
    "signature": "MGYCMQClZXVAFn+vflIIikwMz64YZGoH71DKnfMr3LXkQ0lhljSsvDrmtmi/oWwOsqy28PsCMQCMe4n9aXXK4R+vY0SIfRWSCCfaADD6teclFCkVNK4317ep+5ENM/5T/vDJf3V4IvI="
  },
  "state": "Ready",
  "transactionId": "2.13"
}

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

  • النوع: يمثل نوع مطالبة التطبيق. تشير القيمة إلى كيفية تحليل كائن مطالبة التطبيق للنوع المتوفر.

  • ledgerEntry: يمثل مطالبة تطبيق مشتقة من بيانات إدخال دفتر الأستاذ. ستحتوي المطالبة على البيانات التي سجلها التطبيق أثناء معاملة الكتابة (على سبيل المثال، معرف المجموعة والمحتويات التي يوفرها المستخدم) والمعلومات المطلوبة لحساب الملخص المقابل لكائن المطالبة الواحد.

  • ملخص: يمثل مطالبة تطبيق في شكل ملخص. سيحتوي كائن المطالبة هذا على الملخص المحسوب مسبقا بواسطة التطبيق والبروتوكول المستخدم للحساب.

ledgerEntry يحتوي الحقل على الحقول التالية.

  • البروتوكول: يمثل البروتوكول الذي سيتم استخدامه لحساب ملخص مطالبة من بيانات المطالبة المحددة.

  • collectionId: معرف المجموعة المكتوبة أثناء معاملة الكتابة المقابلة.

  • المحتويات: محتويات دفتر الأستاذ المكتوبة أثناء معاملة الكتابة المقابلة.

  • secretKey: مفتاح سري مشفر ب base64. سيتم استخدام هذا المفتاح في خوارزمية HMAC مع القيم المتوفرة في مطالبة التطبيق للحصول على ملخص المطالبة.

digest يحتوي الحقل على الحقول التالية.

  • البروتوكول: يمثل البروتوكول المستخدم لحساب ملخص المطالبة المحددة.

  • value: ملخص مطالبة التطبيق، في شكل سداسي عشري. يجب تجزئة هذه القيمة بالقيمة protocol لحساب الملخص الكامل لمطالبة التطبيق.

المزيد من الموارد

لمزيد من المعلومات حول إيصالات معاملة الكتابة وكيف يضمن CCF تكامل كل معاملة، راجع الارتباطات التالية:

الخطوات التالية