You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys/cmd/datekeys/present.go

280 lines
8.8 KiB

Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
package main
import (
"fmt"
"io"
"os"
"strings"
"time"
Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
"g.activething.com/go/DateKeys/capsule"
"g.activething.com/go/DateKeys/internal/pathrule"
)
// The labels of spec §29.7, which the official SDK must use.
const (
authorLabel = "autor declarado (texto del creador, sin comprobar):"
commentTitle = "Comentario del creador (sin comprobar)"
noteTitle = "Nota pública del creador (sin comprobar)"
Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// prefix goes before every piece of text of the creator. It counts 3
// columns: U+2502 is of ambiguous width, 2 columns in a CJK terminal.
prefix = "│ "
prefixWidth = 3
// defaultWidth is W when the output is not a terminal, and minWidth the
// least W ever used.
defaultWidth = 80
minWidth = 20
Review fixes: author keys, the writer, the CLI, extensions and the locator Fixes of the review of the session of 1 and 2 October that the text of spec v0.11 already asks for: - authorkey: String and GoString hide the secret key, which only Secret returns; ParsePublic refuses a key that is not a point of the curve (ed25519strict.OnCurve, checked against the square root of testkit). - capsule: a typed nil in AuthorKey, CMSSigner or Sealer is an error, never a capsule without the signature or the seal that was asked for. A panic while evaluating the signature or the seal fails only that part, F1 or S2, not both. OpenOptions.Accept sees the verdicts before step 18 and can refuse to publish the files. - extension.CheckWrite, the rule of encoders of spec 72: the writers of capsules and .dkk files refuse datekeys.note and datekeys.capsule outside the arrays where they are registered, or with invalid data. - CLI: encrypt -sign shows the author key and the code of AUTHOR_MESSAGE before it signs (rule 20); decrypt -expect-author compares the key of an F4 and writes nothing unless it matches; decrypt notifies a public note that it does not show; the lines of the verdicts break at the last space that fits, each row after the first behind a mark, so that the terminal never breaks them; L is the payload, not the content. - locator: a reader rejects an address that breaks 44.1 and keeps the others; addresses refuse the special-purpose blocks of IANA, IPv6 outside 2000::/3, localhost and local names, characters outside RFC 3986, dot segments, and a CID that does not decode to version 1 and a multihash; ParseInfo checks that the locator is an age file with one tlock stanza for the round of its DateKey; Info.Extension reads what it writes; its errors carry no normative code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
// contMark goes before each row of a line of the verdicts after its first.
// It counts 5 columns: U+21B3, like any code point that is not ASCII,
// counts 2.
contMark = " ↳ "
contMarkWidth = 5
// unusableNote is what a reader says of a public note that breaks the
// rules of text, which it does not show (spec v0.11, §24.1).
unusableNote = " La cápsula lleva una nota pública que no cumple las reglas de texto: no se muestra."
Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
)
// outputWidth is W for w (spec §29.7): the width of the terminal, or 80 when
// w is not one, and never less than 20.
func outputWidth(w io.Writer) int {
width := defaultWidth
if f, ok := w.(*os.File); ok {
if n, ok := termWidth(f); ok && n > 0 {
width = n
}
}
return max(width, minWidth)
}
// runeWidth counts the width of r by excess: 1 for printable ASCII, 2 for
// any other code point (spec §29.7).
func runeWidth(r rune) int {
if r >= 0x20 && r <= 0x7E {
return 1
}
return 2
}
// expandTabs turns each TAB of line into spaces up to the next column that
// is a multiple of 8, counting columns as runeWidth does.
func expandTabs(line string) string {
if !strings.Contains(line, "\t") {
return line
}
var b strings.Builder
col := 0
for _, r := range line {
if r == '\t' {
n := 8 - col%8
b.WriteString(strings.Repeat(" ", n))
col += n
continue
}
b.WriteRune(r)
col += runeWidth(r)
}
return b.String()
}
// pieces splits line into pieces of at most limit columns, each with at
// least one code point. An empty line is one empty piece.
func pieces(line string, limit int) []string {
var out []string
start, width := 0, 0
for i, r := range line {
w := runeWidth(r)
if width+w > limit && i > start {
out = append(out, line[start:i])
start, width = i, 0
}
width += w
}
return append(out, line[start:])
}
// writeCreator writes text of the creator, line by line, each line in
// pieces of at most W - 3 columns behind the prefix: no line of the creator
// is ever broken by the terminal or shown without the prefix, so none can
// pass for a line of the reader (spec §29.7).
func writeCreator(w io.Writer, text string, width int) {
for _, line := range strings.Split(text, "\n") {
for _, p := range pieces(expandTabs(line), width-prefixWidth) {
fmt.Fprintln(w, prefix+p)
}
}
}
Review fixes: author keys, the writer, the CLI, extensions and the locator Fixes of the review of the session of 1 and 2 October that the text of spec v0.11 already asks for: - authorkey: String and GoString hide the secret key, which only Secret returns; ParsePublic refuses a key that is not a point of the curve (ed25519strict.OnCurve, checked against the square root of testkit). - capsule: a typed nil in AuthorKey, CMSSigner or Sealer is an error, never a capsule without the signature or the seal that was asked for. A panic while evaluating the signature or the seal fails only that part, F1 or S2, not both. OpenOptions.Accept sees the verdicts before step 18 and can refuse to publish the files. - extension.CheckWrite, the rule of encoders of spec 72: the writers of capsules and .dkk files refuse datekeys.note and datekeys.capsule outside the arrays where they are registered, or with invalid data. - CLI: encrypt -sign shows the author key and the code of AUTHOR_MESSAGE before it signs (rule 20); decrypt -expect-author compares the key of an F4 and writes nothing unless it matches; decrypt notifies a public note that it does not show; the lines of the verdicts break at the last space that fits, each row after the first behind a mark, so that the terminal never breaks them; L is the payload, not the content. - locator: a reader rejects an address that breaks 44.1 and keeps the others; addresses refuse the special-purpose blocks of IANA, IPv6 outside 2000::/3, localhost and local names, characters outside RFC 3986, dot segments, and a CID that does not decode to version 1 and a multihash; ParseInfo checks that the locator is an age file with one tlock stanza for the round of its DateKey; Info.Extension reads what it writes; its errors carry no normative code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
// writeVerdicts writes lines of the reader, such as the verdicts, each in
// rows of at most W - 3 columns, and each row after the first behind
// contMark. The terminal never breaks one of them on its own, so no text that
// a certificate gives, inside a line, can start a row and pass for a verdict
// (spec §29.7).
func writeVerdicts(w io.Writer, lines []string, width int) {
for _, line := range lines {
for i, row := range rows(line, width-prefixWidth, width-prefixWidth-contMarkWidth) {
if i > 0 {
row = contMark + row
}
fmt.Fprintln(w, row)
}
}
}
// rows splits line into rows of at most first columns, the first one, and
// rest columns, the others. A row ends at the last space that fits after
// some text, and the break drops that space; only a word longer than a row
// is broken inside, after the last code point that fits.
func rows(line string, first, rest int) []string {
var out []string
limit := first
for {
end, width, lastSpace, text := len(line), 0, -1, false
for i, r := range line {
w := runeWidth(r)
if width+w > limit && i > 0 {
end = i
break
}
if r == ' ' && text {
lastSpace = i
}
text = text || r != ' '
width += w
}
if end == len(line) {
return append(out, line)
}
cut, next := end, end
switch {
case line[end] == ' ':
next = end + 1
case lastSpace > 0:
cut, next = lastSpace, lastSpace+1
}
out = append(out, line[:cut])
line, limit = line[next:], rest
}
}
Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
// present shows what a format 3 capsule holds, after step 18, as spec §29.7
// says: the verdicts first, then the declared author and the comment as
// text of the creator that nobody has checked, then the paths of the files
// written to dir, with a warning after those that are risky to open, and the
// verdicts again at the end.
func present(w io.Writer, o *capsule.Opened, dir string, width int) {
verdicts := o.Verdicts.Lines()
Review fixes: author keys, the writer, the CLI, extensions and the locator Fixes of the review of the session of 1 and 2 October that the text of spec v0.11 already asks for: - authorkey: String and GoString hide the secret key, which only Secret returns; ParsePublic refuses a key that is not a point of the curve (ed25519strict.OnCurve, checked against the square root of testkit). - capsule: a typed nil in AuthorKey, CMSSigner or Sealer is an error, never a capsule without the signature or the seal that was asked for. A panic while evaluating the signature or the seal fails only that part, F1 or S2, not both. OpenOptions.Accept sees the verdicts before step 18 and can refuse to publish the files. - extension.CheckWrite, the rule of encoders of spec 72: the writers of capsules and .dkk files refuse datekeys.note and datekeys.capsule outside the arrays where they are registered, or with invalid data. - CLI: encrypt -sign shows the author key and the code of AUTHOR_MESSAGE before it signs (rule 20); decrypt -expect-author compares the key of an F4 and writes nothing unless it matches; decrypt notifies a public note that it does not show; the lines of the verdicts break at the last space that fits, each row after the first behind a mark, so that the terminal never breaks them; L is the payload, not the content. - locator: a reader rejects an address that breaks 44.1 and keeps the others; addresses refuse the special-purpose blocks of IANA, IPv6 outside 2000::/3, localhost and local names, characters outside RFC 3986, dot segments, and a CID that does not decode to version 1 and a multihash; ParseInfo checks that the locator is an age file with one tlock stanza for the round of its DateKey; Info.Extension reads what it writes; its errors carry no normative code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
writeVerdicts(w, verdicts, width)
Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
h := o.Head
// Spec v0.11 §29.7: under a valid seal, a modification time later than the
// instant of the seal is shown as an inconsistency.
if t, ok := o.Verdicts.SealedAt(); ok {
for _, f := range h.Files {
if f.HasMTime && time.Unix(int64(f.MTime), 0).After(t) {
Review fixes: author keys, the writer, the CLI, extensions and the locator Fixes of the review of the session of 1 and 2 October that the text of spec v0.11 already asks for: - authorkey: String and GoString hide the secret key, which only Secret returns; ParsePublic refuses a key that is not a point of the curve (ed25519strict.OnCurve, checked against the square root of testkit). - capsule: a typed nil in AuthorKey, CMSSigner or Sealer is an error, never a capsule without the signature or the seal that was asked for. A panic while evaluating the signature or the seal fails only that part, F1 or S2, not both. OpenOptions.Accept sees the verdicts before step 18 and can refuse to publish the files. - extension.CheckWrite, the rule of encoders of spec 72: the writers of capsules and .dkk files refuse datekeys.note and datekeys.capsule outside the arrays where they are registered, or with invalid data. - CLI: encrypt -sign shows the author key and the code of AUTHOR_MESSAGE before it signs (rule 20); decrypt -expect-author compares the key of an F4 and writes nothing unless it matches; decrypt notifies a public note that it does not show; the lines of the verdicts break at the last space that fits, each row after the first behind a mark, so that the terminal never breaks them; L is the payload, not the content. - locator: a reader rejects an address that breaks 44.1 and keeps the others; addresses refuse the special-purpose blocks of IANA, IPv6 outside 2000::/3, localhost and local names, characters outside RFC 3986, dot segments, and a CID that does not decode to version 1 and a multihash; ParseInfo checks that the locator is an age file with one tlock stanza for the round of its DateKey; Info.Extension reads what it writes; its errors carry no normative code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
writeVerdicts(w, []string{fmt.Sprintf(" aviso: la fecha de modificación de un fichero es posterior al sello (%s): no es coherente.", t.UTC().Format(time.RFC3339))}, width)
break
}
}
}
if o.Inspection != nil && o.Inspection.Header != nil {
if note, ok := o.Inspection.Header.PublicNote(); ok {
fmt.Fprintln(w, "┌ "+noteTitle)
writeCreator(w, note, width)
fmt.Fprintln(w, "└")
Review fixes: author keys, the writer, the CLI, extensions and the locator Fixes of the review of the session of 1 and 2 October that the text of spec v0.11 already asks for: - authorkey: String and GoString hide the secret key, which only Secret returns; ParsePublic refuses a key that is not a point of the curve (ed25519strict.OnCurve, checked against the square root of testkit). - capsule: a typed nil in AuthorKey, CMSSigner or Sealer is an error, never a capsule without the signature or the seal that was asked for. A panic while evaluating the signature or the seal fails only that part, F1 or S2, not both. OpenOptions.Accept sees the verdicts before step 18 and can refuse to publish the files. - extension.CheckWrite, the rule of encoders of spec 72: the writers of capsules and .dkk files refuse datekeys.note and datekeys.capsule outside the arrays where they are registered, or with invalid data. - CLI: encrypt -sign shows the author key and the code of AUTHOR_MESSAGE before it signs (rule 20); decrypt -expect-author compares the key of an F4 and writes nothing unless it matches; decrypt notifies a public note that it does not show; the lines of the verdicts break at the last space that fits, each row after the first behind a mark, so that the terminal never breaks them; L is the payload, not the content. - locator: a reader rejects an address that breaks 44.1 and keeps the others; addresses refuse the special-purpose blocks of IANA, IPv6 outside 2000::/3, localhost and local names, characters outside RFC 3986, dot segments, and a CID that does not decode to version 1 and a multihash; ParseInfo checks that the locator is an age file with one tlock stanza for the round of its DateKey; Info.Extension reads what it writes; its errors carry no normative code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
} else if o.Inspection.Header.UnusableNote() {
writeVerdicts(w, []string{unusableNote}, width)
}
}
Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
if h.Author != "" {
fmt.Fprintln(w, authorLabel)
writeCreator(w, h.Author, width)
}
if h.Comment != "" {
fmt.Fprintln(w, "┌ "+commentTitle)
writeCreator(w, h.Comment, width)
fmt.Fprintln(w, "└")
}
if len(h.Files) > 0 {
fmt.Fprintf(w, "Ficheros escritos en %s (%d):\n", dir, len(h.Files))
for _, f := range h.Files {
writeCreator(w, f.Path, width)
for _, warning := range risks(f.Path) {
fmt.Fprintln(w, " aviso: "+warning)
}
}
}
Review fixes: author keys, the writer, the CLI, extensions and the locator Fixes of the review of the session of 1 and 2 October that the text of spec v0.11 already asks for: - authorkey: String and GoString hide the secret key, which only Secret returns; ParsePublic refuses a key that is not a point of the curve (ed25519strict.OnCurve, checked against the square root of testkit). - capsule: a typed nil in AuthorKey, CMSSigner or Sealer is an error, never a capsule without the signature or the seal that was asked for. A panic while evaluating the signature or the seal fails only that part, F1 or S2, not both. OpenOptions.Accept sees the verdicts before step 18 and can refuse to publish the files. - extension.CheckWrite, the rule of encoders of spec 72: the writers of capsules and .dkk files refuse datekeys.note and datekeys.capsule outside the arrays where they are registered, or with invalid data. - CLI: encrypt -sign shows the author key and the code of AUTHOR_MESSAGE before it signs (rule 20); decrypt -expect-author compares the key of an F4 and writes nothing unless it matches; decrypt notifies a public note that it does not show; the lines of the verdicts break at the last space that fits, each row after the first behind a mark, so that the terminal never breaks them; L is the payload, not the content. - locator: a reader rejects an address that breaks 44.1 and keeps the others; addresses refuse the special-purpose blocks of IANA, IPv6 outside 2000::/3, localhost and local names, characters outside RFC 3986, dot segments, and a CID that does not decode to version 1 and a multihash; ParseInfo checks that the locator is an age file with one tlock stanza for the round of its DateKey; Info.Extension reads what it writes; its errors carry no normative code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
writeVerdicts(w, verdicts, width)
Format 3, step 5: the CLI datekeys encrypt writes format 3 and datekeys decrypt writes its files to a new folder, with the presentation of spec 29.7. - encrypt: -in is repeatable and takes files and folders; a folder gives its name as the first segment, as a browser does, and is walked with Lstat, following no link, taking regular files only. .DS_Store, Thumbs.db, desktop.ini, ._* and __MACOSX are left out of folders, and each one left out is reported (62.1 rule 15). New -comment, -author and -no-mtime; the mtimes are kept by default (rule 16). A capsule may hold a comment alone. The copy of a pipe to a temporary file goes, as only regular files are taken. - decrypt: the prelude decides. Format 3 claims -out with os.Mkdir, only when there are files, stages the tree in -out/.datekeys-* through an os.Root with O_EXCL and mode 0600, sets the mtimes, and moves each entry of the first level into place at step 18; any failure removes the folder (spec 56). Formats 1 and 2 still write a file. - The presentation goes to stdout: the verdicts, the declared author and the comment box with their labels, the paths, and the verdicts again. Every line of the creator goes in pieces of at most W - 3 columns behind the prefix, counting 2 for anything but printable ASCII, with its TABs expanded to multiples of 8; W is the width of the terminal, asked with syscall on Unix and Windows, or 80. Risky names get a warning: shortcuts, desktop.ini, .git, programs and a leading dash, compared by their key of R7. - Encrypt no longer runs in the CLI: only the test data generators set TestVectors. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 week ago
}
// The names that spec §29.7 asks a reader to warn of, compared by their key
// of R7, so that ".GIT" or "Informe.LNK" warn too.
var (
shortcutExts = keys(".lnk", ".url", ".library-ms", ".searchConnector-ms")
programExts = keys(".exe", ".com", ".bat", ".cmd", ".scr", ".pif", ".msi", ".msp", ".cpl", ".hta",
".jar", ".js", ".jse", ".vbs", ".vbe", ".wsf", ".wsh", ".ps1", ".psm1", ".reg", ".sh", ".command", ".app")
desktopINI = pathrule.Key("desktop.ini")
gitDir = pathrule.Key(".git")
)
func keys(names ...string) map[string]bool {
m := make(map[string]bool, len(names))
for _, n := range names {
m[pathrule.Key(n)] = true
}
return m
}
// risks returns the warnings for path: a Windows shortcut or folder
// setting, a .git folder, a program, or a segment that starts with '-'.
func risks(path string) []string {
var out []string
segs := strings.Split(path, "/")
for i, s := range segs {
k := pathrule.Key(s)
switch {
case k == gitDir && i < len(segs)-1:
out = append(out, "está dentro de una carpeta .git, cuyos ganchos pueden ejecutar órdenes")
case k == gitDir:
out = append(out, "se llama .git y puede apuntar a otro repositorio")
case k == desktopINI:
out = append(out, "es la configuración de una carpeta de Windows")
}
if strings.HasPrefix(s, "-") {
out = append(out, "un nombre que empieza por '-' puede tomarse por una opción en una orden")
}
}
last := segs[len(segs)-1]
if dot := strings.LastIndexByte(last, '.'); dot > 0 {
switch ext := pathrule.Key(last[dot:]); {
case shortcutExts[ext]:
out = append(out, "es un acceso directo de Windows: puede abrir otro programa o una dirección")
case programExts[ext]:
out = append(out, "es un programa o un script: no lo ejecutes sin saber qué hace")
}
}
return out
}
// showNote shows the public note of an inspected capsule as spec v0.11 §24.1
// and §29.7 ask: as text of the creator that nobody has checked, with the
// prefix and the wrapping of any text of the creator, and, before the date,
// the warning that nobody can check who made the capsule or whether it is
// signed. A note that breaks the rules of text is not shown, and the person
// is told. It shows the note even when the capsule fails a check: that is
// when a forged one is most likely.
func showNote(w io.Writer, in *capsule.Inspection) {
if in == nil || in.Header == nil {
return
}
note, ok := in.Header.PublicNote()
if !ok {
Review fixes: author keys, the writer, the CLI, extensions and the locator Fixes of the review of the session of 1 and 2 October that the text of spec v0.11 already asks for: - authorkey: String and GoString hide the secret key, which only Secret returns; ParsePublic refuses a key that is not a point of the curve (ed25519strict.OnCurve, checked against the square root of testkit). - capsule: a typed nil in AuthorKey, CMSSigner or Sealer is an error, never a capsule without the signature or the seal that was asked for. A panic while evaluating the signature or the seal fails only that part, F1 or S2, not both. OpenOptions.Accept sees the verdicts before step 18 and can refuse to publish the files. - extension.CheckWrite, the rule of encoders of spec 72: the writers of capsules and .dkk files refuse datekeys.note and datekeys.capsule outside the arrays where they are registered, or with invalid data. - CLI: encrypt -sign shows the author key and the code of AUTHOR_MESSAGE before it signs (rule 20); decrypt -expect-author compares the key of an F4 and writes nothing unless it matches; decrypt notifies a public note that it does not show; the lines of the verdicts break at the last space that fits, each row after the first behind a mark, so that the terminal never breaks them; L is the payload, not the content. - locator: a reader rejects an address that breaks 44.1 and keeps the others; addresses refuse the special-purpose blocks of IANA, IPv6 outside 2000::/3, localhost and local names, characters outside RFC 3986, dot segments, and a CID that does not decode to version 1 and a multihash; ParseInfo checks that the locator is an age file with one tlock stanza for the round of its DateKey; Info.Extension reads what it writes; its errors carry no normative code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 days ago
if in.Header.UnusableNote() {
fmt.Fprintln(w, unusableNote)
}
return
}
fmt.Fprintln(w, "┌ "+noteTitle)
writeCreator(w, note, outputWidth(w))
fmt.Fprintln(w, "└")
fmt.Fprintln(w, " Nadie puede comprobar antes de la fecha quién creó la cápsula ni si va firmada.")
}

Powered by TurnKey Linux.