From 4f5e93a19328c778542fb152eaeff10dd75df23f Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Fri, 30 Jan 2026 10:27:25 -0500 Subject: [PATCH] Implement draft-davidben-10 in the demo tool Since draft-davidben-09 is what some prototypes are targetting, keep support in there by adding a "Version" field to the config file. --- demo/README.md | 3 --- demo/config.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ demo/encode.go | 15 ++++++++++----- demo/encode_test.go | 37 +++++++++++++++++++++++++++---------- demo/main.go | 2 +- demo/mtc.json | 1 + 6 files changed, 83 insertions(+), 19 deletions(-) diff --git a/demo/README.md b/demo/README.md index e6f2ac0..9acf6ff 100644 --- a/demo/README.md +++ b/demo/README.md @@ -3,6 +3,3 @@ This tool generates a corpus of test certificates and issuance log based on a JSON configuration file. It has been minimally tested and may not yet correctly match the spec. - -Currently this implements the draft-davidben-tls-merkle-tree-certs-09 variant. -It has not yet been updated for -10. diff --git a/demo/config.go b/demo/config.go index e09b88b..d2fc28d 100644 --- a/demo/config.go +++ b/demo/config.go @@ -14,6 +14,49 @@ var ( oidServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} ) +type DraftVersion int + +// Support versions for as long as it is easy to support and useful. If we need +// to remove one, older versions of the demo tool are always available. +const ( + VersionDavidben09 DraftVersion = iota + VersionDavidben10 +) + +func (v DraftVersion) String() string { + switch v { + case VersionDavidben09: + return "davidben-09" + case VersionDavidben10: + return "davidben-10" + } + panic(fmt.Sprintf("unknown version %d", v)) +} + +func (v *DraftVersion) UnmarshalJSON(data []byte) error { + var s string + if err := json.Unmarshal(data, &s); err != nil { + return err + } + var ok bool + *v, ok = DraftVersionFromString(s) + if !ok { + return fmt.Errorf("unknown version %q", s) + } + return nil +} + +func DraftVersionFromString(s string) (v DraftVersion, ok bool) { + switch s { + case "davidben-09": + return VersionDavidben09, true + case "davidben-10": + return VersionDavidben10, true + default: + return 0, false + } +} + type SignatureAlgorithm int const ( @@ -62,6 +105,7 @@ func (s *SignatureAlgorithm) UnmarshalJSON(data []byte) error { } type CAConfig struct { + Version DraftVersion LogID TrustAnchorID Cosigners []CosignerConfig Entries []EntryConfig diff --git a/demo/encode.go b/demo/encode.go index c71ee97..7d00504 100644 --- a/demo/encode.go +++ b/demo/encode.go @@ -194,10 +194,8 @@ func MarshalNullEntry() []byte { return []byte{byte(entryTypeNull >> 8), byte(entryTypeNull)} } -func MarshalTBSCertificateLogEntry(issuer TrustAnchorID, entry *EntryConfig) ([]byte, error) { - b := cryptobyte.NewBuilder(nil) - b.AddUint16(entryTypeTBSCert) - b.AddASN1(cbasn1.SEQUENCE, func(tbs *cryptobyte.Builder) { +func MarshalTBSCertificateLogEntry(version DraftVersion, issuer TrustAnchorID, entry *EntryConfig) ([]byte, error) { + marshalContents := func(tbs *cryptobyte.Builder) { addX509V3Version(tbs) addIssuer(tbs, issuer) addValidity(tbs, entry) @@ -207,7 +205,14 @@ func MarshalTBSCertificateLogEntry(issuer TrustAnchorID, entry *EntryConfig) ([] spkiHash.AddBytes(h[:]) }) addExtensions(tbs, entry) - }) + } + b := cryptobyte.NewBuilder(nil) + b.AddUint16(entryTypeTBSCert) + if version >= VersionDavidben10 { + marshalContents(b) + } else { + b.AddASN1(cbasn1.SEQUENCE, marshalContents) + } return b.Bytes() } diff --git a/demo/encode_test.go b/demo/encode_test.go index 11ee571..3e7e8c4 100644 --- a/demo/encode_test.go +++ b/demo/encode_test.go @@ -28,6 +28,7 @@ func TestMarshalTBSCertificate(t *testing.T) { } var tests = []struct { + version DraftVersion issuer TrustAnchorID serial int entry *EntryConfig @@ -36,20 +37,22 @@ func TestMarshalTBSCertificate(t *testing.T) { }{ // A minimal TBSCertificate { - issuer: issuer, - serial: 1234, + version: VersionDavidben10, + issuer: issuer, + serial: 1234, entry: &EntryConfig{ PublicKey: publicKey, NotBefore: time.Unix(1577836800, 0), // 2020-01-01 00:00:00 NotAfter: time.Unix(1609459199, 0), // 2020-12-31 23:59:59 }, expectedTBSHex: "3081afa003020102020204d2300c060a2b0601040182da4b2f00301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a30003059301306072a8648ce3d020106082a8648ce3d03010703420004e62b69e2bf659f97be2f1e0d948a4cd5976bb7a91e0d46fbdda9a91e9ddcba5a01e7d697a80a18f9c3c4a31e56e27c8348db161a1cf51d7ef1942d4bcf7222c1", - expectedLogEntryHex: "00013064a003020102301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a30000420b3aea0f0a50538874f2b4c912f2676bd25ccc3dae700e20dcad42d3d5c074ca5", + expectedLogEntryHex: "0001a003020102301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a30000420b3aea0f0a50538874f2b4c912f2676bd25ccc3dae700e20dcad42d3d5c074ca5", }, // Fill in a bit of everything. { - issuer: issuer, - serial: 1234, + version: VersionDavidben10, + issuer: issuer, + serial: 1234, entry: &EntryConfig{ Subject: SubjectConfig{ CommonName: "example.com", @@ -62,13 +65,14 @@ func TestMarshalTBSCertificate(t *testing.T) { ExtKeyUsage: []ExtKeyUsageConfig{ExtKeyUsageConfig(oidServerAuth)}, }, expectedTBSHex: "30820124a003020102020204d2300c060a2b0601040182da4b2f00301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a3016311430120603550403130b6578616d706c652e636f6d3059301306072a8648ce3d020106082a8648ce3d03010703420004e62b69e2bf659f97be2f1e0d948a4cd5976bb7a91e0d46fbdda9a91e9ddcba5a01e7d697a80a18f9c3c4a31e56e27c8348db161a1cf51d7ef1942d4bcf7222c1a35d305b300e0603551d0f0101ff04040302078030160603551d250101ff040c300a06082b0601050507030130310603551d110101ff04273025820b6578616d706c652e636f6d8209612e6578616d706c65820b2a2e622e6578616d706c65", - expectedLogEntryHex: "00013081d9a003020102301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a3016311430120603550403130b6578616d706c652e636f6d0420b3aea0f0a50538874f2b4c912f2676bd25ccc3dae700e20dcad42d3d5c074ca5a35d305b300e0603551d0f0101ff04040302078030160603551d250101ff040c300a06082b0601050507030130310603551d110101ff04273025820b6578616d706c652e636f6d8209612e6578616d706c65820b2a2e622e6578616d706c65", + expectedLogEntryHex: "0001a003020102301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a3016311430120603550403130b6578616d706c652e636f6d0420b3aea0f0a50538874f2b4c912f2676bd25ccc3dae700e20dcad42d3d5c074ca5a35d305b300e0603551d0f0101ff04040302078030160603551d250101ff040c300a06082b0601050507030130310603551d110101ff04273025820b6578616d706c652e636f6d8209612e6578616d706c65820b2a2e622e6578616d706c65", }, // Generate a CA too, even though it's a little questionable. See // https://github.com/davidben/merkle-tree-certs/issues/146 { - issuer: issuer, - serial: 1234, + version: VersionDavidben10, + issuer: issuer, + serial: 1234, entry: &EntryConfig{ Subject: SubjectConfig{ CommonName: "A CA?", @@ -81,7 +85,20 @@ func TestMarshalTBSCertificate(t *testing.T) { MaxPathLen: ptrOf(int64(5)), }, expectedTBSHex: "3081e7a003020102020204d2300c060a2b0601040182da4b2f00301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a3010310e300c06035504031305412043413f3059301306072a8648ce3d020106082a8648ce3d03010703420004e62b69e2bf659f97be2f1e0d948a4cd5976bb7a91e0d46fbdda9a91e9ddcba5a01e7d697a80a18f9c3c4a31e56e27c8348db161a1cf51d7ef1942d4bcf7222c1a3263024300e0603551d0f0101ff04040302020430120603551d130101ff040830060101ff020105", - expectedLogEntryHex: "000130819ca003020102301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a3010310e300c06035504031305412043413f0420b3aea0f0a50538874f2b4c912f2676bd25ccc3dae700e20dcad42d3d5c074ca5a3263024300e0603551d0f0101ff04040302020430120603551d130101ff040830060101ff020105", + expectedLogEntryHex: "0001a003020102301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a3010310e300c06035504031305412043413f0420b3aea0f0a50538874f2b4c912f2676bd25ccc3dae700e20dcad42d3d5c074ca5a3263024300e0603551d0f0101ff04040302020430120603551d130101ff040830060101ff020105", + }, + // draft-davidben-09 included a TBSCertificate wrapper TLV. + { + version: VersionDavidben09, + issuer: issuer, + serial: 1234, + entry: &EntryConfig{ + PublicKey: publicKey, + NotBefore: time.Unix(1577836800, 0), // 2020-01-01 00:00:00 + NotAfter: time.Unix(1609459199, 0), // 2020-12-31 23:59:59 + }, + expectedTBSHex: "3081afa003020102020204d2300c060a2b0601040182da4b2f00301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a30003059301306072a8648ce3d020106082a8648ce3d03010703420004e62b69e2bf659f97be2f1e0d948a4cd5976bb7a91e0d46fbdda9a91e9ddcba5a01e7d697a80a18f9c3c4a31e56e27c8348db161a1cf51d7ef1942d4bcf7222c1", + expectedLogEntryHex: "00013064a003020102301931173015060a2b0601040182da4b2f010c0733323437332e31301e170d3230303130313030303030305a170d3230313233313233353935395a30000420b3aea0f0a50538874f2b4c912f2676bd25ccc3dae700e20dcad42d3d5c074ca5", }, } for i, tt := range tests { @@ -94,7 +111,7 @@ func TestMarshalTBSCertificate(t *testing.T) { t.Errorf("%d. AddTBSCertificate() gave %s, wanted %s", i, got, tt.expectedTBSHex) } - log, err := MarshalTBSCertificateLogEntry(tt.issuer, tt.entry) + log, err := MarshalTBSCertificateLogEntry(tt.version, tt.issuer, tt.entry) if err != nil { t.Errorf("%d. MarshalTBSCertificateLogEntry() failed: %s", i, err) } else if got := hex.EncodeToString(log); got != tt.expectedLogEntryHex { diff --git a/demo/main.go b/demo/main.go index 8c486b4..21ed15b 100644 --- a/demo/main.go +++ b/demo/main.go @@ -99,7 +99,7 @@ func do() error { repeat = entryConfig.Repeat } for range repeat { - entry, err := MarshalTBSCertificateLogEntry(config.LogID, entryConfig) + entry, err := MarshalTBSCertificateLogEntry(config.Version, config.LogID, entryConfig) if err != nil { return err } diff --git a/demo/mtc.json b/demo/mtc.json index ce4660d..31944d5 100644 --- a/demo/mtc.json +++ b/demo/mtc.json @@ -1,4 +1,5 @@ { + "Version": "davidben-10", "LogID": "32473.1", "Cosigners": [ {