Udostępnij za pośrednictwem


Poświadczenia transakcji zapisu poufnego rejestru platformy Azure

Aby wymusić gwarancje integralności transakcji, rejestr poufny platformy Azure używa struktury danych drzewa Merkle do rejestrowania skrótu wszystkich bloków transakcji, które są dołączane do niezmiennego rejestru. Po zatwierdzeniu transakcji zapisu użytkownicy rejestru poufnego platformy Azure mogą uzyskać kryptograficzny dowód Merkle lub potwierdzenie wpisu utworzonego w rejestrze poufnym, aby sprawdzić, czy operacja zapisu została poprawnie zapisana. Potwierdzenie transakcji zapisu jest dowodem na to, że system zadeklarował odpowiednią transakcję i może służyć do sprawdzania, czy wpis został skutecznie dołączony do rejestru.

Więcej informacji na temat sposobu użycia drzewa Merkle w rejestrze poufnym można znaleźć w dokumentacji CCF.

Pobieranie potwierdzeń transakcji zapisu

Konfigurowanie i wymagania wstępne

Użytkownicy rejestru poufnego platformy Azure mogą uzyskać potwierdzenie dla określonej transakcji przy użyciu biblioteki klienta Poufne rejestry platformy Azure. W poniższym przykładzie pokazano, jak uzyskać potwierdzenie zapisu przy użyciu biblioteki klienta dla języka Python, ale kroki są takie same jak w przypadku innych obsługiwanych zestawów SDK dla rejestru poufnego platformy Azure.

Zakładamy, że zasób Poufne rejestry został już utworzony przy użyciu biblioteki zarządzania poufnymi rejestrami platformy Azure. Jeśli nie masz jeszcze istniejącego zasobu rejestru, utwórz go, korzystając z poniższych instrukcji.

Przewodnik po kodzie

Rozpoczynamy od skonfigurowania importu dla naszego programu w języku 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 

Poniżej przedstawiono stałe wartości używane do konfigurowania klienta rejestru poufnego platformy Azure. Pamiętaj, aby zaktualizować stałą ledger_name o unikatową nazwę zasobu Poufne rejestry.

# 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" 

Uwierzytelniamy się przy użyciu klasy DefaultAzureCredential.

# Setup authentication 
credential = DefaultAzureCredential() 

Następnie uzyskujemy i zapisujemy certyfikat usługi Poufne rejestry przy użyciu klienta certyfikatu z adresu URL tożsamości rejestru poufnego. Certyfikat usługi jest certyfikatem klucza publicznego tożsamości sieciowej używanym jako główny certyfikat zaufania na potrzeby uwierzytelniania serwera TLS . Innymi słowy, jest używany jako urząd certyfikacji do ustanawiania połączenia TLS z dowolnymi węzłami w sieci 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"]) 

Następnie możemy użyć naszych poświadczeń, pobranego certyfikatu sieciowego i naszego unikatowego adresu URL rejestru, aby utworzyć klienta rejestru poufnego.

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

Korzystając z klienta Rejestru poufnego, możemy uruchomić wszystkie obsługiwane operacje w wystąpieniu rejestru poufnego platformy Azure. Na przykład możemy dołączyć nowy wpis do rejestru i poczekać, aż odpowiednia transakcja zapisu zostanie zatwierdzona.

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

Po zatwierdzeniu transakcji możemy użyć klienta, aby uzyskać potwierdzenie za pośrednictwem wpisu dołączonego do rejestru w poprzednim kroku przy użyciu odpowiedniego identyfikatora transakcji.

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

Przykładowy kod

Podano pełny przykładowy kod używany w przewodniku po kodzie.

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

Zapisywanie zawartości potwierdzenia transakcji

Oto przykład ładunku odpowiedzi JSON zwróconego przez wystąpienie poufnej księgi platformy Azure podczas wywoływania punktu końcowego 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"
}

Odpowiedź JSON zawiera następujące pola na poziomie głównym.

  • potwierdzenie: zawiera wartości, których można użyć do zweryfikowania ważności paragonu dla odpowiedniej transakcji zapisu.

  • state: stan zwróconej odpowiedzi JSON. Poniżej przedstawiono dozwolone wartości:

    • Ready: Potwierdzenie zwrócone w odpowiedzi jest dostępne
    • Loading: Potwierdzenie nie jest jeszcze dostępne do pobrania, a żądanie musi zostać ponowione
  • transactionId: identyfikator transakcji skojarzony z potwierdzeniem transakcji zapisu.

Pole receipt zawiera następujące pola.

  • cert: ciąg z certyfikatem klucza publicznego PEM węzła CCF, który podpisał transakcję zapisu. Certyfikat tożsamości usługi powinien zawsze wspierać certyfikat węzła podpisywania. Zobacz również więcej szczegółów na temat regularnego podpisywania transakcji i dołączania transakcji podpisów do rejestru w programie CCF pod poniższym linkiem.

  • nodeId: ciąg szesnastkowy reprezentujący skrót SHA-256 klucza publicznego węzła CCF podpisywania.

  • leafComponents: składniki skrótu węzła liścia w drzewie Merkle, które są skojarzone z określoną transakcją. Merkle Tree to struktura danych drzewa, która rejestruje skrót każdej transakcji i gwarantuje integralność rejestru. Aby uzyskać więcej informacji na temat sposobu użycia drzewa Merkle w programie CCF, zobacz powiązaną dokumentację CCF.

  • proof: Lista par klucz-wartość reprezentujących skróty węzłów Drzewa Merkle, które w połączeniu z skrótem węzła liścia odpowiadające danej transakcji umożliwiają ponowne obliczanie skrótu głównego drzewa. Dzięki właściwościom drzewa Merkle można ponownie skompilować skrót główny drzewa tylko podzestaw węzłów. Elementy na tej liście są w postaci par klucz-wartość: klucze wskazują względną pozycję względem węzła nadrzędnego w drzewie na określonym poziomie; wartości to skrót SHA-256 węzła podane jako ciągi szesnastkowe.

  • serviceEndorsements: lista ciągów certyfikatów zakodowanych za pomocą standardu PEM reprezentujących poprzednie certyfikaty tożsamości usługi. Istnieje możliwość, że tożsamość usługi, która zatwierdziła węzeł podpisywania, nie jest taka sama jak tożsamość, która wystawiła potwierdzenie. Na przykład certyfikat usługi jest odnawiany po odzyskiwaniu po awarii poufnego rejestru. Lista poprzednich certyfikatów usług umożliwia audytorom tworzenie łańcucha zaufania z węzła podpisywania CCF do bieżącego certyfikatu usługi.

  • signature: Ciąg Base64 reprezentujący podpis katalogu głównego drzewa Merkle w danej transakcji przez węzeł podpisywania CCF.

Pole leafComponents zawiera następujące pola.

  • claimsDigest: ciąg szesnastkowy reprezentujący skrót SHA-256 oświadczenia aplikacji dołączonego przez aplikację Poufne rejestry w momencie wykonania transakcji. Oświadczenia aplikacji są obecnie nieobsługiwane, ponieważ aplikacja Poufne rejestry nie dołącza żadnego oświadczenia podczas wykonywania transakcji zapisu.

  • commitEvidence: unikatowy ciąg wygenerowany na transakcję, pochodzący z identyfikatora transakcji i wpisów tajnych rejestru. Aby uzyskać więcej informacji na temat dowodów zatwierdzenia, zobacz powiązaną dokumentację CCF.

  • writeSetDigest: ciąg szesnastkowy reprezentujący skrót SHA-256 magazynu klucz-wartość, który zawiera wszystkie klucze i wartości zapisane w momencie zakończenia transakcji. Aby uzyskać więcej informacji na temat zestawu zapisu, zobacz powiązaną dokumentację CCF.

Oświadczenia aplikacji

Aplikacje rejestru poufnego platformy Azure mogą dołączać dowolne dane nazywane oświadczeniami aplikacji w celu zapisywania transakcji. Te oświadczenia reprezentują akcje wykonywane podczas operacji zapisu. Po dołączeniu do transakcji skrót SHA-256 obiektu oświadczeń jest uwzględniony w rejestrze i zatwierdzony w ramach transakcji zapisu. Dołączenie oświadczenia w transakcji zapisu gwarantuje, że skrót oświadczenia jest podpisany i nie można go manipulować.

Później oświadczenia aplikacji można ujawnić w formacie zwykłym w ładunku paragonu odpowiadającym tej samej transakcji, w której zostały dodane. Ujawnione oświadczenia umożliwiają użytkownikom ponowne obliczanie tego samego skrótu oświadczeń, który został dołączony i zalogowany przez rejestr podczas transakcji. Skrót oświadczeń może być używany w ramach procesu weryfikacji potwierdzenia transakcji zapisu, zapewniając użytkownikom możliwość pełnego zweryfikowania autentyczności zarejestrowanych oświadczeń.

Oświadczenia aplikacji są obecnie obsługiwane w wersji 2023-01-18-previewzapoznawczej interfejsu API .

Zapisywanie zawartości potwierdzenia transakcji przy użyciu oświadczeń aplikacji

Oto przykład ładunku odpowiedzi JSON zwróconego przez wystąpienie poufnej księgi platformy Azure, które zarejestrowało oświadczenia aplikacji podczas wywoływania punktu końcowego 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"
}

W porównaniu z przykładem paragonu pokazanym w poprzedniej sekcji odpowiedź JSON zawiera inne applicationClaims pole reprezentujące listę oświadczeń aplikacji zarejestrowanych przez rejestr podczas transakcji zapisu. Każdy obiekt na applicationClaims liście zawiera następujące pola.

  • kind: reprezentuje rodzaj oświadczenia aplikacji. Wartość wskazuje, jak przeanalizować obiekt oświadczenia aplikacji dla podanego typu.

  • ledgerEntry: reprezentuje oświadczenie aplikacji pochodzące z danych wpisu rejestru. Oświadczenie zawiera dane zarejestrowane przez aplikację podczas transakcji zapisu (na przykład identyfikator kolekcji i zawartość dostarczoną przez użytkownika) oraz wymagane informacje do obliczenia skrótu odpowiadającego pojedynczemu obiektowi oświadczenia.

  • skrót: reprezentuje oświadczenie aplikacji w postaci szyfrowanej. Ten obiekt oświadczenia będzie zawierać wstępnie skompilowany skrót przez aplikację i protokół używany do obliczeń.

Pole ledgerEntry zawiera następujące pola.

  • protocol: reprezentuje protokół używany do obliczania skrótu oświadczenia z danych oświadczeń.

  • collectionId: identyfikator kolekcji zapisanej podczas odpowiedniej transakcji zapisu.

  • zawartość: zawartość rejestru zapisana podczas odpowiedniej transakcji zapisu.

  • secretKey: klucz tajny zakodowany w formacie base64. Ten klucz jest używany w algorytmie HMAC z wartościami podanymi w oświadczeniu aplikacji w celu uzyskania skrótu oświadczenia.

Pole digest zawiera następujące pola.

  • protocol: reprezentuje protokół używany do obliczania skrótu danego oświadczenia.

  • value: skrót oświadczenia aplikacji w postaci szesnastkowej. Ta wartość musiałaby zostać skrócona przy protocol użyciu wartości w celu obliczenia pełnego skrótu oświadczenia aplikacji.

Więcej zasobów

Aby uzyskać więcej informacji na temat zapisu paragonów transakcji i sposobu, w jaki program CCF zapewnia integralność każdej transakcji, zobacz następujące linki:

Następne kroki