From 8e10c0045cd2c4a27536efc9fea2ef1984737f08 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 8 Apr 2024 14:12:52 +0200 Subject: [PATCH] internal/ctlog: simplify and fold injectedSigner --- internal/ctlog/ctlog.go | 22 +++++++++---- internal/tlogx/logx.go | 73 ----------------------------------------- 2 files changed, 16 insertions(+), 79 deletions(-) delete mode 100644 internal/tlogx/logx.go diff --git a/internal/ctlog/ctlog.go b/internal/ctlog/ctlog.go index 5e77cc0..24001bf 100644 --- a/internal/ctlog/ctlog.go +++ b/internal/ctlog/ctlog.go @@ -19,7 +19,6 @@ import ( "crawshaw.io/sqlite" "filippo.io/sunlight" "filippo.io/sunlight/internal/rfc6979" - "filippo.io/sunlight/internal/tlogx" ct "github.com/google/certificate-transparency-go" "github.com/google/certificate-transparency-go/x509util" "github.com/prometheus/client_golang/prometheus" @@ -123,7 +122,7 @@ func CreateLog(ctx context.Context, config *Config) error { timestamp := timeNowUnixMilli() tree := treeWithTimestamp{tlog.Tree{}, timestamp} - checkpoint, err := signTreeHead(config.Name, logID, config.Key, tree) + checkpoint, err := signTreeHead(config.Name, config.Key, tree) if err != nil { return fmt.Errorf("couldn't sign empty tree head: %w", err) } @@ -684,7 +683,7 @@ func (l *Log) sequencePool(ctx context.Context, p *pool) (err error) { } tree := treeWithTimestamp{Tree: tlog.Tree{N: n, Hash: rootHash}, Time: timestamp} - checkpoint, err := signTreeHead(l.c.Name, l.logID, l.c.Key, tree) + checkpoint, err := signTreeHead(l.c.Name, l.c.Key, tree) if err != nil { return fmtErrorf("couldn't sign checkpoint: %w", err) } @@ -742,7 +741,7 @@ var testingOnlyPauseSequencing func() // signTreeHead signs the tree and returns a checkpoint according to // c2sp.org/checkpoint. -func signTreeHead(name string, logID [sha256.Size]byte, privKey *ecdsa.PrivateKey, tree treeWithTimestamp) (checkpoint []byte, err error) { +func signTreeHead(name string, privKey *ecdsa.PrivateKey, tree treeWithTimestamp) (checkpoint []byte, err error) { sthBytes, err := ct.SerializeSTHSignatureInput(ct.SignedTreeHead{ Version: ct.V1, TreeSize: uint64(tree.N), @@ -773,10 +772,11 @@ func signTreeHead(name string, logID [sha256.Size]byte, privKey *ecdsa.PrivateKe return nil, fmtErrorf("couldn't encode RFC6962NoteSignature: %w", err) } - signer, err := tlogx.NewInjectedSigner(name, 0x05, logID[:], sig) + v, err := sunlight.NewRFC6962Verifier(name, privKey.Public(), nil) if err != nil { - return nil, fmtErrorf("couldn't construct signer: %w", err) + return nil, fmtErrorf("couldn't construct verifier: %w", err) } + signer := &injectedSigner{v, sig} signedNote, err := note.Sign(¬e.Note{ Text: sunlight.FormatCheckpoint(sunlight.Checkpoint{ Origin: name, @@ -789,6 +789,16 @@ func signTreeHead(name string, logID [sha256.Size]byte, privKey *ecdsa.PrivateKe return signedNote, nil } +type injectedSigner struct { + v note.Verifier + sig []byte +} + +func (s *injectedSigner) Sign(msg []byte) ([]byte, error) { return s.sig, nil } +func (s *injectedSigner) Name() string { return s.v.Name() } +func (s *injectedSigner) KeyHash() uint32 { return s.v.KeyHash() } +func (s *injectedSigner) Verifier() note.Verifier { return s.v } + // digitallySign produces an encoded digitally-signed signature. // // It reimplements tls.CreateSignature and tls.Marshal from diff --git a/internal/tlogx/logx.go b/internal/tlogx/logx.go deleted file mode 100644 index 8713978..0000000 --- a/internal/tlogx/logx.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found at -// https://go.googlesource.com/go/+/refs/heads/master/LICENSE. - -package tlogx - -import ( - "bytes" - "crypto/sha256" - "encoding/binary" - "fmt" - "strings" - "unicode" - "unicode/utf8" - - "golang.org/x/mod/sumdb/note" -) - -type verifier struct { - name string - hash uint32 - verify func(msg, sig []byte) bool -} - -func (v *verifier) Name() string { return v.name } -func (v *verifier) KeyHash() uint32 { return v.hash } -func (v *verifier) Verify(msg, sig []byte) bool { return v.verify(msg, sig) } - -// NewInjectedSigner constructs a new InjectedSigner that produces -// note signatures bearing the provided fixed value. -func NewInjectedSigner(name string, alg uint8, key, sig []byte) (*InjectedSigner, error) { - if !isValidName(name) { - return nil, fmt.Errorf("invalid name %q", name) - } - - s := &InjectedSigner{} - s.name = name - s.hash = keyHash(name, append([]byte{alg}, key...)) - s.sign = func(msg []byte) ([]byte, error) { - return sig, nil - } - s.verify = func(msg, s []byte) bool { - return bytes.Equal(s, sig) - } - - return s, nil -} - -type InjectedSigner struct { - verifier - sign func([]byte) ([]byte, error) -} - -var _ note.Signer = &InjectedSigner{} - -func (s *InjectedSigner) Sign(msg []byte) ([]byte, error) { return s.sign(msg) } -func (s *InjectedSigner) Verifier() note.Verifier { return &s.verifier } - -// isValidName reports whether name is valid. -// It must be non-empty and not have any Unicode spaces or pluses. -func isValidName(name string) bool { - return name != "" && utf8.ValidString(name) && strings.IndexFunc(name, unicode.IsSpace) < 0 && !strings.Contains(name, "+") -} - -func keyHash(name string, key []byte) uint32 { - h := sha256.New() - h.Write([]byte(name)) - h.Write([]byte("\n")) - h.Write(key) - sum := h.Sum(nil) - return binary.BigEndian.Uint32(sum) -}