From 385b3e096afce6923a340017799cd69f33730c88 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 23 Apr 2025 16:16:30 +0200 Subject: [PATCH 1/3] REAMDE: update --- README.md | 422 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 245 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 6f4fdcf..47ecfb0 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,11 @@ Merkle Tree Certificates for TLS Implementation of [Merkle Tree Certificates for TLS]( https://davidben.github.io/merkle-tree-certs/draft-davidben-tls-merkle-tree-certs.html) - -At the moment only the Certification Authority (CA) side is implemented, -and we differ from `-03` and `master` branch, by including -some [unmerged PRs](https://github.com/davidben/merkle-tree-certs/pulls). + in Go. This contains a Certification Authority (CA), mirror, and + code to verify certificates. +This does not contain integration with TLS (yet) or the ACME bits. +At the moment we differ from `-04` and `main` branch of the specification, + by including some [unmerged PRs](https://github.com/davidben/merkle-tree-certs/pulls). Demo ---- @@ -20,9 +21,11 @@ and [David's TLS working group presentation at IETF116]( Merkle Tree Certificates is an **optimisation** to the WebPKI (including [Certificate Transparency](https://certificate.transparency.dev)) -motivated by the large sizes of typical post-quantum signatures and public keys, -to reduce the number of keys and signatures -required for the common case where +motivated by the [large sizes]( + https://dadrian.io/blog/posts/pqc-signatures-2024/) of +[typical post-quantum signatures and public keys]( + https://blog.cloudflare.com/another-look-at-pq-signatures/), +to reduce the number of keys and signatures required for the common case where 1. Certificate issuance does not have to be immediate. For instance, because a certificate can be requested ahead of time for an existing domain @@ -31,11 +34,13 @@ required for the common case where 2. The relying party (eg. browser) has a trusted update mechanism. There are also several ways to use MTC without trusted update mechanism, - with various trade-offs: see the *Transparency Services* section - of the spec. + with various trade-offs: see the [Relying Party Policy]( + https://davidben.github.io/merkle-tree-certs/draft-davidben-tls-merkle-tree-certs.html#name-relying-party-policy) + section of the specification. -MTC does not aim to replace the full WebPKI, but is a first meaningful step -for improvement. +If we're not in this case (which is estimated to be +[less than 0.1%](https://www.youtube.com/watch?v=f8unMB2Qjho) of the time), +then we fall back to regular X.509 certificates. ### Intermezzo: `mtc` commandline tool @@ -57,8 +62,9 @@ The first part (TLS and the public key) is the *subject*, and the latter (domain and IP) are the *claim*. Roughly, an assertion is like a certificate without the signature. -To create an assertion, you can use the `mtc new-assertion` command. -First, let's quickly create a P-256 public key to play with. +You can create a request for an assertion to be signed with the +`mtc new-assertion-request` command. First, let's quickly create +a P-256 public key to play with. ``` $ openssl ecparam -name prime256v1 -genkey -out p256.priv @@ -67,39 +73,47 @@ $ openssl ec -in p256.priv -pubout -out p256.pub Now we create an assertion that this P-256 public key should be valid for `example.com` and `198.51.100.60`, and write it to -the `my-assertion`. +the `my-asr`. ``` -$ mtc new-assertion --tls-pem p256.pub --dns example.com --ip4 198.51.100.60 -o my-assertion -checksum: 14bc907eafd02d5be8b8cc319d87ad5afe9266a6910a18cbdcbfcee1b7af696a +$ mtc new-assertion-request --tls-pem p256.pub --dns example.com --ip4 198.51.100.60 -o my-asr ``` Let's check it using `mtc inspect`: ``` -$ mtc inspect assertion my-assertion +$ ./mtc inspect assertion-request my-asr +checksum 2024bdbffe399acca37d299a03c047aa33ef596ae471c17698a0566d00951bd9 +not_after unset subject_type TLS signature_scheme p256 -public_key_hash a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41ef +public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a dns [example.com] ip4 [198.51.100.60] +evidence-list (0 entries) ``` +An assertion request can contain two bits of extra information besides +the assertion itself. First is a `not_after` field to request to limit +the validity of the assertion when published. +The second is optional "evidence" that's published alongside the +assertions. In the future this could be used for serialized DNSSEC proofs. + ### Batches, merkle trees and signed validity windows -An MTC CA doesn't give you a certificate for an assertion immediately. Instead, -assertions are queued and issued in **batches** with a fixed rhythm, -for instance a batch is issused once every hour. -All assertions in a single batch are valid for the same period of time, -the **validity window**, which is, for instance, two weeks. +An MTC CA doesn't give you a certificate for an assertion request immediately. +Instead, assertions are queued and issued in **batches** with a fixed rhythm, +for instance a batch is issued once every hour. +All assertions in a single batch by default are valid for the same period of +time, the **validity window**, which is, for instance, two weeks. The CA publishes these batches publicly over HTTP. For each batch, the CA computes a [Merkle tree]( https://en.wikipedia.org/wiki/Merkle_tree). -This condenses all the assertions in that batch into a single **root** hash. -For every batch, the CA signs that root together with all the roots +This condenses all the assertions in that batch into a single **tree head** hash. +For every batch, the CA signs that tree head together with all the tree heads of the currently valid batches. This signature, together with those - signed roots is called the **signed validity window** for that batch, + signed tree heads is called the **signed validity window** for that batch, which is published alongside the assertions. ### Creating a CA @@ -110,9 +124,12 @@ Let's create an MTC CA. $ mtc ca new --batch-duration 5m --lifetime 1h 62253.12.15 ca.example.com/path ``` -This creates a new MTC CA called `my-mtc-ca`, and puts the data in the -current working directory. A batch is issued every 5 minutes, and -each batch is valid for one hour. +This creates a new MTC CA in the current working directory. It's configured +to issue a batch every 5 minutes, and for each batch to be valid for an hour. +It is identified by the [trust anchor identifier]( + https://datatracker.ietf.org/doc/draft-ietf-tls-trust-anchor-ids/) 62253.12.15. +You can get your own by requesting a [private enterprise number here]( + https://www.iana.org/assignments/enterprise-numbers/). Let's have a look at the files created: @@ -122,9 +139,9 @@ $ find . ./signing.key ./www ./www/mtc -./www/mtc/v1 -./www/mtc/v1/ca-params -./www/mtc/v1/batches +./www/mtc/v04b +./www/mtc/v04b/ca-params +./www/mtc/v04b/batches ./queue ./tmp ``` @@ -136,154 +153,187 @@ at `https://ca.example.com/path`. At the moment, the only file of interest is `ca-params`, which contains the information about the CA: ``` -$ mtc inspect ca-params www/mtc/v1/ca-params +$ mtc inspect ca-params www/mtc/v04b/ca-params issuer 62253.12.15 -start_time 1705677477 2024-01-19 16:17:57 +0100 CET +start_time 1745415825 2025-04-23 13:43:45 +0000 UTC batch_duration 300 5m0s life_time 3600 1h0m0s storage_window_size 24 2h0m0s validity_window_size 12 server_prefix ca.example.com/path -public_key fingerprint ml-dsa-87:85b5a617ef109e0a8d68a094c8b969f622ac4096c513fa0acd169c231ce2fad5 +public_key fingerprint ml-dsa-87:52f3488ca58a51a3d8d4b5d054828e5ebcc3767a0732da374f608f766cf8bad2 ``` The `batches` folder is empty, because there are no batches issued yet. -The `queue` file contains the assertions that will be issued. +The `queue` file contains the assertion requests that will be fulfilled +during the next issuance. ### Issuing our first batch -Let's issue our first assertion. We can read the assertion from disk we've -created earlier with `mtc new-assertion`: +Let's issue our first assertion. We can read the assertion request from disk we've +created earlier with `mtc new-assertion-request`: ``` -$ mtc ca queue -i my-assertion +$ mtc ca queue -i my-asr $ mtc ca show-queue -checksum 14bc907eafd02d5be8b8cc319d87ad5afe9266a6910a18cbdcbfcee1b7af696a +checksum 3241885a438bd82f21d193fe7be9e87a24f5b6aac899bd780b1604da0ec39f48 +not_after 2025-04-23 14:48:44 +0000 UTC subject_type TLS signature_scheme p256 -public_key_hash a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41ef +public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a dns [example.com] ip4 [198.51.100.60] +evidence-list (0 entries) -Total number of assertions in queue: 1 +Total number of assertion requests in queue: 1 ``` -(We can pass the checksum from `new-assertion` with `--checksum` to make sure -the assertion wasn't corrupted.) +(We can pass the checksum from `new-assertion-request` with `--checksum` +to make sure the assertion wasn't corrupted.) -We can also queue an assertion ad hoc: +We can also queue an assertion request ad hoc: ``` $ mtc ca queue --tls-pem p256.pub -d other.example.com -d second.example.com -$ mtc ca show-queue | tail -n 8 - -checksum fbdea936ae7795a3fa01d44230daba351d7480eceadd086ba32938ebc88a5458 +$ mtc ca show-queue | tail -n 10 +checksum 3241885a438bd82f21d193fe7be9e87a24f5b6aac899bd780b1604da0ec39f48 +not_after 2025-04-23 14:48:44 +0000 UTC subject_type TLS signature_scheme p256 -public_key_hash a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41ef -dns [other.example.com second.example.com] +public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a +dns [example.com] +ip4 [198.51.100.60] +evidence-list (0 entries) -Total number of assertions in queue: 2 +Total number of assertion requests in queue: 2 ``` Let's issue our first batch. ``` $ mtc ca issue -2024/01/19 16:27:31 INFO Starting issuance time=2024-01-19T16:27:31.841+01:00 -2024/01/19 16:27:31 INFO Current state expectedStored=0 expectedActive=0 existingBatches=⌀ -2024/01/19 16:27:31 INFO To issue batches=0 +2025/04/23 15:50:58 INFO Starting issuance time=2025-04-23T13:50:58.023Z +2025/04/23 15:50:58 INFO Current state expectedStored=0,1 expectedActive=0,1 existingBatches=⌀ +2025/04/23 15:50:58 INFO To issue batches=0,1 ``` And let's check: ``` $ find . +``` . ./signing.key ./www ./www/mtc -./www/mtc/v1 -./www/mtc/v1/ca-params -./www/mtc/v1/batches -./www/mtc/v1/batches/0 -./www/mtc/v1/batches/0/tree -./www/mtc/v1/batches/0/abridged-assertions -./www/mtc/v1/batches/0/signed-validity-window -./www/mtc/v1/batches/0/index -./www/mtc/v1/batches/latest +./www/mtc/v04b +./www/mtc/v04b/ca-params +./www/mtc/v04b/batches +./www/mtc/v04b/batches/0 +./www/mtc/v04b/batches/0/validity-window +./www/mtc/v04b/batches/0/tree +./www/mtc/v04b/batches/0/entries +./www/mtc/v04b/batches/0/evidence +./www/mtc/v04b/batches/0/index +./www/mtc/v04b/batches/latest +./www/mtc/v04b/batches/1 +./www/mtc/v04b/batches/1/validity-window +./www/mtc/v04b/batches/1/tree +./www/mtc/v04b/batches/1/entries +./www/mtc/v04b/batches/1/evidence +./www/mtc/v04b/batches/1/index ./queue ./tmp ``` -We see a `0` batch has been created. `latest` is a symlink to `0`. +We see an `0` and `1` batch have been created. `latest` is a symlink to `1`. -The `abridged-assertions` is essentially the list of assertions: -the difference between a regular and abridged assertion, -is that with an abridged assertion, the public key has been replaced +Because we waited more than 5 minutes between creating the CA, +and starting issuance, both batches `0` and `1` were ready to be issued. +The assertions have been issued in batch `1` and batch `0` is empty. + +Now, let's have a look at each batch. The `entries` file is essentially +the list of assertions: the difference between a regular assertion +and an entry is that with an entry, the public key has been replaced by the hash of the public key. ``` -$ mtc inspect abridged-assertions www/mtc/v1/batches/0/abridged-assertions -key 28b2216e7905ab48d5444f5b7ebf3d2386bc0444c9721fff77b0b313e734dab4 +$ mtc inspect entries www/mtc/v04b/batches/0/entries +Total number of entries: 0 +$ mtc inspect entries www/mtc/v04b/batches/1/entries +key 0b65c8a5f69e88fd1eb58dff4d317f6173bd31773e14d99ace88a2aa7062fdd9 +not_after 2025-04-23 14:48:44 +0000 UTC subject_type TLS signature_scheme p256 -public_key_hash a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41ef -dns [example.com] -ip4 [198.51.100.60] +public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a +dns [other.example.com second.example.com] -key 80944a1728bc7b4cd7e583c6b24a5f413ba50b7ef5ba9d214e26c1a1974f0a19 +key 78b5ccc905b693659bf6581011f8efb17fd7aedf9ca70a196a22923f560feeca +not_after 2025-04-23 14:48:44 +0000 UTC subject_type TLS signature_scheme p256 -public_key_hash a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41ef -dns [other.example.com second.example.com] +public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a +dns [example.com] +ip4 [198.51.100.60] -Total number of abridged assertions: 2 +Total number of entries: 2 ``` -The `signed-validity-window` is the signed validity window: the roots of +The `validity-window` is the signed validity window: the tree heads of the currently valid batches: ``` -$ mtc inspect -ca-params www/mtc/v1/ca-params signed-validity-window www/mtc/v1/batches/0/signed-validity-window +$ mtc inspect -ca-params www/mtc/v04b/ca-params validity-window www/mtc/v04b/batches/1/validity-window signature ✅ -batch_number 0 -tree_heads[-11] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-10] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-9] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-8] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-7] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-6] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-5] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-4] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-3] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-2] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-1] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[0] c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3 +batch_number 1 +tree_heads[1] 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e +tree_heads[0] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-1] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-2] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-3] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-4] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-5] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-6] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-7] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-8] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-9] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-10] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf ``` We need to pass the `ca-params` file to be able to parse the file, and -check the signature therein. (As this is the first batch, the previous batches -contain a placeholder value.) +check the signature therein. (As not all previous batches exist, they use +the placeholder value for an empty tree.) The `tree` file contains the Merkle tree. ``` -$ mtc inspect tree www/mtc/v1/batches/0/tree +$ mtc inspect tree www/mtc/v04b/batches/1/tree number of leaves 2 number of nodes 3 -root c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3 +tree head 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e ``` -Finally, the `index` file allows a quick lookup in `abridged-assertions` +The `evidence` file contains the optional evidence that can be provided +with the assertion request. We did not pass any, so they're empty: + +``` +$ mtc inspect evidence www/mtc/v04b/batches/1/evidence +evidence-list (0 entries) + +evidence-list (0 entries) + +Total number of evidence lists: 2 +``` + +Finally, the `index` file allows a quick lookup in `entries` (and `evidence`) by key (hash of the assertion): ``` -$ mtc inspect index www/mtc/v1/batches/0/index +$ mtc inspect index www/mtc/v04b/batches/1/index key seqno offset -28b2216e7905ab48d5444f5b7ebf3d2386bc0444c9721fff77b0b313e734dab4 0 0 -80944a1728bc7b4cd7e583c6b24a5f413ba50b7ef5ba9d214e26c1a1974f0a19 1 69 +0b65c8a5f69e88fd1eb58dff4d317f6173bd31773e14d99ace88a2aa7062fdd9 0 0 0 +78b5ccc905b693659bf6581011f8efb17fd7aedf9ca70a196a22923f560feeca 1 91 3 total number of entries: 2 ``` @@ -300,135 +350,153 @@ $ mtc ca queue --tls-pem p256.pub -d 1.example.com $ mtc ca queue --tls-pem p256.pub -d 2.example.com $ mtc ca queue --tls-pem p256.pub -d 3.example.com $ mtc ca issue -2024/01/19 16:33:57 INFO Starting issuance time=2024-01-19T16:33:57.860+01:00 -2024/01/19 16:33:57 INFO Current state expectedStored=0,…,2 expectedActive=0,…,2 existingBatches=0 -2024/01/19 16:33:57 INFO To issue batches=1,2 +2025/04/23 16:03:35 INFO Starting issuance time=2025-04-23T14:03:35.653Z +2025/04/23 16:03:35 INFO Current state expectedStored=0,…,3 expectedActive=0,…,3 existingBatches=0,1 +2025/04/23 16:03:35 INFO To issue batches=2,3 $ find . +``` . ./signing.key ./www ./www/mtc -./www/mtc/v1 -./www/mtc/v1/ca-params -./www/mtc/v1/batches -./www/mtc/v1/batches/0 -./www/mtc/v1/batches/0/tree -./www/mtc/v1/batches/0/abridged-assertions -./www/mtc/v1/batches/0/signed-validity-window -./www/mtc/v1/batches/0/index -./www/mtc/v1/batches/latest -./www/mtc/v1/batches/1 -./www/mtc/v1/batches/1/tree -./www/mtc/v1/batches/1/abridged-assertions -./www/mtc/v1/batches/1/signed-validity-window -./www/mtc/v1/batches/1/index -./www/mtc/v1/batches/2 -./www/mtc/v1/batches/2/tree -./www/mtc/v1/batches/2/abridged-assertions -./www/mtc/v1/batches/2/signed-validity-window -./www/mtc/v1/batches/2/index +./www/mtc/v04b +./www/mtc/v04b/ca-params +./www/mtc/v04b/batches +./www/mtc/v04b/batches/0 +./www/mtc/v04b/batches/0/validity-window +./www/mtc/v04b/batches/0/tree +./www/mtc/v04b/batches/0/entries +./www/mtc/v04b/batches/0/evidence +./www/mtc/v04b/batches/0/index +./www/mtc/v04b/batches/latest +./www/mtc/v04b/batches/1 +./www/mtc/v04b/batches/1/validity-window +./www/mtc/v04b/batches/1/tree +./www/mtc/v04b/batches/1/entries +./www/mtc/v04b/batches/1/evidence +./www/mtc/v04b/batches/1/index +./www/mtc/v04b/batches/3 +./www/mtc/v04b/batches/3/validity-window +./www/mtc/v04b/batches/3/tree +./www/mtc/v04b/batches/3/entries +./www/mtc/v04b/batches/3/evidence +./www/mtc/v04b/batches/3/index +./www/mtc/v04b/batches/2 +./www/mtc/v04b/batches/2/validity-window +./www/mtc/v04b/batches/2/tree +./www/mtc/v04b/batches/2/entries +./www/mtc/v04b/batches/2/evidence +./www/mtc/v04b/batches/2/index ./queue ./tmp ``` -As we waited a bit longer, the current batch is `2`, which will contain -the queued assertions. The batch `1` in between will be empty. +As we waited a bit longer (again), the current batch is `3`, which will contain +the queued assertions. The batch `2` in between will be empty. -Now `latest` points to `2`, and its signed validity window is more interesting. +Now `latest` points to `3`, and its signed validity window is more interesting. ``` -$ mtc inspect -ca-params www/mtc/v1/ca-params signed-validity-window www/mtc/v1/batches/2/signed-validity-window +$ mtc inspect -ca-params www/mtc/v04b/ca-params validity-window www/mtc/v04b/batches/3/validity-window signature ✅ -batch_number 2 -tree_heads[-9] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-8] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-7] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-6] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-5] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-4] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-3] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-2] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[-1] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98e -tree_heads[0] c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3 -tree_heads[1] 98a421741cf06a19b56d7b52436f686885bd798611426f638ffcdb6b5a65c42c -tree_heads[2] ab3cb1262fc084be0447c2b3d175d63f6ec2782dcc1443888b12f685976093d5 +batch_number 3 +tree_heads[3] 73bff824738bd56b400477ead88a50c61a449c390d539412e95c763f8da1e041 +tree_heads[2] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[1] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[0] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-1] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-2] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-3] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-4] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-5] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-6] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-7] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-8] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf ``` ### Creating a certificate -In MTC, a **certificate** is an assertion, -together with the TrustAnchorIdentifier (consisting of an OID for the CA and the batch number), -and an authentication path in the Merkle tree. +In MTC, a **certificate** is an assertion together with a trust anchor identifier +(to identify the CA), and an authentication path in the Merkle tree. Let's create one for our initial assertion. ``` -$ mtc ca cert -i my-assertion -o my-cert +$ mtc ca cert -i my-asr -o my-cert ``` -If we inspect the certificate, it can recompute the root from the authentication path and CA parameters: +If we inspect the certificate, it can recompute the root from the +authentication path and CA parameters: ``` -$ mtc inspect -ca-params www/mtc/v1/ca-params cert my-cert +$ mtc inspect -ca-params www/mtc/v04b/ca-params cert my-cert subject_type TLS signature_scheme p256 -public_key_hash a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41ef +public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a dns [example.com] ip4 [198.51.100.60] -proof_type merkle_tree_sha256 -CA OID 62253.12.15 -batch 0 -index 0 -recomputed root c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3 +proof_type merkle_tree_sha256 +CA OID 62253.12.15 +Batch number 1 +index 1 +recomputed tree head 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e authentication path - 00b17df8d909fd3e77005486a16ca00fdc9af38f92a23351359fd420d9f2ef78 + e1c642c6da3e8665d83cc359e830929386b11658c55146e88e79c2c466b8cecb ``` -This is indeed the root of the `0`th batch, and so this certificate is valid. +This is indeed the root of batch `1`, and so this certificate is valid. -### Run CA server +### Run CA as server -Run an HTTP server to serve static files, accept queue requests, periodically -issue new batches of certificate, and serve issued certificates. +An Merkle Tree CA can be run just from the commandline, but it's often +more convenient to run it as a server. To start the server, run: -Start the server. ``` -$ mtc ca --ca-path . serve --listen-addr localhost:8080 +$ mtc ca serve -listen-addr localhost:8080 ``` +This will accept HTTP requests on `localhost:8080` and serve the static +files. It will also accept queue requests; periodically issue new batches; +and return issued certificates. + Get and inspect CA parameters. + ``` -$ curl -X GET "http://localhost:8080/static/mtc/v1/ca-params" -o ca-params +$ curl -s "http://localhost:8080/mtc/v04b/ca-params" -o ca-params $ mtc inspect ca-params ca-params -issuer 123.4.5 -start_time 1739593848 2025-02-14 23:30:48 -0500 EST -batch_duration 300 5m0s -life_time 3600 1h0m0s -storage_window_size 24 2h0m0s -validity_window_size 12 -server_prefix ca.example.com/path -public_key fingerprint ml-dsa-87:be1903a366b462b7b4e0010120d4b38279bbf4e350559b95e93671dbc4b821fc +issuer 62253.12.15 +start_time 1745415825 2025-04-23 13:43:45 +0000 UTC +batch_duration 300 5m0s +life_time 3600 1h0m0s +storage_window_size 24 2h0m0s +validity_window_size 12 +server_prefix ca.example.com/path +public_key fingerprint ml-dsa-87:52f3488ca58a51a3d8d4b5d054828e5ebcc3767a0732da374f608f766cf8bad2 ``` Queue up the assertion created in above. + ``` -$ curl -X POST "http://localhost:8080/ca/queue" --data-binary "@my-assertion" -w "%{http_code}" +$ curl -X POST "http://localhost:8080/ca/queue" --data-binary "@my-asr" -w "%{http_code}" 200 ``` -Wait 5 minutes for the next batch and retrieve the certificate from the CA server. +After it's been issued, we can get the certificate via the `/ca/cert` endpoint: + ``` $ curl -X POST "http://localhost:8080/ca/cert" --data-binary "@my-assertion" -o my-cert $ mtc inspect -ca-params ca-params cert my-cert -subject_type TLS +subject_type TLS signature_scheme p256 -public_key_hash f3ee2efd8bc3dd01ab924d12ee0bc5661866a4b147fcdc6881b5455c9084c973 -dns [example.com] -ip4 [198.51.100.60] -proof_type merkle_tree_sha256 -CA OID 123.4.5 -Batch number 991 -index 0 -recomputed root 27a893fa1f864f97b2c2073f784bfd6bbcd1b2deb3d8aafbdd18b09ac10bc430 +public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a +dns [example.com] +ip4 [198.51.100.60] + +proof_type merkle_tree_sha256 +CA OID 62253.12.15 +Batch number 1 +index 1 +recomputed tree head 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e authentication path + e1c642c6da3e8665d83cc359e830929386b11658c55146e88e79c2c466b8cecb ``` From 0e271380091a2627e4eb99f2002f9a467a3baad2 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 23 Apr 2025 16:54:28 +0200 Subject: [PATCH 2/3] Suggestions from Chris and Luke on #65 Co-authored-by: Christopher Patton --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 47ecfb0..599377d 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Merkle Tree Certificates for TLS Implementation of [Merkle Tree Certificates for TLS]( https://davidben.github.io/merkle-tree-certs/draft-davidben-tls-merkle-tree-certs.html) - in Go. This contains a Certification Authority (CA), mirror, and + in Go. This contains a Certification Authority (CA), Mirror, and code to verify certificates. -This does not contain integration with TLS (yet) or the ACME bits. +This does not contain integration with TLS (yet) or the ACME bits (yet). At the moment we differ from `-04` and `main` branch of the specification, by including some [unmerged PRs](https://github.com/davidben/merkle-tree-certs/pulls). @@ -94,14 +94,14 @@ evidence-list (0 entries) ``` An assertion request can contain two bits of extra information besides -the assertion itself. First is a `not_after` field to request to limit +the assertion itself. First is a `not_after` field that limits the validity of the assertion when published. The second is optional "evidence" that's published alongside the assertions. In the future this could be used for serialized DNSSEC proofs. ### Batches, merkle trees and signed validity windows -An MTC CA doesn't give you a certificate for an assertion request immediately. +An MTCA doesn't give you a certificate for an assertion request immediately. Instead, assertions are queued and issued in **batches** with a fixed rhythm, for instance a batch is issued once every hour. All assertions in a single batch by default are valid for the same period of @@ -249,7 +249,7 @@ $ find . We see an `0` and `1` batch have been created. `latest` is a symlink to `1`. -Because we waited more than 5 minutes between creating the CA, +Because we waited more than 5 minutes between creating the CA and starting issuance, both batches `0` and `1` were ready to be issued. The assertions have been issued in batch `1` and batch `0` is empty. From 042003f0d1e62ae5f77ec40debfa9e4414dcfb4f Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Wed, 23 Apr 2025 17:22:20 +0200 Subject: [PATCH 3/3] README: updates --- README.md | 125 ++++++++++++++++++++++++------------------------------ 1 file changed, 55 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index 599377d..f8fc216 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ $ mtc new-assertion-request --tls-pem p256.pub --dns example.com --ip4 198.51.10 Let's check it using `mtc inspect`: ``` -$ ./mtc inspect assertion-request my-asr +$ mtc inspect assertion-request my-asr checksum 2024bdbffe399acca37d299a03c047aa33ef596ae471c17698a0566d00951bd9 not_after unset subject_type TLS @@ -97,7 +97,8 @@ An assertion request can contain two bits of extra information besides the assertion itself. First is a `not_after` field that limits the validity of the assertion when published. The second is optional "evidence" that's published alongside the -assertions. In the future this could be used for serialized DNSSEC proofs. +assertions. In the future this could for instance be used for +serialized DNSSEC proofs. ### Batches, merkle trees and signed validity windows @@ -126,7 +127,12 @@ $ mtc ca new --batch-duration 5m --lifetime 1h 62253.12.15 ca.example.com/path This creates a new MTC CA in the current working directory. It's configured to issue a batch every 5 minutes, and for each batch to be valid for an hour. -It is identified by the [trust anchor identifier]( +For a real CA we'd want batch durations in the order of an hour, +and a lifetime of a week or two. In this demo we shorten things a bit, so +we don't have to wait too long. + +The CA is configured to be hosted at `https://ca.example.com/path` and +to be identified by the [trust anchor identifier]( https://datatracker.ietf.org/doc/draft-ietf-tls-trust-anchor-ids/) 62253.12.15. You can get your own by requesting a [private enterprise number here]( https://www.iana.org/assignments/enterprise-numbers/). @@ -155,13 +161,13 @@ is `ca-params`, which contains the information about the CA: ``` $ mtc inspect ca-params www/mtc/v04b/ca-params issuer 62253.12.15 -start_time 1745415825 2025-04-23 13:43:45 +0000 UTC +start_time 1745420554 2025-04-23 15:02:34 +0000 UTC batch_duration 300 5m0s life_time 3600 1h0m0s storage_window_size 24 2h0m0s validity_window_size 12 server_prefix ca.example.com/path -public_key fingerprint ml-dsa-87:52f3488ca58a51a3d8d4b5d054828e5ebcc3767a0732da374f608f766cf8bad2 +public_key fingerprint ml-dsa-87:84489bcb42b411a85d163ae95e7deb92b106a75840819a985e44d0e01ae3238e ``` The `batches` folder is empty, because there are no batches issued yet. @@ -177,8 +183,8 @@ created earlier with `mtc new-assertion-request`: ``` $ mtc ca queue -i my-asr $ mtc ca show-queue -checksum 3241885a438bd82f21d193fe7be9e87a24f5b6aac899bd780b1604da0ec39f48 -not_after 2025-04-23 14:48:44 +0000 UTC +checksum 91723d11282646f6e798aaeb4ac8515168657c3df4622bc646437b4187a5deb7 +not_after 2025-04-23 16:02:33 +0000 UTC subject_type TLS signature_scheme p256 public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a @@ -189,16 +195,13 @@ evidence-list (0 entries) Total number of assertion requests in queue: 1 ``` -(We can pass the checksum from `new-assertion-request` with `--checksum` -to make sure the assertion wasn't corrupted.) - We can also queue an assertion request ad hoc: ``` $ mtc ca queue --tls-pem p256.pub -d other.example.com -d second.example.com $ mtc ca show-queue | tail -n 10 -checksum 3241885a438bd82f21d193fe7be9e87a24f5b6aac899bd780b1604da0ec39f48 -not_after 2025-04-23 14:48:44 +0000 UTC +checksum 91723d11282646f6e798aaeb4ac8515168657c3df4622bc646437b4187a5deb7 +not_after 2025-04-23 16:02:33 +0000 UTC subject_type TLS signature_scheme p256 public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a @@ -212,10 +215,10 @@ Total number of assertion requests in queue: 2 Let's issue our first batch. ``` -$ mtc ca issue -2025/04/23 15:50:58 INFO Starting issuance time=2025-04-23T13:50:58.023Z -2025/04/23 15:50:58 INFO Current state expectedStored=0,1 expectedActive=0,1 existingBatches=⌀ -2025/04/23 15:50:58 INFO To issue batches=0,1 +$ mtc ca issue +2025/04/23 17:05:20 INFO Starting issuance time=2025-04-23T15:05:20.664Z +2025/04/23 17:05:20 INFO Current state expectedStored=0 expectedActive=0 existingBatches=⌀ +2025/04/23 17:05:20 INFO To issue batches=0 ``` And let's check: @@ -237,40 +240,28 @@ $ find . ./www/mtc/v04b/batches/0/evidence ./www/mtc/v04b/batches/0/index ./www/mtc/v04b/batches/latest -./www/mtc/v04b/batches/1 -./www/mtc/v04b/batches/1/validity-window -./www/mtc/v04b/batches/1/tree -./www/mtc/v04b/batches/1/entries -./www/mtc/v04b/batches/1/evidence -./www/mtc/v04b/batches/1/index ./queue ./tmp ``` -We see an `0` and `1` batch have been created. `latest` is a symlink to `1`. +We see batch `0` has been created. `latest` is a symlink to to `0`. -Because we waited more than 5 minutes between creating the CA -and starting issuance, both batches `0` and `1` were ready to be issued. -The assertions have been issued in batch `1` and batch `0` is empty. - -Now, let's have a look at each batch. The `entries` file is essentially +Now, let's have a look at the batch. The `entries` file is essentially the list of assertions: the difference between a regular assertion and an entry is that with an entry, the public key has been replaced by the hash of the public key. ``` -$ mtc inspect entries www/mtc/v04b/batches/0/entries -Total number of entries: 0 -$ mtc inspect entries www/mtc/v04b/batches/1/entries +$ mtc inspect entries www/mtc/v04b/batches/0/entries key 0b65c8a5f69e88fd1eb58dff4d317f6173bd31773e14d99ace88a2aa7062fdd9 -not_after 2025-04-23 14:48:44 +0000 UTC +not_after 2025-04-23 16:02:33 +0000 UTC subject_type TLS signature_scheme p256 public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a dns [other.example.com second.example.com] key 78b5ccc905b693659bf6581011f8efb17fd7aedf9ca70a196a22923f560feeca -not_after 2025-04-23 14:48:44 +0000 UTC +not_after 2025-04-23 16:02:33 +0000 UTC subject_type TLS signature_scheme p256 public_key_hash 20b57b9c55dab26db14fb6cc801b7d7294cbf448abb1196e1ffc19d73013498a @@ -284,11 +275,10 @@ The `validity-window` is the signed validity window: the tree heads of the currently valid batches: ``` -$ mtc inspect -ca-params www/mtc/v04b/ca-params validity-window www/mtc/v04b/batches/1/validity-window +$ mtc inspect -ca-params www/mtc/v04b/ca-params validity-window www/mtc/v04b/batches/0/validity-window signature ✅ -batch_number 1 -tree_heads[1] 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e -tree_heads[0] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +batch_number 0 +tree_heads[0] 043bc6b0e49a085f2370b2e0f0876d154c2e8d8fe049077dbad118a363580345 tree_heads[-1] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-2] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-3] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf @@ -299,6 +289,7 @@ tree_heads[-7] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-8] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-9] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-10] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-11] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf ``` We need to pass the `ca-params` file to be able to parse the file, and @@ -308,17 +299,17 @@ the placeholder value for an empty tree.) The `tree` file contains the Merkle tree. ``` -$ mtc inspect tree www/mtc/v04b/batches/1/tree +$ mtc inspect tree www/mtc/v04b/batches/0/tree number of leaves 2 number of nodes 3 -tree head 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e +tree head 043bc6b0e49a085f2370b2e0f0876d154c2e8d8fe049077dbad118a363580345 ``` The `evidence` file contains the optional evidence that can be provided with the assertion request. We did not pass any, so they're empty: ``` -$ mtc inspect evidence www/mtc/v04b/batches/1/evidence +$ mtc inspect evidence www/mtc/v04b/batches/0/evidence evidence-list (0 entries) evidence-list (0 entries) @@ -330,7 +321,7 @@ Finally, the `index` file allows a quick lookup in `entries` (and `evidence`) by key (hash of the assertion): ``` -$ mtc inspect index www/mtc/v04b/batches/1/index +$ mtc inspect index www/mtc/v04b/batches/0/index key seqno offset 0b65c8a5f69e88fd1eb58dff4d317f6173bd31773e14d99ace88a2aa7062fdd9 0 0 0 78b5ccc905b693659bf6581011f8efb17fd7aedf9ca70a196a22923f560feeca 1 91 3 @@ -350,9 +341,9 @@ $ mtc ca queue --tls-pem p256.pub -d 1.example.com $ mtc ca queue --tls-pem p256.pub -d 2.example.com $ mtc ca queue --tls-pem p256.pub -d 3.example.com $ mtc ca issue -2025/04/23 16:03:35 INFO Starting issuance time=2025-04-23T14:03:35.653Z -2025/04/23 16:03:35 INFO Current state expectedStored=0,…,3 expectedActive=0,…,3 existingBatches=0,1 -2025/04/23 16:03:35 INFO To issue batches=2,3 +2025/04/23 17:12:45 INFO Starting issuance time=2025-04-23T15:12:45.869Z +2025/04/23 17:12:45 INFO Current state expectedStored=0,…,2 expectedActive=0,…,2 existingBatches=0 +2025/04/23 17:12:45 INFO To issue batches=1,2 $ find . ``` . @@ -367,6 +358,7 @@ $ find . ./www/mtc/v04b/batches/0/tree ./www/mtc/v04b/batches/0/entries ./www/mtc/v04b/batches/0/evidence +./www/mtc/v04b/batches/0/latest ./www/mtc/v04b/batches/0/index ./www/mtc/v04b/batches/latest ./www/mtc/v04b/batches/1 @@ -375,12 +367,6 @@ $ find . ./www/mtc/v04b/batches/1/entries ./www/mtc/v04b/batches/1/evidence ./www/mtc/v04b/batches/1/index -./www/mtc/v04b/batches/3 -./www/mtc/v04b/batches/3/validity-window -./www/mtc/v04b/batches/3/tree -./www/mtc/v04b/batches/3/entries -./www/mtc/v04b/batches/3/evidence -./www/mtc/v04b/batches/3/index ./www/mtc/v04b/batches/2 ./www/mtc/v04b/batches/2/validity-window ./www/mtc/v04b/batches/2/tree @@ -391,19 +377,17 @@ $ find . ./tmp ``` -As we waited a bit longer (again), the current batch is `3`, which will contain -the queued assertions. The batch `2` in between will be empty. - -Now `latest` points to `3`, and its signed validity window is more interesting. +As we waited a bit longer, the current batch is `2`, which will contain +the queued assertions. The batch `1` in between will be empty. +Now `latest` points to `2`, and its signed validity window is more interesting. ``` -$ mtc inspect -ca-params www/mtc/v04b/ca-params validity-window www/mtc/v04b/batches/3/validity-window +$ mtc inspect -ca-params www/mtc/v04b/ca-params validity-window www/mtc/v04b/batches/1/validity-window signature ✅ -batch_number 3 -tree_heads[3] 73bff824738bd56b400477ead88a50c61a449c390d539412e95c763f8da1e041 -tree_heads[2] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf -tree_heads[1] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf -tree_heads[0] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +batch_number 2 +tree_heads[2] 03a95ba3c354e2b0eb4bea9b111dbc8b97e2c90b85ddcc63d4b635b16f77005d +tree_heads[1] 7ceda88ec6c8e34ecacde47588e2605fb86192b94ca96cb897fa6ff442198c8c +tree_heads[0] 043bc6b0e49a085f2370b2e0f0876d154c2e8d8fe049077dbad118a363580345 tree_heads[-1] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-2] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-3] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf @@ -412,6 +396,7 @@ tree_heads[-5] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-6] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-7] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf tree_heads[-8] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf +tree_heads[-9] a7b081f10c7116c30781a957c3f52625c4d831c8d61ceea021db101ab3c901cf ``` ### Creating a certificate @@ -437,14 +422,14 @@ ip4 [198.51.100.60] proof_type merkle_tree_sha256 CA OID 62253.12.15 -Batch number 1 +Batch number 0 index 1 -recomputed tree head 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e +recomputed tree head 043bc6b0e49a085f2370b2e0f0876d154c2e8d8fe049077dbad118a363580345 authentication path - e1c642c6da3e8665d83cc359e830929386b11658c55146e88e79c2c466b8cecb + 8964f010faa9e499b21917f8792b541b7b1ac19f313a5d53094c698c2edc330b ``` -This is indeed the root of batch `1`, and so this certificate is valid. +This is indeed the root of batch `0`, and so this certificate is valid. ### Run CA as server @@ -465,13 +450,13 @@ Get and inspect CA parameters. $ curl -s "http://localhost:8080/mtc/v04b/ca-params" -o ca-params $ mtc inspect ca-params ca-params issuer 62253.12.15 -start_time 1745415825 2025-04-23 13:43:45 +0000 UTC +start_time 1745420554 2025-04-23 15:02:34 +0000 UTC batch_duration 300 5m0s life_time 3600 1h0m0s storage_window_size 24 2h0m0s validity_window_size 12 server_prefix ca.example.com/path -public_key fingerprint ml-dsa-87:52f3488ca58a51a3d8d4b5d054828e5ebcc3767a0732da374f608f766cf8bad2 +public_key fingerprint ml-dsa-87:84489bcb42b411a85d163ae95e7deb92b106a75840819a985e44d0e01ae3238e ``` Queue up the assertion created in above. @@ -484,7 +469,7 @@ $ curl -X POST "http://localhost:8080/ca/queue" --data-binary "@my-asr" -w "%{ht After it's been issued, we can get the certificate via the `/ca/cert` endpoint: ``` -$ curl -X POST "http://localhost:8080/ca/cert" --data-binary "@my-assertion" -o my-cert +$ curl -X POST "http://localhost:8080/ca/cert" --data-binary "@my-asr" -o my-cert $ mtc inspect -ca-params ca-params cert my-cert subject_type TLS signature_scheme p256 @@ -494,9 +479,9 @@ ip4 [198.51.100.60] proof_type merkle_tree_sha256 CA OID 62253.12.15 -Batch number 1 +Batch number 0 index 1 -recomputed tree head 074e46cfebf57e3e21bea9b8eb6f446060db668926a041aa0bc2b13e0708dd3e +recomputed tree head 043bc6b0e49a085f2370b2e0f0876d154c2e8d8fe049077dbad118a363580345 authentication path - e1c642c6da3e8665d83cc359e830929386b11658c55146e88e79c2c466b8cecb + 8964f010faa9e499b21917f8792b541b7b1ac19f313a5d53094c698c2edc330b ```