Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Go implementation of Merkle Tree Certificates

License

NotificationsYou must be signed in to change notification settings

bwesterb/mtc

Repository files navigation

🚨 Merkle Tree Certificates (MTC) is a moving target.

Implementation ofMerkle Tree Certificates for TLS

At the moment only the Certification Authority (CA) side is implemented,and we differ from-03 andmaster branch, by includingsomeunmerged PRs.

Demo

For a proper introduction and motivation, check out thedraft specificationandDavid's TLS working group presentation at IETF116.

Merkle Tree Certificates is anoptimisation to the WebPKI (includingCertificate Transparency)motivated by the large sizes of typical post-quantum signatures and public keys,to reduce the number of keys and signaturesrequired for the common case where

  1. Certificate issuance does not have to be immediate. For instance, becausea certificate can be requested ahead of time for an existing domainby anACME clientlikecertbot.

  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 theTransparency Services sectionof the spec.

MTC does not aim to replace the full WebPKI, but is a first meaningful stepfor improvement.

Intermezzo:mtc commandline tool

To play around with MTC, you can install themtc commandline tool:

$ go install github.com/bwesterb/mtc/cmd/mtc@v0.1.2

Assertions

In MTC CAs certifyassertions, which bind asubject to aclaim.An informal example of an assertion is:

For TLS, you can trust the P-256 public keya02342ff2…23efwhen visitingexample.com or198.51.100.60.

The first part (TLS and the public key) is thesubject, and thelatter (domain and IP) are theclaim.Roughly, an assertion is like a certificate without the signature.

To create an assertion, you can use themtc new-assertion command.First, let's quickly create a P-256 public key to play with.

$ openssl ecparam -name prime256v1 -genkey -out p256.priv$ openssl ec -in p256.priv -pubout -out p256.pub

Now we create an assertion that this P-256 public key shouldbe valid forexample.com and198.51.100.60, and write it tothemy-assertion.

$ mtc new-assertion --tls-pem p256.pub --dns example.com --ip4 198.51.100.60 -o my-assertionchecksum: 14bc907eafd02d5be8b8cc319d87ad5afe9266a6910a18cbdcbfcee1b7af696a

Let's check it usingmtc inspect:

$ mtc inspect assertion my-assertionsubject_type     TLSsignature_scheme p256public_key_hash  a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41efdns              [example.com]ip4              [198.51.100.60]

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 inbatches 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,thevalidity window, which is, for instance, two weeks.The CA publishes these batches publicly over HTTP.

For each batch, the CA computes aMerkle tree.This condenses all the assertions in that batch into a singleroot hash.For every batch, the CA signs that root together with all the rootsof the currently valid batches. This signature, together with thosesigned roots is called thesigned validity window for that batch,which is published alongside the assertions.

Creating a CA

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 calledmy-mtc-ca, and puts the data in thecurrent working directory. A batch is issued every 5 minutes, andeach batch is valid for one hour.

Let's have a look at the files created:

$ find .../signing.key./www./www/mtc./www/mtc/v1./www/mtc/v1/ca-params./www/mtc/v1/batches./queue./tmp

Thesigning.key file contains the private key of the keypair used by the CA.

Thewww folder contains the files that have to be servedathttps://ca.example.com/path. At the moment, the only file of interestisca-params, which contains the information about the CA:

$ mtc inspect ca-params www/mtc/v1/ca-paramsissuer                 62253.12.15start_time             1705677477 2024-01-19 16:17:57 +0100 CETbatch_duration         300        5m0slife_time              3600       1h0m0sstorage_window_size    24         2h0m0svalidity_window_size   12server_prefix          ca.example.com/pathpublic_key fingerprint ml-dsa-87:85b5a617ef109e0a8d68a094c8b969f622ac4096c513fa0acd169c231ce2fad5

Thebatches folder is empty, because there are no batches issued yet.

Thequeue file contains the assertions that will be issued.

Issuing our first batch

Let's issue our first assertion. We can read the assertion from disk we'vecreated earlier withmtc new-assertion:

$ mtc ca queue -i my-assertion $ mtc ca show-queuechecksum         14bc907eafd02d5be8b8cc319d87ad5afe9266a6910a18cbdcbfcee1b7af696asubject_type     TLSsignature_scheme p256public_key_hash  a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41efdns              [example.com]ip4              [198.51.100.60]Total number of assertions in queue: 1

(We can pass the checksum fromnew-assertion with--checksum to make surethe assertion wasn't corrupted.)

We can also queue an assertion ad hoc:

$ mtc ca queue --tls-pem p256.pub -d other.example.com -d second.example.com$ mtc ca show-queue | tail -n 8checksum         fbdea936ae7795a3fa01d44230daba351d7480eceadd086ba32938ebc88a5458subject_type     TLSsignature_scheme p256public_key_hash  a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41efdns              [other.example.com second.example.com]Total number of assertions 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:002024/01/19 16:27:31 INFO Current state expectedStored=0 expectedActive=0 existingBatches=⌀2024/01/19 16:27:31 INFO To issue batches=0

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./queue./tmp

We see a0 batch has been created.latest is a symlink to0.

Theabridged-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 replacedby the hash of the public key.

$ mtc inspect abridged-assertions www/mtc/v1/batches/0/abridged-assertionskey              28b2216e7905ab48d5444f5b7ebf3d2386bc0444c9721fff77b0b313e734dab4subject_type     TLSsignature_scheme p256public_key_hash  a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41efdns              [example.com]ip4              [198.51.100.60]key              80944a1728bc7b4cd7e583c6b24a5f413ba50b7ef5ba9d214e26c1a1974f0a19subject_type     TLSsignature_scheme p256public_key_hash  a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41efdns              [other.example.com second.example.com]Total number of abridged assertions: 2

Thesigned-validity-window is the signed validity window: the roots ofthe currently valid batches:

$ mtc inspect -ca-params www/mtc/v1/ca-params signed-validity-window www/mtc/v1/batches/0/signed-validity-window signature       ✅batch_number    0tree_heads[-11] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-10] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-9]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-8]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-7]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-6]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-5]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-4]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-3]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-2]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-1]  f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[0]   c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3

We need to pass theca-params file to be able to parse the file, andcheck the signature therein. (As this is the first batch, the previous batchescontain a placeholder value.)

Thetree file contains the Merkle tree.

$ mtc inspect tree www/mtc/v1/batches/0/tree       number of leaves 2number of nodes  3root             c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3

Finally, theindex file allows a quick lookup inabridged-assertionsby key (hash of the assertion):

$ mtc inspect index www/mtc/v1/batches/0/index                                                             key   seqno  offset28b2216e7905ab48d5444f5b7ebf3d2386bc0444c9721fff77b0b313e734dab4       0       080944a1728bc7b4cd7e583c6b24a5f413ba50b7ef5ba9d214e26c1a1974f0a19       1      69total number of entries: 2

Issuing more batches

As we just issued a new batch, we need to wait a while before thenext batch is ready to issue.

Let's queue some more assertions, wait a bit, and issue a new batch.

$ 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 issue2024/01/19 16:33:57 INFO Starting issuance time=2024-01-19T16:33:57.860+01:002024/01/19 16:33:57 INFO Current state expectedStored=0,…,2 expectedActive=0,…,2 existingBatches=02024/01/19 16:33:57 INFO To issue batches=1,2$ 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./queue./tmp

As we waited a bit longer, the current batch is2, which will containthe queued assertions. The batch1 in between will be empty.

Nowlatest points to2, 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-windowsignature      ✅batch_number   2tree_heads[-9] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-8] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-7] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-6] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-5] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-4] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-3] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-2] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[-1] f2f65b0486c8cad3876475c9c509afdf3f51dc073b1d2d2d261ff9883d63f98etree_heads[0]  c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3tree_heads[1]  98a421741cf06a19b56d7b52436f686885bd798611426f638ffcdb6b5a65c42ctree_heads[2]  ab3cb1262fc084be0447c2b3d175d63f6ec2782dcc1443888b12f685976093d5

Creating a certificate

In MTC, acertificate 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.Let's create one for our initial assertion.

$ mtc ca cert -i my-assertion -o my-cert

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-certsubject_type     TLSsignature_scheme p256public_key_hash  a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41efdns              [example.com]ip4              [198.51.100.60]proof_type      merkle_tree_sha256CA OID          62253.12.15batch           0index           0recomputed root c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3authentication path 00b17df8d909fd3e77005486a16ca00fdc9af38f92a23351359fd420d9f2ef78

This is indeed the root of the0th batch, and so this certificate is valid.

Run CA server

Run an HTTP server to serve static files, accept queue requests, periodicallyissue new batches of certificate, and serve issued certificates.

Start the server.

$ mtc ca --ca-path . serve --listen-addr localhost:8080

Get and inspect CA parameters.

$ curl -X GET "http://localhost:8080/static/mtc/v1/ca-params" -o ca-params$ mtc inspect ca-params ca-paramsissuer         123.4.5start_time       1739593848 2025-02-14 23:30:48 -0500 ESTbatch_duration     300    5m0slife_time       3600    1h0m0sstorage_window_size  24     2h0m0svalidity_window_size  12server_prefix    ca.example.com/pathpublic_key fingerprint ml-dsa-87:be1903a366b462b7b4e0010120d4b38279bbf4e350559b95e93671dbc4b821fc

Queue up the assertion created in above.

$ curl -X POST "http://localhost:8080/ca/queue" --data-binary "@my-assertion" -w "%{http_code}"200

Wait 5 minutes for the next batch and retrieve the certificate from the CA server.

$ curl -X POST "http://localhost:8080/ca/cert" --data-binary "@my-assertion" -o my-cert$ mtc inspect -ca-params ca-params cert my-certsubject_type   TLSsignature_scheme p256public_key_hash f3ee2efd8bc3dd01ab924d12ee0bc5661866a4b147fcdc6881b5455c9084c973dns       [example.com]ip4       [198.51.100.60]proof_type   merkle_tree_sha256CA OID     123.4.5Batch number  991index      0recomputed root 27a893fa1f864f97b2c2073f784bfd6bbcd1b2deb3d8aafbdd18b09ac10bc430authentication path

About

Go implementation of Merkle Tree Certificates

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp