You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: articles/confidential-ledger/verify-write-transaction-receipts.md
+25-21Lines changed: 25 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,11 +13,13 @@ ms.topic: how-to
13
13
14
14
## Context
15
15
16
-
For more details about Azure Confidential Ledger write transaction receipts, please refer to the detailed documentation on the topic that can be found at the [following page](write-transaction-receipts.md).
16
+
An Azure Confidential Ledger write transaction receipt represents a cryptographic Merkle proof that the corresponding write transaction has been globally committed by the CCF network. Azure Confidential Ledger users can get a receipt over a committed write transaction at any point in time to verify that the corresponding write operation was successfully recorded into the immutable ledger.
17
+
18
+
For more information about Azure Confidential Ledger write transaction receipts, see the [dedicated article](write-transaction-receipts.md).
17
19
18
20
## Receipt verification steps
19
21
20
-
An Azure Confidential Ledger write transaction receipt represents a cryptographic Merkle proof that the corresponding write transaction has been globally committed into the immutable ledger. A receipt can be verified following a specific set of steps outlined in the following sub-sections.
22
+
A write transaction receipt can be verified following a specific set of steps outlined in the following subsections. The same steps are outlined in the [CCF Documentation](https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#receipt-verification).
21
23
22
24
### Leaf node computation
23
25
@@ -27,13 +29,13 @@ The first step is to compute the SHA-256 hash of the leaf node in the Merkle Tre
27
29
2. SHA-256 digest of `commit_evidence`
28
30
3.`claims_digest` fields
29
31
30
-
Please keep in mind that the these values needs to be concatenated as arrays of bytes. This means that `write_set_digest` and `claims_digest` would need to be converted from strings of hexadecimal digits to arrays of bytes; on the other hand, the hash of `commit_evidence` can be obtained by applying the SHA-256 hash function over the UTF-8 encoded `commit_evidence` string.
32
+
These values need to be concatenated as arrays of bytes: both `write_set_digest` and `claims_digest` would need to be converted from strings of hexadecimal digits to arrays of bytes; on the other hand, the hash of `commit_evidence` (as an array of bytes) can be obtained by applying the SHA-256 hash function over the UTF-8 encoded `commit_evidence` string.
31
33
32
34
Similarly, the leaf node hash digest can be computed by applying the SHA-256 hash function over the result concatenation of the resulting bytes.
33
35
34
36
### Root node computation
35
37
36
-
The second step is to compute the SHA-256 hash of the root of the Merkle Tree at the time the transaction was committed. This can be accomplished by iteratively concatenating and hashing the result of the previous iteration (starting from the leaf node hash computed in the previous step) with the ordered nodes' hashes provided in the `proof` field of a receipt. Please note that the`proof` list is provided as an ordered list and its elements need to be iterated in the given order.
38
+
The second step is to compute the SHA-256 hash of the root of the Merkle Tree at the time the transaction was committed. The computation is done by iteratively concatenating and hashing the result of the previous iteration (starting from the leaf node hash computed in the previous step) with the ordered nodes' hashes provided in the `proof` field of a receipt. The`proof` list is provided as an ordered list and its elements need to be iterated in the given order.
37
39
38
40
The concatenation needs to be done on the bytes representation with respect to the relative order indicated in the objects provided in the `proof` field (either `left` or `right`).
39
41
@@ -48,20 +50,21 @@ The third step is to verify that the cryptographic signature produced over the r
48
50
49
51
1. Decode the base64 string `signature` into an array of bytes.
50
52
2. Extract the ECDSA public key from the signing node certificate `cert`.
51
-
3. Verify that the signature over the root of the Merkle Tree (computed using the instructions in the previous sub-section) is authentic using the extracted public key from the previous step. This step effectively corresponds to a standard [digital signature](https://wikipedia.org/wiki/Digital_signature) verification process using ECDSA. There are many libraries in the most popular programming languages that allow verifying an ECDSA signature using a public key certificate over some data and that can be leveraged for this step (e.g., [ecdsa](https://pypi.org/project/ecdsa/) for Python).
53
+
3. Verify that the signature over the root of the Merkle Tree (computed using the instructions in the previous subsection) is authentic using the extracted public key from the previous step. This step effectively corresponds to a standard [digital signature](https://wikipedia.org/wiki/Digital_signature) verification process using ECDSA. There are many libraries in the most popular programming languages that allow verifying an ECDSA signature using a public key certificate over some data (for example, [ecdsa](https://pypi.org/project/ecdsa/) for Python).
52
54
53
55
### Verify signing node certificate endorsement
54
56
55
-
In addition to the above, it is also required to verify that the signing node certificate is endorsed (i.e., signed) by the current ledger certificate. Please note that this step does not depend on the other three previous steps and can be carried out independenly from the others.
57
+
In addition to the above, it's also required to verify that the signing node certificate is endorsed (that is, signed) by the current ledger certificate. This step doesn't depend on the other three previous steps and can be carried out independently from the others.
56
58
57
-
As the ledger certificate may have been renewed since the transaction was committed, it is possible that the current service identity that issued the receipt is different from the one that endorsed the signing node. If this applies, it is required to verify the chain of certificates trust from the signing node certificate (i.e., the `cert` field in the receipt) up to the trusted root Certificate Authority (CA) (i.e., the current service identity certificate) through other previous service identities (i.e., the `service_endorsements` list field in the receipt). Please note that the`service_endorsements` list is provided as an ordered list from the oldest to the latest service identity.
59
+
It's possible that the current service identity that issued the receipt is different from the one that endorsed the signing node (for example, due to a certificate renewal). In this case, it's required to verify the chain of certificates trust from the signing node certificate (that is, the `cert` field in the receipt) up to the trusted root Certificate Authority (CA) (that is, the current service identity certificate) through other previous service identities (that is, the `service_endorsements` list field in the receipt). The`service_endorsements` list is provided as an ordered list from the oldest to the latest service identity.
58
60
59
-
Certificate endorsement need to be verified for the entire chain and follows the exact same digital signature verification process outlined in the previous sub-section. There are popular open-source cryptographic libraries (e.g., [OpenSSL](https://www.openssl.org/)) that can be typically used to carry out a certificate endorsement step.
61
+
Certificate endorsement need to be verified for the entire chain and follows the exact same digital signature verification process outlined in the previous subsection. There are popular open-source cryptographic libraries (for example, [OpenSSL](https://www.openssl.org/)) that can be typically used to carry out a certificate endorsement step.
60
62
61
-
### Additional resources
63
+
### More resources
62
64
63
-
Please refer to the [CCF documentation about receipt verification](https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#receipt-verification) for more details about how the algorithm works. The following links could also be useful to better understand some topics related to receipt verification:
65
+
For more information about the content of an Azure Confidential Ledger write transaction receipt and explanation of each field, see the [dedicated article](write-transaction-receipts.md#write-transaction-receipt-content). The [CCF documentation](https://microsoft.github.io/CCF) also contains more information about receipt verification and other related resources at the following links:
@@ -73,13 +76,13 @@ Please refer to the [CCF documentation about receipt verification](https://micro
73
76
74
77
For reference purposes, we provide sample code in Python to fully verify Azure Confidential Ledger write transaction receipts following the steps outlined above.
75
78
76
-
For the verification algorithm, we are going to need the current service network certificate and a write transaction receipt from a running Confidential Ledger resource. Please refer to the [following page](write-transaction-receipts.md#fetching-a-write-transaction-receipt) for details on how to fetch a write transaction receipt and how to retrieve the service certificate.
79
+
To run the full verification algorithm, the current service network certificate and a write transaction receipt from a running Confidential Ledger resource are required. Refer to [this article](write-transaction-receipts.md#fetching-a-write-transaction-receipt) for details on how to fetch a write transaction receipt and the service certificate from a Confidential Ledger instance.
77
80
78
81
### Code walkthrough
79
82
80
-
We are going to use a separate utility (`verify_receipt`) to run the receipt verification algorithm and we provide as input of the algorithm the content of the `receipt` field of a `GET_RECEIPT` response as a dictionary and the service certitificate as a simple string. The function throws an exceptions if the receipt is not valid or if any error was encountered.
83
+
The following code can be used to initialize the required objects and run the receipt verification algorithm. A separate utility (`verify_receipt`) is used to run the full verification algorithm, and accepts input the content of the `receipt` field in a `GET_RECEIPT` response as a dictionary and the service certificate as a simple string. The function throws an exception if the receipt isn't valid or if any error was encountered during the processing.
81
84
82
-
We assume that both the receipt and the service certificate can be loaded from files.
85
+
It's assumed that both the receipt and the service certificate can be loaded from files. Make sure to update both the `service_certificate_file_name` and `receipt_file_name` constants with the respective files names of the service certificate and receipt you would like to verify.
83
86
84
87
```python
85
88
import json
@@ -108,10 +111,10 @@ with open(service_certificate_file_name, "r") as service_certificate_file, open(
108
111
raise e
109
112
```
110
113
111
-
As the verification process requires some cryptographic and hashing algorithms, we are going to need the following modules as helper utilities:
114
+
As the verification process requires some cryptographic and hashing primitives, the following libraries are used to facilitate the computation.
112
115
113
116
* The [CCF Python library](https://microsoft.github.io/CCF/main/audit/python_library.html): the module provides a set of tools for receipt verification.
114
-
* The [Python cryptography library](https://cryptography.io/en/latest/): a widely used library that includes a variety of cryptographic algorithms and primitives.
117
+
* The [Python cryptography library](https://cryptography.io/en/latest/): a widely used library that includes various cryptographic algorithms and primitives.
115
118
* The [hashlib module](https://docs.python.org/3/library/hashlib.html), part of the Python standard library: a module that provides a common interface for popular hashing algorithms.
116
119
117
120
```python
@@ -136,7 +139,7 @@ assert "service_endorsements" in receipt
136
139
assert"signature"in receipt
137
140
```
138
141
139
-
We initialize the variables we are going to use for the rest of the program.
142
+
We initialize the variables that are going to be used in the rest of the program.
We check that the receipt is not related to a signature transaction. Receipts for signature transactions are not allowed for Confidential Ledger.
156
+
In the following snipper, we check that the receipt isn't related to a signature transaction. Receipts for signature transactions aren't allowed for Confidential Ledger.
154
157
155
158
```python
156
159
# Check that this receipt is not for a signature transaction
The `compute_leaf_node` function accepts as parameters the leaf components of the receipt (the `claims_digest`, the `commit_evidence`, and the `write_set_digest`) and returns the leaf node hash in hexadecimal form.
184
187
185
-
As detailed above, we compute the digest of `commit_evidence` (using the SHA256 hashlib function). Then, we convert both `write_set_digest` and `claims_digest` into arrays of bytes. Finally, we concatenate the three arrays, and we digest the result using the SHA256 hashlib function.
188
+
As detailed above, we compute the digest of `commit_evidence` (using the SHA256 `hashlib` function). Then, we convert both `write_set_digest` and `claims_digest` into arrays of bytes. Finally, we concatenate the three arrays, and we digest the result using the SHA256 function.
186
189
187
190
```python
188
191
defcompute_leaf_node(
@@ -220,7 +223,7 @@ After computing the leaf, we can compute the root of the Merkle tree.
220
223
root_node = root(leaf_node_hex, proof_list)
221
224
```
222
225
223
-
We leverage the function `root` provided as part of the CCF Python library. The function successively concatenates the result of the previous iteration with a new element from `proof`, digests the concatenation, and then repeats the step for every element in `proof` with the previously computed digest. The concatenation needs to respect the order of the nodes in the Merkle Tree to make sure the root is re-computed correctly.
226
+
We use the function `root` provided as part of the CCF Python library. The function successively concatenates the result of the previous iteration with a new element from `proof`, digests the concatenation, and then repeats the step for every element in `proof` with the previously computed digest. The concatenation needs to respect the order of the nodes in the Merkle Tree to make sure the root is recomputed correctly.
224
227
225
228
```python
226
229
defroot(leaf: str, proof: List[dict]):
@@ -271,7 +274,7 @@ The last step of receipt verification is validating the certificate that was use
Likewise, we can use the CCF utility `check_endorsements` to validate that the certificate of the signing node is endorsed by the service identity. The certificate chain could be composed of previous service certificates, so we should validate that the endorsement is applied transitively if `service_endorsements`is not an empty list.
277
+
Likewise, we can use the CCF utility `check_endorsements` to validate that the certificate of the signing node is endorsed by the service identity. The certificate chain could be composed of previous service certificates, so we should validate that the endorsement is applied transitively if `service_endorsements`isn't an empty list.
0 commit comments