Ontvangstbevestigingen voor schrijfbewerkingen van Azure Confidential Ledger
Voor het afdwingen van garanties voor transactieintegriteit maakt een Azure Confidential Ledger gebruik van een Merkle-structuurgegevensstructuur om de hash vast te leggen van alle transactieblokken die worden toegevoegd aan het onveranderbare grootboek. Nadat een schrijftransactie is doorgevoerd, kunnen Azure Confidential Ledger-gebruikers een cryptografisch Merkle-bewijs of ontvangstbewijs krijgen via de vermelding die is geproduceerd in een vertrouwelijk grootboek om te controleren of de schrijfbewerking correct is opgeslagen. Een ontvangstbewijs voor schrijftransacties is bewijs dat het systeem de bijbehorende transactie heeft doorgevoerd en kan worden gebruikt om te controleren of de vermelding effectief is toegevoegd aan het grootboek.
Meer informatie over hoe een Merkle Tree wordt gebruikt in een vertrouwelijk grootboek vindt u in de CCF-documentatie.
Ontvangstbevestigingen voor schrijftransacties ophalen
Installatie en vereisten
Azure Confidential Ledger-gebruikers kunnen een ontvangstbewijs voor een specifieke transactie krijgen met behulp van de Azure Confidential Ledger-clientbibliotheek. In het volgende voorbeeld ziet u hoe u een schrijfbevestiging krijgt met behulp van de clientbibliotheek voor Python, maar de stappen zijn hetzelfde met een andere ondersteunde SDK voor Azure Confidential Ledger.
We gaan ervan uit dat er al een Confidential Ledger-resource is gemaakt met behulp van de Azure Confidential Ledger Management-bibliotheek. Als u nog geen bestaande grootboekresource hebt, maakt u er een met behulp van de volgende instructies.
Kennismaking met code
We beginnen met het instellen van de importbewerkingen voor ons Python-programma.
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
Hier volgen de constante waarden die worden gebruikt voor het instellen van de Azure Confidential Ledger-client. Zorg ervoor dat u de ledger_name
constante bijwerkt met de unieke naam van uw Vertrouwelijke grootboekresource.
# 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"
We verifiëren met behulp van de klasse DefaultAzureCredential.
# Setup authentication
credential = DefaultAzureCredential()
Vervolgens krijgen en opslaan we het certificaat voor de vertrouwelijke grootboekservice met behulp van de certificaatclient van de URL van de vertrouwelijke grootboekidentiteit. Het servicecertificaat is een openbaar sleutelcertificaat voor de netwerkidentiteit dat wordt gebruikt als basis voor TLS-serververificatie . Met andere woorden, deze wordt gebruikt als certificeringsinstantie (CA) voor het tot stand brengen van een TLS-verbinding met een van de knooppunten in het CCF-netwerk.
# 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"])
Vervolgens kunnen we onze referenties, het opgehaalde netwerkcertificaat en onze unieke grootboek-URL gebruiken om een vertrouwelijke grootboekclient te maken.
# Create Confidential Ledger client
ledger_client = ConfidentialLedgerClient(
endpoint=ledger_url,
credential=credential,
ledger_certificate_path=ledger_tls_cert_file_name
)
Met behulp van de Confidential Ledger-client kunnen we alle ondersteunde bewerkingen uitvoeren op een Azure Confidential Ledger-exemplaar. We kunnen bijvoorbeeld een nieuwe vermelding toevoegen aan het grootboek en wachten tot de bijbehorende schrijftransactie is doorgevoerd.
# 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()
Nadat de transactie is doorgevoerd, kunnen we de client gebruiken om een ontvangstbewijs te krijgen over de vermelding die in de vorige stap aan het grootboek is toegevoegd met behulp van de betreffende transactie-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()
Voorbeeldcode
De volledige voorbeeldcode die in het code-overzicht wordt gebruikt, wordt verstrekt.
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))
Inhoud van transactiebevestiging schrijven
Hier volgt een voorbeeld van een nettolading van een JSON-antwoord die wordt geretourneerd door een Azure Confidential Ledger-exemplaar bij het aanroepen van het GET_RECEIPT
eindpunt.
{
"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"
}
Het JSON-antwoord bevat de volgende velden op hoofdniveau.
ontvangstbewijs: het bevat de waarden die kunnen worden gebruikt om de geldigheid van de ontvangst van de bijbehorende schrijftransactie te controleren.
status: de status van het geretourneerde JSON-antwoord. Hier volgen de mogelijke waarden die zijn toegestaan:
Ready
: Het ontvangstbewijs dat in het antwoord wordt geretourneerd, is beschikbaarLoading
: Het ontvangstbewijs is nog niet beschikbaar om te worden opgehaald en de aanvraag moet opnieuw worden geprobeerd
transactionId: de transactie-id die is gekoppeld aan de ontvangstbevestiging van de schrijftransactie.
Het receipt
veld bevat de volgende velden.
certificaat: Tekenreeks met het openbare PEM-sleutelcertificaat van het CCF-knooppunt dat de schrijftransactie heeft ondertekend. Het certificaat voor service-id's moet altijd het certificaat van het ondertekeningsknooppunt goedkeuren. Zie ook meer informatie over hoe transacties regelmatig worden ondertekend en hoe de handtekeningtransacties worden toegevoegd aan het grootboek in CCF via de volgende koppeling.
nodeId: Hexadecimale tekenreeks die de SHA-256-hashsamenvatting van de openbare sleutel van het ondertekenings-CCF-knooppunt vertegenwoordigt.
leafComponents: De onderdelen van de leaf-knooppunt-hash in de Merkle-structuur die zijn gekoppeld aan de opgegeven transactie. Een Merkle Tree is een boomgegevensstructuur die de hash van elke transactie registreert en de integriteit van het grootboek garandeert. Zie de bijbehorende CCF-documentatie voor meer informatie over hoe een Merkle Tree wordt gebruikt in CCF.
proof: Lijst met sleutel-waardeparen die de Merkle Tree-knooppunthashes vertegenwoordigen die, in combinatie met de leaf-knooppunt-hash die overeenkomt met de opgegeven transactie, de hercomputatie van de hoofd-hash van de structuur toestaan. Dankzij de eigenschappen van een Merkle-boom is het mogelijk om de hoofd-hash van de structuur slechts een subset van knooppunten opnieuw te compileren. De elementen in deze lijst hebben de vorm van sleutel-waardeparen: sleutels geven de relatieve positie aan met betrekking tot het bovenliggende knooppunt in de structuur op een bepaald niveau; waarden zijn de SHA-256-hash-digests van het opgegeven knooppunt, zoals hexadecimale tekenreeksen.
serviceEndorsements: Lijst met door PEM gecodeerde certificatentekenreeksen die eerdere certificaten voor service-identiteiten vertegenwoordigen. Het is mogelijk dat de service-id die het ondertekeningsknooppunt heeft goedgekeurd, niet hetzelfde is als het knooppunt dat het ontvangstbewijs heeft uitgegeven. Het servicecertificaat wordt bijvoorbeeld vernieuwd na een noodherstel van een vertrouwelijk grootboek. Met de lijst met eerdere servicecertificaten kunnen auditors de vertrouwensketen bouwen van het CCF-ondertekeningsknooppunt naar het huidige servicecertificaat.
handtekening: Base64-tekenreeks die de handtekening vertegenwoordigt van de hoofdmap van de Merkle Tree bij de opgegeven transactie, door het ondertekening CCF-knooppunt.
Het leafComponents
veld bevat de volgende velden.
claimsDigest: Hexadecimale tekenreeks die de SHA-256-hashsamenvatting van de toepassingsclaim vertegenwoordigt die is gekoppeld door de toepassing Confidential Ledger op het moment dat de transactie werd uitgevoerd. Toepassingsclaims worden momenteel niet ondersteund omdat de toepassing Confidential Ledger geen claim koppelt bij het uitvoeren van een schrijftransactie.
commitEvidence: Een unieke tekenreeks die per transactie wordt geproduceerd, afgeleid van de transactie-id en de grootboekgeheimen. Zie de bijbehorende CCF-documentatie voor meer informatie over het doorvoerbewijs.
writeSetDigest: Hexadecimale tekenreeks die de SHA-256-hashsamenvatting van het sleutel-waardearchief vertegenwoordigt, dat alle sleutels en waarden bevat die zijn geschreven op het moment dat de transactie is voltooid. Zie de gerelateerde CCF-documentatie voor meer informatie over de schrijfset.
Toepassingsclaims
Azure Confidential Ledger-toepassingen kunnen willekeurige gegevens, toepassingsclaims genoemd, koppelen om transacties te schrijven. Deze claims vertegenwoordigen de acties die worden uitgevoerd tijdens een schrijfbewerking. Wanneer het is gekoppeld aan een transactie, wordt de SHA-256-samenvatting van het claimobject opgenomen in het grootboek en vastgelegd als onderdeel van de schrijftransactie. De opname van de claim in de schrijftransactie garandeert dat de claimsamenvatt is aangemeld en niet kan worden gemanipuleerd.
Later kunnen toepassingsclaims worden weergegeven in hun gewone indeling in de nettolading van het ontvangstbewijs die overeenkomt met dezelfde transactie waar ze zijn toegevoegd. Met de weergegeven claims kunnen gebruikers dezelfde claimssamenvating die is gekoppeld en aangemeld door het grootboek tijdens de transactie opnieuw compileren. De claimssamenvatbaarheid kan worden gebruikt als onderdeel van het verificatieproces voor het ontvangen van schrijftransacties, zodat gebruikers de echtheid van de geregistreerde claims volledig kunnen verifiëren.
Toepassingsclaims worden momenteel ondersteund in de preview-API-versie 2023-01-18-preview
.
Inhoud van transactiebevestiging schrijven met toepassingsclaims
Hier volgt een voorbeeld van een nettolading van een JSON-antwoord die wordt geretourneerd door een Azure Confidential Ledger-exemplaar dat toepassingsclaims heeft geregistreerd bij het aanroepen van het GET_RECEIPT
eindpunt.
{
"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"
}
Vergeleken met het ontvangstbewijsvoorbeeld dat in de vorige sectie wordt weergegeven, bevat het JSON-antwoord een ander applicationClaims
veld dat de lijst met toepassingsclaims vertegenwoordigt die zijn vastgelegd door het grootboek tijdens de schrijftransactie. Elk object in de applicationClaims
lijst bevat de volgende velden.
soort: Het vertegenwoordigt het soort toepassingsclaim. De waarde geeft aan hoe het toepassingsclaimobject voor het opgegeven type moet worden geparseerd.
grootboekEntry: Het vertegenwoordigt een toepassingsclaim die is afgeleid van gegevens van grootboekinvoer. De claim bevat de gegevens die door de toepassing zijn vastgelegd tijdens een schrijftransactie (bijvoorbeeld de verzamelings-id en de inhoud van de gebruiker) en de vereiste informatie voor het berekenen van de samenvatting die overeenkomt met het object met één claim.
digest: Het vertegenwoordigt een toepassingsclaim in een verteerd formulier. Dit claimobject bevat de vooraf berekende digest door de toepassing en het protocol dat wordt gebruikt voor de berekening.
Het ledgerEntry
veld bevat de volgende velden.
protocol: het protocol dat moet worden gebruikt voor het berekenen van de samenvatting van een claim van de opgegeven claimgegevens.
collectionId: de id van de verzameling die is geschreven tijdens de bijbehorende schrijftransactie.
inhoud: De inhoud van het grootboek dat is geschreven tijdens de bijbehorende schrijftransactie.
secretKey: een met base64 gecodeerde geheime sleutel. Deze sleutel moet worden gebruikt in het HMAC-algoritme met de waarden in de toepassingsclaim om de claimsamenvating te verkrijgen.
Het digest
veld bevat de volgende velden.
protocol: Het vertegenwoordigt het protocol dat wordt gebruikt om de samenvatting van de opgegeven claim te berekenen.
waarde: De samenvatting van de toepassingsclaim, in hexadecimale vorm. Deze waarde moet worden gehasht met de
protocol
waarde om de volledige samenvatting van de toepassingsclaim te berekenen.
Meer resources
Zie de volgende koppelingen voor meer informatie over het ontvangen van schrijftransacties en hoe CCF de integriteit van elke transactie garandeert:
- Ontvangstbewijzen schrijven
- Ontvangsten
- CCF-woordenlijst
- Merkle Tree
- Cryptografie
- Getuigschriften
- Toepassingsclaims
- Door de gebruiker gedefinieerde claims in ontvangstbevestigingen