Skip to content

Commit 29b1393

Browse files
Merge pull request #222229 from andpiccione/apiccione/update-receipt-verification-docs
Update ACL receipt docs following receipt model fixes
2 parents 5e7c3aa + 301ba9e commit 29b1393

File tree

2 files changed

+37
-57
lines changed

2 files changed

+37
-57
lines changed

articles/confidential-ledger/verify-write-transaction-receipts.md

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ A write transaction receipt can be verified following a specific set of steps ou
2121

2222
### Leaf node computation
2323

24-
The first step is to compute the SHA-256 hash of the leaf node in the Merkle Tree corresponding to the committed transaction. A leaf node is composed of the ordered concatenation of the following fields that can be found in an Azure Confidential Ledger receipt, under `leaf_components`:
24+
The first step is to compute the SHA-256 hash of the leaf node in the Merkle Tree corresponding to the committed transaction. A leaf node is composed of the ordered concatenation of the following fields that can be found in an Azure Confidential Ledger receipt, under `leafComponents`:
2525

26-
1. `write_set_digest`
27-
2. SHA-256 digest of `commit_evidence`
28-
3. `claims_digest` fields
26+
1. `writeSetDigest`
27+
2. SHA-256 digest of `commitEvidence`
28+
3. `claimsDigest` fields
2929

30-
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.
30+
These values need to be concatenated as arrays of bytes: both `writeSetDigest` and `claimsDigest` would need to be converted from strings of hexadecimal digits to arrays of bytes; on the other hand, the hash of `commitEvidence` (as an array of bytes) can be obtained by applying the SHA-256 hash function over the UTF-8 encoded `commitEvidence` string.
3131

3232
Similarly, the leaf node hash digest can be computed by applying the SHA-256 hash function over the result concatenation of the resulting bytes.
3333

@@ -54,7 +54,7 @@ The third step is to verify that the cryptographic signature produced over the r
5454

5555
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.
5656

57-
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.
57+
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 `serviceEndorsements` list field in the receipt). The `serviceEndorsements` list is provided as an ordered list from the oldest to the latest service identity.
5858

5959
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.
6060

@@ -127,13 +127,11 @@ Inside the `verify_receipt` function, we check that the given receipt is valid a
127127
```python
128128
# Check that all the fields are present in the receipt
129129
assert "cert" in receipt
130-
assert "is_signature_transaction" in receipt
131-
assert "leaf_components" in receipt
132-
assert "claims_digest" in receipt["leaf_components"]
133-
assert "commit_evidence" in receipt["leaf_components"]
134-
assert "write_set_digest" in receipt["leaf_components"]
130+
assert "leafComponents" in receipt
131+
assert "claimsDigest" in receipt["leafComponents"]
132+
assert "commitEvidence" in receipt["leafComponents"]
133+
assert "writeSetDigest" in receipt["leafComponents"]
135134
assert "proof" in receipt
136-
assert "service_endorsements" in receipt
137135
assert "signature" in receipt
138136
```
139137

@@ -142,22 +140,14 @@ We initialize the variables that are going to be used in the rest of the program
142140
```python
143141
# Set the variables
144142
node_cert_pem = receipt["cert"]
145-
is_signature_transaction = receipt["is_signature_transaction"]
146-
claims_digest_hex = receipt["leaf_components"]["claims_digest"]
147-
commit_evidence_str = receipt["leaf_components"]["commit_evidence"]
148-
write_set_digest_hex = receipt["leaf_components"]["write_set_digest"]
143+
claims_digest_hex = receipt["leafComponents"]["claimsDigest"]
144+
commit_evidence_str = receipt["leafComponents"]["commitEvidence"]
145+
write_set_digest_hex = receipt["leafComponents"]["writeSetDigest"]
149146
proof_list = receipt["proof"]
150-
service_endorsements_certs_pem = receipt["service_endorsements"]
147+
service_endorsements_certs_pem = receipt.get("serviceEndorsements", [])
151148
root_node_signature = receipt["signature"]
152149
```
153150

154-
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.
155-
156-
```python
157-
# Check that this receipt is not for a signature transaction
158-
assert not is_signature_transaction
159-
```
160-
161151
We can load the PEM certificates for the service identity, the signing node, and the endorsements certificates from previous service identities using the cryptography library.
162152

163153
```python
@@ -181,9 +171,9 @@ leaf_node_hex = compute_leaf_node(
181171
)
182172
```
183173

184-
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.
174+
The `compute_leaf_node` function accepts as parameters the leaf components of the receipt (the `claimsDigest`, the `commitEvidence`, and the `writeSetDigest`) and returns the leaf node hash in hexadecimal form.
185175

186-
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.
176+
As detailed above, we compute the digest of `commitEvidence` (using the SHA256 `hashlib` function). Then, we convert both `writeSetDigest` and `claimsDigest` into arrays of bytes. Finally, we concatenate the three arrays, and we digest the result using the SHA256 function.
187177

188178
```python
189179
def compute_leaf_node(
@@ -272,7 +262,7 @@ The last step of receipt verification is validating the certificate that was use
272262
check_endorsements(node_cert, service_cert, service_endorsements_certs)
273263
```
274264

275-
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.
265+
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 `serviceEndorsements` isn't an empty list.
276266

277267
```python
278268
def check_endorsement(endorsee: Certificate, endorser: Certificate):
@@ -395,29 +385,23 @@ def verify_receipt(receipt: Dict[str, Any], service_cert_pem: str) -> None:
395385

396386
    # Check that all the fields are present in the receipt
397387
    assert "cert" in receipt
398-
    assert "is_signature_transaction" in receipt
399-
    assert "leaf_components" in receipt
400-
    assert "claims_digest" in receipt["leaf_components"]
401-
    assert "commit_evidence" in receipt["leaf_components"]
402-
    assert "write_set_digest" in receipt["leaf_components"]
388+
    assert "leafComponents" in receipt
389+
    assert "claimsDigest" in receipt["leafComponents"]
390+
    assert "commitEvidence" in receipt["leafComponents"]
391+
    assert "writeSetDigest" in receipt["leafComponents"]
403392
    assert "proof" in receipt
404-
    assert "service_endorsements" in receipt
405393
    assert "signature" in receipt
406394

407395
    # Set the variables
408396
    node_cert_pem = receipt["cert"]
409-
    is_signature_transaction = receipt["is_signature_transaction"]
410-
    claims_digest_hex = receipt["leaf_components"]["claims_digest"]
411-
    commit_evidence_str = receipt["leaf_components"]["commit_evidence"]
397+
    claims_digest_hex = receipt["leafComponents"]["claimsDigest"]
398+
    commit_evidence_str = receipt["leafComponents"]["commitEvidence"]
412399

413-
    write_set_digest_hex = receipt["leaf_components"]["write_set_digest"]
400+
    write_set_digest_hex = receipt["leafComponents"]["writeSetDigest"]
414401
    proof_list = receipt["proof"]
415-
    service_endorsements_certs_pem = receipt["service_endorsements"]
402+
service_endorsements_certs_pem = receipt.get("serviceEndorsements", [])
416403
    root_node_signature = receipt["signature"]
417404

418-
    # Check that this receipt is not for a signature transaction
419-
    assert not is_signature_transaction
420-
421405
    # Load service and node PEM certificates
422406
    service_cert = load_pem_x509_certificate(service_cert_pem.encode())
423407
    node_cert = load_pem_x509_certificate(node_cert_pem.encode())

articles/confidential-ledger/write-transaction-receipts.md

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,12 @@ Here's an example of a JSON response payload returned by an Azure Confidential L
175175
{
176176
"receipt": {
177177
"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",
178-
"is_signature_transaction": false,
179-
"leaf_components": {
180-
"claims_digest": "0000000000000000000000000000000000000000000000000000000000000000",
181-
"commit_evidence": "ce:2.40:f36ffe2930ec95d50ebaaec26e2bec56835abd051019eb270f538ab0744712a4",
182-
"write_set_digest": "8452624d10bdd79c408c0f062a1917aa96711ea062c508c745469636ae1460be"
178+
"leafComponents": {
179+
"claimsDigest": "0000000000000000000000000000000000000000000000000000000000000000",
180+
"commitEvidence": "ce:2.40:f36ffe2930ec95d50ebaaec26e2bec56835abd051019eb270f538ab0744712a4",
181+
"writeSetDigest": "8452624d10bdd79c408c0f062a1917aa96711ea062c508c745469636ae1460be"
183182
},
184-
"node_id": "70e995887e3e6b73c80bc44f9fbb6e66b9f644acaddbc9c0483cfc17d77af24f",
183+
"nodeId": "70e995887e3e6b73c80bc44f9fbb6e66b9f644acaddbc9c0483cfc17d77af24f",
185184
"proof": [
186185
{
187186
"left": "b78230f9abb27b9b803a9cae4e4cec647a3be1000fc2241038867792d59d4bc1"
@@ -190,7 +189,6 @@ Here's an example of a JSON response payload returned by an Azure Confidential L
190189
"left": "a2835d4505b8b6b25a0c06a9c8e96a5204533ceac1edf2b3e0e4dece78fbaf35"
191190
}
192191
],
193-
"service_endorsements": [],
194192
"signature": "MEUCIQCjtMqk7wOtUTgqlHlCfWRqAco+38roVdUcRv7a1G6pBwIgWKpCSdBmhzgEdwguUW/Cj/Z5bAOA8YHSoLe8KzrlqK8="
195193
},
196194
"state": "Ready",
@@ -213,25 +211,23 @@ The `receipt` field contains the following fields.
213211

214212
* **cert**: String with the [PEM](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail) public key certificate of the CCF node that signed the write transaction. The certificate of the signing node should always be endorsed by the service identity certificate. See also more details about how transactions get regularly signed and how the signature transactions are appended to the ledger in CCF at the following [link](https://microsoft.github.io/CCF/main/architecture/merkle_tree.html).
215213

216-
* **is_signature_transaction**: Boolean value indicating whether the receipt is related to a signature transaction or not. Receipts for signature transactions can't be retrieved for Confidential Ledgers.
214+
* **nodeId**: Hexadecimal string representing the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) hash digest of the public key of the signing CCF node.
217215

218-
* **node_id**: Hexadecimal string representing the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) hash digest of the public key of the signing CCF node.
219-
220-
* **leaf_components**: The components of the leaf node hash in the [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree) that are associated to the specified transaction. A Merkle Tree is a tree data structure that records the hash of every transaction and guarantees the integrity of the ledger. For more information on how a Merkle Tree is used in CCF, see the related [CCF documentation](https://microsoft.github.io/CCF/main/architecture/merkle_tree.html).
216+
* **leafComponents**: The components of the leaf node hash in the [Merkle Tree](https://en.wikipedia.org/wiki/Merkle_tree) that are associated to the specified transaction. A Merkle Tree is a tree data structure that records the hash of every transaction and guarantees the integrity of the ledger. For more information on how a Merkle Tree is used in CCF, see the related [CCF documentation](https://microsoft.github.io/CCF/main/architecture/merkle_tree.html).
221217

222218
* **proof**: List of key-value pairs representing the Merkle Tree nodes hashes that, when combined with the leaf node hash corresponding to the given transaction, allow the recomputation of the root hash of the tree. Thanks to the properties of a Merkle Tree, it's possible to recompute the root hash of the tree only a subset of nodes. The elements in this list are in the form of key-value pairs: keys indicate the relative position with respect to the parent node in the tree at a certain level; values are the SHA-256 hash digests of the node given, as hexadecimal strings.
223219

224-
* **service_endorsements**: List of PEM-encoded certificates strings representing previous service identities certificates. It's possible that the service identity that endorsed the signing node isn't the same as the one that issued the receipt. For example, the service certificate is renewed after a disaster recovery of a Confidential Ledger. The list of past service certificates allows auditors to build the chain of trust from the CCF signing node to the current service certificate.
220+
* **serviceEndorsements**: List of PEM-encoded certificates strings representing previous service identities certificates. It's possible that the service identity that endorsed the signing node isn't the same as the one that issued the receipt. For example, the service certificate is renewed after a disaster recovery of a Confidential Ledger. The list of past service certificates allows auditors to build the chain of trust from the CCF signing node to the current service certificate.
225221

226222
* **signature**: Base64 string representing the signature of the root of the Merkle Tree at the given transaction, by the signing CCF node.
227223

228-
The `leaf_components` field contains the following fields.
224+
The `leafComponents` field contains the following fields.
229225

230-
* **claims_digest**: Hexadecimal string representing the SHA-256 hash digest of the [application claim](https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#application-claims) attached by the Confidential Ledger application at the time the transaction was executed. Application claims are currently unsupported as the Confidential Ledger application doesn't attach any claim when executing a write transaction.
226+
* **claimsDigest**: Hexadecimal string representing the SHA-256 hash digest of the [application claim](https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#application-claims) attached by the Confidential Ledger application at the time the transaction was executed. Application claims are currently unsupported as the Confidential Ledger application doesn't attach any claim when executing a write transaction.
231227

232-
* **commit_evidence**: A unique string produced per transaction, derived from the transaction ID and the ledger secrets. For more information about the commit evidence, see the related [CCF documentation](https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#commit-evidence).
228+
* **commitEvidence**: A unique string produced per transaction, derived from the transaction ID and the ledger secrets. For more information about the commit evidence, see the related [CCF documentation](https://microsoft.github.io/CCF/main/use_apps/verify_tx.html#commit-evidence).
233229

234-
* **write_set_digest**: Hexadecimal string representing the SHA-256 hash digest of the [Key-Value store](https://microsoft.github.io/CCF/main/build_apps/kv/index.html), which contains all the keys and values written at the time the transaction was completed. For more information about the write set, see the related [CCF documentation](https://microsoft.github.io/CCF/main/overview/glossary.html#term-Write-Set).
230+
* **writeSetDigest**: Hexadecimal string representing the SHA-256 hash digest of the [Key-Value store](https://microsoft.github.io/CCF/main/build_apps/kv/index.html), which contains all the keys and values written at the time the transaction was completed. For more information about the write set, see the related [CCF documentation](https://microsoft.github.io/CCF/main/overview/glossary.html#term-Write-Set).
235231

236232
### More resources
237233

0 commit comments

Comments
 (0)