Поделиться через


Квитанции о транзакциях записи в Конфиденциальном реестре Azure

Чтобы обеспечить гарантии целостности транзакций, конфиденциальный реестр Azure использует структуру данных дерева Меркл для записи хэша всех блоков транзакций, добавляемых в неизменяемый реестр. После фиксации транзакции записи пользователи Конфиденциального реестра Azure могут получить криптографическое подтверждение меркла или квитанцию по записи, созданной в конфиденциальном реестре, чтобы убедиться, что операция записи была сохранена правильно. Квитанция о транзакции записи является доказательством того, что система зафиксировала соответствующую транзакцию, и может использоваться для проверки того, что запись была эффективно добавлена в реестр.

Дополнительные сведения об использовании дерева Меркла в конфиденциальном реестре см. в документации по CCF.

Получение квитанций о транзакциях записи

Настройка и необходимые компоненты

Пользователи Конфиденциального реестра Azure могут получить квитанцию о конкретной транзакции с помощью клиентской библиотеки Конфиденциального реестра Azure. В следующем примере показано, как получить уведомление о записи с помощью клиентской библиотеки для Python, но шаги аналогичны любому другому поддерживаемому пакету SDK для Конфиденциального реестра Azure.

Предполагается, что ресурс конфиденциального реестра уже создан с помощью библиотеки управления конфиденциальным реестром Azure. Если у вас еще нет ресурса реестра, создайте его, следуя приведенным ниже инструкциям.

Пошаговое руководство по написанию кода

Начнем с настройки импорта для нашей программы 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. Обязательно обновите константу ledger_name , указав уникальное имя ресурса Конфиденциального реестра.

# 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() 

Затем мы получаем и сохраняем сертификат службы конфиденциального реестра с помощью клиента сертификата из URL-адреса удостоверения конфиденциального реестра. Сертификат службы — это сертификат открытого ключа сетевого удостоверения, используемый в качестве корня доверия для проверки подлинности СЕРВЕРА TLS . Другими словами, он используется в качестве центра сертификации (ЦС) для установления 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-адрес реестра для создания клиента конфиденциального реестра.

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

С помощью клиента Конфиденциального реестра можно выполнять любые поддерживаемые операции в экземпляре Конфиденциального реестра Azure. Например, можно добавить новую запись в реестр и дождаться фиксации соответствующей транзакции записи.

# 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 при вызове конечной 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 содержит следующие поля на корневом уровне.

  • receipt: содержит значения, которые можно использовать для проверки действительности квитанции для соответствующей транзакции записи.

  • state: состояние возвращенного ответа JSON. Ниже приведены возможные допустимые значения.

    • Ready: квитанция, возвращенная в ответе, доступна.
    • Loading: квитанция еще недоступна для получения, и запрос необходимо повторно выполнить.
  • transactionId: идентификатор транзакции, связанный с квитанцией о транзакции записи.

Поле receipt содержит следующие поля.

  • cert: строка с сертификатом открытого ключа PEM узла CCF, подписавшего транзакцию записи. Сертификат удостоверения службы всегда должен поддерживать сертификат узла подписывания. Дополнительные сведения о том, как транзакции регулярно подписываются и как транзакции подписи добавляются в реестр в CCF, см. по следующей ссылке.

  • nodeId: шестнадцатеричная строка, представляющая хэш-хэш SHA-256 открытого ключа узла CCF подписывания.

  • leafComponents: компоненты хэша конечного узла в дереве Меркла , связанные с указанной транзакцией. Дерево Меркла — это древовидная структура данных, которая записывает хэш каждой транзакции и гарантирует целостность реестра. Дополнительные сведения об использовании дерева Меркла в CCF см. в соответствующей документации по CCF.

  • proof: список пар "ключ-значение", представляющих хэши узлов дерева меркл, которые в сочетании с хэшом конечного узла, соответствующим данной транзакции, позволяют повторно вычислять корневой хэш дерева. Благодаря свойствам дерева Меркла можно повторно вычислить корневой хэш дерева только подмножество узлов. Элементы в этом списке представлены в виде пар "ключ-значение": ключи указывают относительное положение относительно родительского узла в дереве на определенном уровне; значения представляют собой хэш-хэш-код заданного узла в виде шестнадцатеричных строк.

  • serviceEndorsements: список строк сертификатов в кодировке PEM, представляющих предыдущие сертификаты удостоверений служб. Возможно, удостоверение службы, которое одобрило узел подписывания, не совпадает с удостоверением, выдавающим квитанцию. Например, сертификат службы обновляется после аварийного восстановления конфиденциального реестра. Список прошлых сертификатов служб позволяет аудиторам создавать цепочку доверия от узла подписывания CCF к текущему сертификату службы.

  • signature: строка Base64, представляющая сигнатуру корня дерева Меркла в данной транзакции с помощью узла CCF подписывания.

Поле leafComponents содержит следующие поля.

  • claimsDigest: шестнадцатеричная строка, представляющая хэш-хэш SHA-256 утверждения приложения , присоединенного приложением Конфиденциального реестра на момент выполнения транзакции. Утверждения приложения в настоящее время не поддерживаются, так как приложение Конфиденциального реестра не присоединяет утверждения при выполнении транзакции записи.

  • commitEvidence: уникальная строка, созданная для каждой транзакции, производная от идентификатора транзакции и секретов реестра. Дополнительные сведения о доказательствах фиксации см. в соответствующей документации по CCF.

  • writeSetDigest: шестнадцатеричная строка, представляющая хэш-хэш SHA-256 хранилища "ключ-значение", который содержит все ключи и значения, записанные на момент завершения транзакции. Дополнительные сведения о наборе для записи см. в соответствующей документации по CCF.

Утверждения приложения

Приложения Конфиденциального реестра Azure могут присоединять произвольные данные, называемые утверждениями приложений, для записи транзакций. Эти утверждения представляют действия, выполняемые во время операции записи. При присоединении к транзакции хэш SHA-256 объекта утверждений включается в реестр и фиксируется как часть транзакции записи. Включение утверждения в транзакцию записи гарантирует, что дайджест утверждения подписан на месте и не может быть изменен.

Позже утверждения приложения можно отобразить в обычном формате в полезных данных квитанции, соответствующих той же транзакции, в которой они были добавлены. Предоставленные утверждения позволяют пользователям повторно вычислять тот же дайджест утверждений, который был присоединен и подписан реестром во время транзакции. Дайджест утверждений можно использовать как часть процесса проверки получения транзакций записи, предоставляя пользователям автономный способ полной проверки подлинности записанных утверждений.

Утверждения приложений в настоящее время поддерживаются в предварительной версии 2023-01-18-previewAPI .

Запись содержимого квитанции о транзакциях с утверждениями приложения

Ниже приведен пример полезных данных ответа JSON, возвращаемых экземпляром Конфиденциального реестра Azure, который записывает утверждения приложения при вызове конечной 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 содержит следующие поля.

  • kind: представляет тип утверждения приложения. Значение указывает, как проанализировать объект утверждения приложения для предоставленного типа.

  • ledgerEntry: представляет утверждение приложения, полученное из данных записи реестра. Утверждение будет содержать данные, записанные приложением во время транзакции записи (например, идентификатор коллекции и содержимое, предоставленное пользователем), а также необходимые сведения для вычисления хэша, соответствующего одному объекту утверждения.

  • digest: представляет утверждение приложения в хиджест-форме. Этот объект утверждения будет содержать предварительно вычисляемый хэш приложениями и протокол, используемый для вычисления.

Поле ledgerEntry содержит следующие поля.

  • protocol: представляет протокол, используемый для вычисления дайджеста утверждения на основе заданных данных утверждения.

  • collectionId: идентификатор коллекции, записанной во время соответствующей транзакции записи.

  • contents: содержимое реестра, записанное во время соответствующей транзакции записи.

  • secretKey: секретный ключ в кодировке Base64. Этот ключ следует использовать в алгоритме HMAC со значениями, указанными в утверждении приложения, для получения дайджеста утверждения.

Поле digest содержит следующие поля.

  • protocol: представляет протокол, используемый для вычисления хэша данного утверждения.

  • value: дайджест утверждения приложения в шестнадцатеричной форме. Это значение должно быть хэшировано со значением , protocol чтобы вычислить полный дайджест утверждения приложения.

Дополнительные ресурсы

Дополнительные сведения о квитанциях о записях транзакций и о том, как CCF обеспечивает целостность каждой транзакции, см. по следующим ссылкам:

Дальнейшие действия