diff --git a/internal/note/note_signer.go b/internal/note/note_signer.go index baf2981..3170839 100644 --- a/internal/note/note_signer.go +++ b/internal/note/note_signer.go @@ -93,18 +93,20 @@ func formatCosignatureV1(t uint64, msg []byte) ([]byte, error) { // origin line // NNNNNNNNN // tree hash + // ... // // where TTTTTTTTTT is the current UNIX timestamp, and the following - // three lines are the first three lines of the note. All other - // lines are not processed by the witness, so are not signed. + // lines are the lines of the note. + // + // While the witness signs all lines of the note, it's important to + // understand that the witness is asserting observation of correct + // append-only operation of the log based on the first three lines; + // no semantic statement is made about any extra "extension" lines. - lines := bytes.Split(msg, []byte("\n")) - if len(lines) < 3 { + if lines := bytes.Split(msg, []byte("\n")); len(lines) < 3 { return nil, errors.New("cosigned note format invalid") } - return []byte(fmt.Sprintf( - "cosignature/v1\ntime %d\n%s\n%s\n%s\n", - t, lines[0], lines[1], lines[2])), nil + return []byte(fmt.Sprintf("cosignature/v1\ntime %d\n%s", t, msg)), nil } var ( diff --git a/internal/note/note_signer_test.go b/internal/note/note_signer_test.go index 68bbf08..afb16ca 100644 --- a/internal/note/note_signer_test.go +++ b/internal/note/note_signer_test.go @@ -32,3 +32,47 @@ func TestSignerRoundtrip(t *testing.T) { t.Fatal(err) } } + +func TestVerifierInvalidSig(t *testing.T) { + skey, _, err := note.GenerateKey(rand.Reader, "test") + if err != nil { + t.Fatal(err) + } + + s, err := NewSignerForCosignatureV1(skey) + if err != nil { + t.Fatal(err) + } + + msg := "test\n123\nf+7CoKgXKE/tNys9TTXcr/ad6U/K3xvznmzew9y6SP0=\n" + if _, err := note.Sign(¬e.Note{Text: msg}, s); err != nil { + t.Fatal(err) + } + + if _, err := note.Open([]byte("nobbled"), note.VerifierList(s.Verifier())); err == nil { + t.Fatal("Verifier validated incorrect signature") + } +} + +func TestSigCoversExtensionLines(t *testing.T) { + skey, _, err := note.GenerateKey(rand.Reader, "test") + if err != nil { + t.Fatal(err) + } + + s, err := NewSignerForCosignatureV1(skey) + if err != nil { + t.Fatal(err) + } + + msg := "test\n123\nf+7CoKgXKE/tNys9TTXcr/ad6U/K3xvznmzew9y6SP0=\nExtendo\n" + n, err := note.Sign(¬e.Note{Text: msg}, s) + if err != nil { + t.Fatal(err) + } + + n[len(n)-2] = '@' + if _, err := note.Open(n, note.VerifierList(s.Verifier())); err == nil { + t.Fatal("Signature did not cover extension lines") + } +}