Azure Confidential Ledger skriver transaktionskvitton

För att framtvinga garantier för transaktionsintegritet använder en Azure Confidential Ledger en Merkle-träddatastruktur för att registrera hashen för alla transaktionsblock som läggs till i det oföränderliga transaktionsregistret. När en skrivtransaktion har checkats in kan Azure Confidential Ledger-användare få ett kryptografiskt Merkle-bevis, eller ett kvitto, över posten som skapas i ett konfidentiellt transaktionsregister för att kontrollera att skrivåtgärden har sparats korrekt. Ett kvitto på skrivtransaktioner är ett bevis på att systemet har checkat in motsvarande transaktion och kan användas för att verifiera att posten har lagts till i transaktionsregistret.

Mer information om hur ett Merkle-träd används i ett konfidentiellt transaktionsregister finns i CCF-dokumentationen.

Hämta skrivningstransaktionskvitton

Konfiguration och förutsättningar

Azure Confidential Ledger-användare kan få ett kvitto för en viss transaktion med hjälp av Azure Confidential Ledger-klientbiblioteket. I följande exempel visas hur du hämtar ett skrivkvitto med hjälp av klientbiblioteket för Python, men stegen är desamma med andra SDK som stöds för Azure Confidential Ledger.

Vi antar att en konfidentiell transaktionsregisterresurs redan har skapats med azure confidential ledger management-biblioteket. Om du inte har någon befintlig transaktionsregisterresurs än skapar du en med hjälp av följande instruktioner.

Steg-för-steg-beskrivning av kod

Vi börjar med att konfigurera importen för vårt Python-program.

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 

Följande är de konstanta värden som används för att konfigurera Azure Confidential Ledger-klienten. Se till att uppdatera konstanten ledger_name med det unika namnet på din konfidentiella transaktionsregisterresurs.

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

Vi autentiserar med klassen DefaultAzureCredential.

# Setup authentication 
credential = DefaultAzureCredential() 

Sedan hämtar och sparar vi tjänstcertifikatet Konfidentiellt transaktionsregister med certifikatklienten från URL:en för konfidentiell transaktionsregisteridentitet. Tjänstcertifikatet är ett offentligt nyckelcertifikat för nätverksidentitet som används som förtroenderot för TLS-serverautentisering . Med andra ord används den som certifikatutfärdare (CA) för att upprätta en TLS-anslutning med någon av noderna i CCF-nätverket.

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

Sedan kan vi använda våra autentiseringsuppgifter, det hämtade nätverkscertifikatet och vår unika transaktionsregister-URL för att skapa en konfidentiell transaktionsregisterklient.

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

Med hjälp av confidential ledger-klienten kan vi köra alla åtgärder som stöds på en Azure Confidential Ledger-instans. Vi kan till exempel lägga till en ny post i transaktionsregistret och vänta tills motsvarande skrivtransaktion har checkats in.

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

När transaktionen har checkats in kan vi använda klienten för att få ett kvitto över posten som läggs till i transaktionsregistret i föregående steg med respektive transaktions-ID.

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

Exempelkod

Den fullständiga exempelkoden som används i kodgenomgången tillhandahålls.

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

Skriva transaktionskvittoinnehåll

Här är ett exempel på en JSON-svarsnyttolast som returneras av en Azure Confidential Ledger-instans när slutpunkten GET_RECEIPT anropas.

{
    "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-svaret innehåller följande fält på rotnivå.

  • kvitto: Den innehåller de värden som kan användas för att verifiera giltigheten för kvittot för motsvarande skrivtransaktion.

  • state: Status för det returnerade JSON-svaret. Följande är de möjliga värden som tillåts:

    • Ready: Det kvitto som returneras i svaret är tillgängligt
    • Loading: Kvittot är ännu inte tillgängligt för att hämtas och begäran måste göras om
  • transactionId: Transaktions-ID:t som är associerat med kvitto för skrivtransaktionen.

Fältet receipt innehåller följande fält.

  • cert: Sträng med det offentliga PEM-nyckelcertifikatet för CCF-noden som signerade skrivtransaktionen. Tjänstidentitetscertifikatet bör alltid godkänna certifikatet för signeringsnoden. Se även mer information om hur transaktioner regelbundet signeras och hur signaturtransaktioner läggs till i transaktionsregistret i CCF på följande länk.

  • nodeId: Hexadecimal sträng som representerar SHA-256-hashsammandraget för den offentliga nyckeln för signering av CCF-noden.

  • leafComponents: Komponenterna i lövnodshashen i Merkle-trädet som är associerade med den angivna transaktionen. Ett Merkle-träd är en träddatastruktur som registrerar hashen för varje transaktion och garanterar transaktionsregistrets integritet. Mer information om hur ett Merkle-träd används i CCF finns i den relaterade CCF-dokumentationen.

  • proof: Lista över nyckel/värde-par som representerar Merkle Tree-nodernas hashvärden som, när de kombineras med lövnodshash som motsvarar den angivna transaktionen, tillåter omberäkning av trädets rothash. Tack vare egenskaperna för ett Merkle-träd går det att kompilera om rot-hashen för trädet endast en delmängd av noderna. Elementen i den här listan är i form av nyckel/värde-par: nycklar anger den relativa positionen med avseende på den överordnade noden i trädet på en viss nivå; värden är SHA-256-hashsammandrag för den angivna noden, som hexadecimala strängar.

  • serviceEndorsements: Lista över PEM-kodade certifikatsträngar som representerar tidigare certifikat för tjänstidentiteter. Det är möjligt att tjänstidentiteten som godkände signeringsnoden inte är samma som den som utfärdade kvittot. Tjänstcertifikatet förnyas till exempel efter en haveriberedskap för ett konfidentiellt transaktionsregister. Listan över tidigare tjänstcertifikat gör det möjligt för granskare att skapa förtroendekedjan från CCF-signeringsnoden till det aktuella tjänstcertifikatet.

  • signatur: Base64-sträng som representerar signaturen för roten för Merkle-trädet vid den angivna transaktionen, av signerings-CCF-noden.

Fältet leafComponents innehåller följande fält.

  • claimsDigest: Hexadecimal sträng som representerar SHA-256-hashsammandraget för programanspråket som kopplades av programmet Konfidentiellt transaktionsregister när transaktionen utfördes. Programanspråk stöds för närvarande inte eftersom programmet Konfidentiellt transaktionsregister inte bifogar något anspråk när en skrivtransaktion körs.

  • commitEvidence: En unik sträng som skapas per transaktion, härledd från transaktions-ID:t och transaktionsreskontrahemligheterna. Mer information om bevis för incheckning finns i den relaterade CCF-dokumentationen.

  • writeSetDigest: Hexadecimal sträng som representerar SHA-256-hashsammandraget i Key-Value-arkivet, som innehåller alla nycklar och värden som skrevs när transaktionen slutfördes. Mer information om skrivuppsättningen finns i den relaterade CCF-dokumentationen.

Programanspråk

Azure Confidential Ledger-program kan bifoga godtyckliga data, så kallade programanspråk, för att skriva transaktioner. Dessa anspråk representerar de åtgärder som utförs under en skrivåtgärd. När sha-256 kopplas till en transaktion inkluderas den sammanfattade SHA-256-sammanfattningen av anspråksobjektet i transaktionsregistret och checkas in som en del av skrivtransaktionen. Inkluderingen av anspråket i skrivtransaktionen garanterar att anspråkssammandraget är signerat och inte kan manipuleras.

Senare kan programanspråk visas i klarformat i kvittonyttolasten som motsvarar samma transaktion där de lades till. De exponerade anspråken gör det möjligt för användare att omkomponera samma anspråkssammandrag som kopplades och signerades på plats av transaktionsregistret under transaktionen. Anspråkssammandraget kan användas som en del av verifieringsprocessen för att skriva transaktionskvitton, vilket ger ett offline-sätt för användare att fullständigt verifiera äktheten av de registrerade anspråken.

Programanspråk stöds för närvarande i förhandsversionen av API 2023-01-18-preview:et .

Skriva transaktionskvittoinnehåll med programanspråk

Här är ett exempel på en JSON-svarsnyttolast som returneras av en Azure Confidential Ledger-instans som registrerade programanspråk när slutpunkten GET_RECEIPT anropades.

{
  "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"
}

Jämfört med det kvittoexempel som visades i föregående avsnitt innehåller JSON-svaret ett annat applicationClaims fält som representerar listan över programanspråk som registrerats av transaktionsregistret under skrivtransaktionen. Varje objekt i applicationClaims listan innehåller följande fält.

  • kind: Den representerar typen av programanspråk. Värdet anger hur du parsar programanspråksobjektet för den angivna typen.

  • ledgerEntry: Den representerar ett programanspråk som härleds från transaktionsregisterdata. Anspråket innehåller de data som registrerats av programmet under en skrivtransaktion (till exempel samlings-ID:t och innehållet som tillhandahålls av användaren) och den information som krävs för att beräkna sammanfattningen som motsvarar det enskilda anspråksobjektet.

  • sammandrag: Det representerar ett programanspråk i sammanfattat formulär. Det här anspråksobjektet skulle innehålla den förberäknade sammanfattningen av programmet och det protokoll som används för beräkningen.

Fältet ledgerEntry innehåller följande fält.

  • protocol: Det representerar det protokoll som ska användas för att beräkna sammandraget av ett anspråk från angivna anspråksdata.

  • collectionId: Identifieraren för samlingen som skrivits under motsvarande skrivtransaktion.

  • innehåll: Innehållet i transaktionsregistret som skrivits under motsvarande skrivtransaktion.

  • secretKey: En base64-kodad hemlig nyckel. Den här nyckeln ska användas i HMAC-algoritmen med de värden som anges i programanspråket för att hämta anspråkssammandraget.

Fältet digest innehåller följande fält.

  • protocol: Det representerar det protokoll som används för att beräkna sammandraget av det angivna anspråket.

  • värde: Sammanfattningen av programanspråket i hexadecimal form. Det här värdet måste hashas med protocol värdet för att beräkna den fullständiga sammanfattningen av programanspråket.

Fler resurser

Mer information om att skriva transaktionskvitton och hur CCF säkerställer integriteten för varje transaktion finns i följande länkar:

Nästa steg