Difference between revisions of "HTTP asset certification"

From Internet Computer Wiki
Jump to: navigation, search
(Removed content and replaced it with links where the information resides today.)
Tags: Replaced Visual edit
(59 intermediate revisions by 4 users not shown)
Line 1: Line 1:
HTTP asset certification is a protocol that allows canisters to certify bodies of responses to GET HTTP requests.
+
This content has moved to the learn hub ([https://learn.internetcomputer.org/hc/en-us/articles/34276431179412-Asset-Certification Asset Certification] and [https://learn.internetcomputer.org/hc/en-us/articles/34211943471892-HTTP-Gateway-Protocol HTTP Gateway Protocol]) and the [https://internetcomputer.org/docs/references/http-gateway-protocol-spec HTTP Gateway Protocol Specification].
The receiver of such responses can use the IC public key to authenticate the body of the response.
 
The protocol relies on [https://smartcontracts.org/docs/interface-spec/index.html#system-api-certified-data Certified data] feature of the IC.
 
 
 
== Canister protocol ==
 
 
 
A canister must follow the following protocol to certify assets:
 
 
 
<ul>
 
<li>
 
Construct a [https://smartcontracts.org/docs/interface-spec/index.html#_certificate hash tree] that maps paths of HTTP resources to SHA-256 hashes of their bodies.
 
An example of such a tree:
 
<pre>
 
*root*
 
└── http_assets
 
    ├── index.html -> SHA256(body)
 
    ├── ...
 
    └── /css/styles.css -> SHA256(body)
 
</pre>
 
</li>
 
<li>
 
Compute the root hash of the tree and call [https://smartcontracts.org/docs/interface-spec/index.html#system-api-imports <code>ic0.certified_data_set</code>] with the bytes of the hash as the argument.
 
</li>
 
<li>
 
Add a [[#IC-Certificate header]] to each certified HTTP response.
 
</li>
 
</ul>
 
 
 
== Validator protocol ==
 
 
 
The validator follows the following steps to validate the certificate of resource at path <code>PATH</code> served by canister <code>CANISTER_ID</code>:
 
 
 
* Hash the body of the HTTP response, obtaining hash <code>DATA_HASH</code>.
 
* Check that the response contains the <code>IC-Certificate</code> header.
 
* Decode the <code>certificate</code> and the <code>tree</code> from the value of the <code>IC-Certificate</code> header.
 
* Check the validity of the certificate as described in the [https://smartcontracts.org/docs/interface-spec/index.html#certification Interface Specification: Certification]. This step requires knowing the IC root key.
 
* Check that <code>lookup(/http_assets/PATH, tree) = Found(DATA_HASH)</code>
 
* Check that <code>lookup(/canister/CANISTER_ID/certified_data, certificate.tree) = Found(reconstruct(tree))</code>.
 
 
 
== IC-Certificate header ==
 
 
 
The <code>IC-Certificate</code> header is a Structure Header (as per [https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-header-structure RFC proposal]) with is a dictionary with with members <code>certificate</code> and <code>tree</code>, both of which are Byte Sequences:
 
 
 
<pre>
 
IC-Certficate: certificate=:<base64(c)>:, tree=:<base64(t)>:
 
</pre>
 
 
 
where
 
 
 
* <code>c</code> is the a CBOR-encoded certificate (see [https://smartcontracts.org/docs/interface-spec/index.html#certification-encoding Interface Specification: Encoding of certificates]).
 
* <code>t</code> is a Hash Tree, CBOR-encoded according the CDDL <code>#6.55799(hash-tree)</code> where <code>hash-tree</code> is the corresponding [https://smartcontracts.org/docs/interface-spec/index.html#api-cddl CDDL production in the Interface Specification].
 
 
 
The <code>certificate</code> must be a valid [https://smartcontracts.org/docs/interface-spec/index.html#_certificate Internet Specification: Certificate] with
 
 
 
<pre>
 
lookup(/canister/<canister_id>/certified_data, certificate.tree)
 
    = Found (reconstruct(tree))
 
</pre>
 
 
 
The <code>tree</code> exposes the relevant nodes in the <code>/http_assets</code> subtree to allow the client to lookup the request path to get the expected body hash.
 
 
 
=== Example ===
 
 
 
For this example, we fetched <code>/index.html</code> resource of the Internet Identity canister (canister id <code>rdmx6-jaaaa-aaaaa-aaadq-cai</code>) available at https://rdmx6-jaaaa-aaaaa-aaadq-cai.raw.ic0.app/index.html.
 
The SHA-256 hash of the resource at the moment of fetching is <code>478afb8206ca0b566a7f138e623accd169fa822602d2f6d717fb67d1045f4f0d</code>.
 
The response contained the following header:
 
 
 
<pre>
 
IC-Certificate: certificate=:2dn3omR0cmVlgwGDAYMBgwJIY2FuaXN0ZXKDAYMBggRYIIudikoDwH1gRK637olblUhMUX3HlE0Dihj8MTACxGzHgwGCBFggyCRYc8M/ugt8G7C8RPYayn+l4sdBj8gvFotzJELnQ32DAYIEWCA1/+UHZ9SF67w4ssjOi+Jv3ch7WQNzezGmhtuvB+RDpYMCSgAAAAAAAAAHAQGDAYMBgwJOY2VydGlmaWVkX2RhdGGCA1ggWUt10wjWinx0aAWyrNEi/0R7VeuhalDMjGDErzIbZzqCBFgg/VtZRZdYyK/sr3KF2jWeS1rblF+4ajwfDv2ZbCGpaTiCBFggSoI5JS0pCusHP4nh6h780ebr961E0lVnFkFwzF5pZaeCBFggcKidPEGiPoFMPYfEyNGsDRYWmry1iGX0HNUEoKhIATeCBFggR0zdKUZOMcm5EHNl5Tee3XWqbq1gArwUGzZ2FH4rWtmCBFggTkwJcNrh0eJ9FutJcn6th9eCbM2KXnloxed0acxmQNeDAYIEWCA6SNH8IT1JMHEDEE99csK1kw7bqHh7kGMfNDs6popfCoMCRHRpbWWCA0nFnbXrts/65xZpc2lnbmF0dXJlWDCkXN2tcvH5b+xFCzfkuJMqrZDcplfW8vDziJwzx08WOPI4rh2TIGYZ3R6dgQTF0CA=:, tree=:2dn3gwGDAktodHRwX2Fzc2V0c4MBggRYIDgtAGcz5VvevwiEwwZB9zpkt17C9LE6o/O37bEwQUawgwGDAksvaW5kZXguaHRtbIIDWCBHivuCBsoLVmp/E45iOszRafqCJgLS9tcX+2fRBF9PDYIEWCCx2L8SfJwOydBkUxjc8tKXDVUeoiw8qEYI+8b+HRWIWYIEWCAqZ+3yoFSA9s+jbLFbtcVz+wi0HF9x51Kx38qPcBhiDA==:
 
</pre>
 
 
 
We can extract the following data from the header value:
 
 
 
<pre>
 
ROOT HASH: 0b2d843df534ac8ed2331fe2782deb71d23a08d9b4019a8fa695ec7fde93de36
 
TREE HASH: 594b75d308d68a7c746805b2acd122ff447b55eba16a50cc8c60c4af321b673a
 
SIGNATURE: a45cddad72f1f96fec450b37e4b8932aad90dca657d6f2f0f3889c33c74f1638f238ae1d93206619dd1e9d8104c5d020
 
CERTIFICATE TIME: 2022-02-02T08:23:24.851277509+00:00
 
CERTIFICATE TREE:
 
HashTree {
 
    root: Fork(
 
        Fork(
 
            Fork(
 
                Label("canister", Fork(
 
                    Fork(
 
                        Pruned(8b9d8a4a03c07d6044aeb7ee895b95484c517dc7944d038a18fc313002c46cc7),
 
                        Fork(
 
                            Pruned(c8245873c33fba0b7c1bb0bc44f61aca7fa5e2c7418fc82f168b732442e7437d),
 
                            Fork(
 
                                Pruned(35ffe50767d485ebbc38b2c8ce8be26fddc87b5903737b31a686dbaf07e443a5),
 
                                Label(0x00000000000000070101, Fork(
 
                                    Fork(
 
                                        Label("certified_data", Leaf(0x594b75d308d68a7c746805b2acd122ff447b55eba16a50cc8c60c4af321b673a)),
 
                                        Pruned(fd5b59459758c8afecaf7285da359e4b5adb945fb86a3c1f0efd996c21a96938),
 
                                    ),
 
                                    Pruned(4a8239252d290aeb073f89e1ea1efcd1e6ebf7ad44d25567164170cc5e6965a7),
 
                                )),
 
                            ),
 
                        ),
 
                    ),
 
                    Pruned(70a89d3c41a23e814c3d87c4c8d1ac0d16169abcb58865f41cd504a0a8480137),
 
                )),
 
                Pruned(474cdd29464e31c9b9107365e5379edd75aa6ead6002bc141b3676147e2b5ad9),
 
            ),
 
            Pruned(4e4c0970dae1d1e27d16eb49727ead87d7826ccd8a5e7968c5e77469cc6640d7),
 
        ),
 
        Fork(
 
            Pruned(3a48d1fc213d49307103104f7d72c2b5930edba8787b90631f343b3aa68a5f0a),
 
            Label("time", Leaf(0xc59db5ebb6cffae716)),
 
        ),
 
    ),
 
}
 
TREE:
 
HashTree {
 
    root: Fork(
 
        Label("http_assets", Fork(
 
            Pruned(382d006733e55bdebf0884c30641f73a64b75ec2f4b13aa3f3b7edb1304146b0),
 
            Fork(
 
                Label("/index.html", Leaf(0x478afb8206ca0b566a7f138e623accd169fa822602d2f6d717fb67d1045f4f0d)),
 
                Pruned(b1d8bf127c9c0ec9d0645318dcf2d2970d551ea22c3ca84608fbc6fe1d158859),
 
            ),
 
        )),
 
        Pruned(2a67edf2a05480f6cfa36cb15bb5c573fb08b41c5f71e752b1dfca8f7018620c),
 
    ),
 
}
 
</pre>
 
 
 
== Limitations ==
 
 
 
* The protocol supports only one resource per path. This does not work well with content negotiation protocol.
 
* The protocol does not support certification of HTTP statuses and headers. Only resource bodies can be certified.
 
 
 
== Canisters using HTTP asset certification ==
 
 
 
* [https://github.com/dfinity/internet-identity/blob/7ff3dd51dd98c7b1b43d83950c9f31ea7159103d/src/internet_identity/src/main.rs#L775 Internet Identity canister]
 
* [https://github.com/dfinity/nns-dapp/blob/49126394df77b9583e508277fc736eda51de47be/rs/src/assets.rs#L123 NNS frontend]
 
* [https://githug.com/dfinity/certified-assets Certified assets canister]
 
 
 
== Validators ==
 
 
 
* [https://github.com/dfinity/ic/tree/master/typescript/service-worker Certifying Service Worker]
 
* [https://github.com/dfinity/icx-proxy/blob/b0de0437fe6806a96d942465e5ee284c23b812e8/src/main.rs#L470 ICX proxy]
 

Revision as of 17:59, 23 June 2025

This content has moved to the learn hub (Asset Certification and HTTP Gateway Protocol) and the HTTP Gateway Protocol Specification.