Skip to content

Commit

Permalink
Merge pull request bwesterb#5 from pohlm01/main
Browse files Browse the repository at this point in the history
Adopt `TrustAnchorIdentifiers` from v03 of MTC draft
  • Loading branch information
bwesterb authored Sep 17, 2024
2 parents 4f66853 + e5c15c7 commit 400c835
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 228 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: '1.23'

Expand Down
32 changes: 13 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ For every batch, the CA signs that root together with all the roots
Let's create an MTC CA.

```
$ mtc ca new --batch-duration 5m --lifetime 1h my-mtc-ca ca.example.com/path
$ 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
Expand Down Expand Up @@ -137,7 +137,7 @@ is `ca-params`, which contains the information about the CA:

```
$ mtc inspect ca-params www/mtc/v1/ca-params
issuer_id my-mtc-ca
issuer 62253.12.15
start_time 1705677477 2024-01-19 16:17:57 +0100 CET
batch_duration 300 5m0s
life_time 3600 1h0m0s
Expand Down Expand Up @@ -356,33 +356,27 @@ tree_heads[2] ab3cb1262fc084be0447c2b3d175d63f6ec2782dcc1443888b12f685976093d5

### Creating a certificate

In MTC, a **certificate** is an assertion, together with the batch number,
`issuer_id` of the CA, and an authentication path in the Merkle tree.
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.
Let's create one for our initial assertion.

```
$ mtc ca cert -i my-assertion -o my-cert
$ mtc inspect cert 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-cert
subject_type TLS
signature_scheme p256
public_key_hash a02a1758e4c9d6511dc02f59301b9f29e41762d3d769c87a22333497984a41ef
dns [example.com]
ip4 [198.51.100.60]
proof_type merkle_tree_sha256
issuer_id my-mtc-ca
batch 0
index 0
authentication path
00b17df8d909fd3e77005486a16ca00fdc9af38f92a23351359fd420d9f2ef78
```

If we provide the `ca-params` to `mtc inspect`, it can recompute the root
from the authentication path:

```
$ mtc inspect -ca-params www/mtc/v1/ca-params cert my-cert
[…]
proof_type merkle_tree_sha256
CA OID 62253.12.15
batch 0
index 0
recomputed root c005dcdb53c4e41befcf3a294b815d8b8aa0a260e9f10bfd4e4cb52eb3724aa3
Expand Down
6 changes: 3 additions & 3 deletions ca/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var (
)

type NewOpts struct {
IssuerId string
Issuer mtc.RelativeOID
HttpServer string

// Fields below are optional.
Expand Down Expand Up @@ -991,7 +991,7 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
return nil
}

// Creates a new Merkle Tree CA, and opens it.
// New creates a new Merkle Tree CA, and opens it.
//
// Call Handle.Close() when done.
func New(path string, opts NewOpts) (*Handle, error) {
Expand Down Expand Up @@ -1034,7 +1034,7 @@ func New(path string, opts NewOpts) (*Handle, error) {
h.params.StartTime = uint64(time.Now().Unix())

h.params.HttpServer = opts.HttpServer
h.params.IssuerId = opts.IssuerId
h.params.Issuer = opts.Issuer

if opts.SignatureScheme == 0 {
opts.SignatureScheme = mtc.TLSDilitihium5r3
Expand Down
90 changes: 50 additions & 40 deletions cmd/mtc/main.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package main

import (
"errors"
"github.com/bwesterb/mtc"
"github.com/bwesterb/mtc/ca"

"github.com/urfave/cli/v2"
"golang.org/x/crypto/cryptobyte"

"bufio"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
"fmt"
"io"
"net"
Expand Down Expand Up @@ -400,10 +399,18 @@ func handleCaNew(cc *cli.Context) error {
cli.ShowSubcommandHelp(cc)
return errArgs
}

taiString := cc.Args().Get(0)
oid := mtc.RelativeOID{}
err := oid.UnmarshalText([]byte(taiString))
if err != nil {
return err
}

h, err := ca.New(
cc.String("ca-path"),
ca.NewOpts{
IssuerId: cc.Args().Get(0),
Issuer: oid,
HttpServer: cc.Args().Get(1),

BatchDuration: cc.Duration("batch-duration"),
Expand Down Expand Up @@ -575,23 +582,28 @@ func handleInspectCert(cc *cli.Context) error {
if err != nil {
return err
}
params, err := inspectGetCAParams(cc)
if err != nil {
return err
}

caStore := mtc.LocalCAStore{}
caStore.Add(*params)

var c mtc.BikeshedCertificate
err = c.UnmarshalBinary(buf)
err = c.UnmarshalBinary(buf, &caStore)
if err != nil {
return err
}

w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
writeAssertion(w, c.Assertion)
fmt.Fprintf(w, "\n")
fmt.Fprintf(w, "proof_type\t%v\n", c.Proof.TrustAnchor().ProofType())
tai := c.Proof.TrustAnchorIdentifier()
fmt.Fprintf(w, "proof_type\t%v\n", tai.ProofType(&caStore))

switch anch := c.Proof.TrustAnchor().(type) {
case *mtc.MerkleTreeTrustAnchor:
fmt.Fprintf(w, "issuer_id\t%s\n", anch.IssuerId())
fmt.Fprintf(w, "batch\t%d\n", anch.BatchNumber())
}
fmt.Fprintf(w, "CA OID\t%s\n", tai.Issuer)
fmt.Fprintf(w, "Batch number\t%d\n", tai.BatchNumber)

switch proof := c.Proof.(type) {
case *mtc.MerkleTreeProof:
Expand All @@ -601,38 +613,30 @@ func handleInspectCert(cc *cli.Context) error {
switch proof := c.Proof.(type) {
case *mtc.MerkleTreeProof:
path := proof.Path()
batch := &mtc.Batch{
CA: params,
Number: tai.BatchNumber,
}

params, err := inspectGetCAParams(cc)
if err == nil {
anch := proof.TrustAnchor().(*mtc.MerkleTreeTrustAnchor)

batch := &mtc.Batch{
CA: params,
Number: anch.BatchNumber(),
}

if anch.IssuerId() != params.IssuerId {
return fmt.Errorf(
"IssuerId doesn't match: %s ≠ %s",
params.IssuerId,
anch.IssuerId(),
)
}
aa := c.Assertion.Abridge()
root, err := batch.ComputeRootFromAuthenticationPath(
proof.Index(),
path,
&aa,
if !tai.Issuer.Equal(&params.Issuer) {
return fmt.Errorf(
"IssuerId doesn't match: %s ≠ %s",
params.Issuer,
tai.Issuer,
)
if err != nil {
return fmt.Errorf("computing root: %w", err)
}

fmt.Fprintf(w, "recomputed root\t%x\n", root)
} else if err != errNoCaParams {
return err
}
aa := c.Assertion.Abridge()
root, err := batch.ComputeRootFromAuthenticationPath(
proof.Index(),
path,
&aa,
)
if err != nil {
return fmt.Errorf("computing root: %w", err)
}

fmt.Fprintf(w, "recomputed root\t%x\n", root)

w.Flush()
fmt.Printf("authentication path\n")
for i := 0; i < len(path)/mtc.HashLen; i++ {
Expand Down Expand Up @@ -721,7 +725,7 @@ func handleInspectCaParams(cc *cli.Context) error {
return err
}
w := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
fmt.Fprintf(w, "issuer_id\t%s\n", p.IssuerId)
fmt.Fprintf(w, "issuer\t%s\n", p.Issuer)
fmt.Fprintf(w, "start_time\t%d\t%s\n", p.StartTime,
time.Unix(int64(p.StartTime), 0))
fmt.Fprintf(w, "batch_duration\t%d\t%s\n", p.BatchDuration,
Expand Down Expand Up @@ -764,7 +768,7 @@ func main() {
Name: "new",
Usage: "creates a new CA",
Action: handleCaNew,
ArgsUsage: "<issuer-id> <http-server>",
ArgsUsage: "<issuer-oid> <http-server>",
Flags: []cli.Flag{
&cli.DurationFlag{
Name: "batch-duration",
Expand All @@ -781,6 +785,12 @@ func main() {
Aliases: []string{"s"},
Usage: "time to serve assertions",
},
&cli.StringFlag{
Name: "ca-path",
Aliases: []string{"p"},
Usage: "root directory to store CA files",
Value: ".",
},
},
},
{
Expand Down
Loading

0 comments on commit 400c835

Please sign in to comment.