Author SHA1 Message Date
GitHub Actions b662811909 doc: regenerate groff and html man pages 2026-08-28 21:20:09 +00:00
Filippo Valsorda 5f603b5057 all: update dependencies and GitHub Actions
Closes #736
Fixes #731
2026-08-28 23:16:03 +02:00
Filippo Valsorda a68b8e921b README: add dependencies badge 2026-08-28 23:06:33 +02:00
Steve WeisandClaude 706dfc1e79 all: minor cleanups (#700)
Replace two hand-rolled slicesEqual helpers with slices.Equal from
the standard library, which is already imported in age.go.
(age.go:211-221, plugin/plugin.go:666-676)

Fix godoc link typo [Indentity] -> [Identity].
(plugin/plugin.go:3)

Fix comment typo "not MinPayload" -> "so MinPayload".
(internal/inspect/inspect.go:25)

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-20 22:12:32 +01:00
Steve WeisandClaude 4c86929a84 internal/format: return correct byte count from writeWrapped (#698)
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-20 22:02:09 +01:00
Steve WeisandClaude db09cd66d1 internal/inspect: fix tag stanza type names in post-quantum classifier (#695)
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-20 21:49:27 +01:00
Filippo Valsorda 4a3a4ef00a SIGSUM.md: extend release playbook 2026-02-02 17:31:01 +01:00
Filippo Valsorda 10561a774f .github/workflows: remove one-off darwin/amd64 backfill workflow
Updates #676
2026-01-21 18:56:39 +01:00
Filippo Valsorda c918a2c113 .github/workflows: add darwin/amd64 backfill workflow
Updates #676
2026-01-21 18:49:52 +01:00
Filippo Valsorda beb5dfa28c .github/workflows: add darwin/amd64 build target
Closes #676
2026-01-21 18:49:46 +01:00
Filippo Valsorda 0293aca1d7 SIGSUM.md: add release playbook
Updates #617
2025-12-31 16:19:37 +01:00
GitHub Actions e7601d8a67 doc: regenerate groff and html man pages 2025-12-31 11:05:09 +00:00
brettwhiteinc acfa73142b doc: fix post-quantum example in age-keygen manpage (#675) 2025-12-31 12:03:49 +01:00
21 changed files with 138 additions and 93 deletions

No files matched your search

+9 -8
View File
@@ -17,16 +17,17 @@ jobs:
- {GOOS: linux, GOARCH: arm, GOARM: 6}
- {GOOS: linux, GOARCH: arm64}
- {GOOS: darwin, GOARCH: arm64}
- {GOOS: darwin, GOARCH: amd64}
- {GOOS: windows, GOARCH: amd64}
- {GOOS: freebsd, GOARCH: amd64}
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- name: Install Go
uses: actions/setup-go@v6
uses: actions/setup-go@v7
with:
go-version-file: go.mod
cache: false
@@ -61,7 +62,7 @@ jobs:
GOARCH: ${{ matrix.GOARCH }}
GOARM: ${{ matrix.GOARM }}
- name: Upload workflow artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: age-artifacts-${{ matrix.GOOS }}-${{ matrix.GOARCH }}
path: age-*
@@ -70,12 +71,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v7
with:
fetch-depth: 0
persist-credentials: false
- name: Install Go
uses: actions/setup-go@v6
uses: actions/setup-go@v7
with:
go-version-file: go.mod
cache: false
@@ -93,7 +94,7 @@ jobs:
done
tar -cvzf "age-$VERSION-source.tar.gz" -C "$DIR" age
- name: Upload workflow artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: age-artifacts-source
path: age-*-source.tar.gz
@@ -108,12 +109,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download workflow artifacts
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
pattern: age-artifacts-*
merge-multiple: true
- name: Generate artifacts attestation
uses: actions/attest-build-provenance@v3
uses: actions/attest-build-provenance@v4
with:
subject-path: age-*
- name: Upload release artifacts
+5 -5
View File
@@ -13,10 +13,10 @@ jobs:
name: Ronn
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: geomys/sandboxed-step@v1.2.1
- uses: geomys/sandboxed-step@v1.2.2
with:
persist-workspace-changes: true
run: |
@@ -29,7 +29,7 @@ jobs:
awk '/Filippo Valsorda/ { $0 = "<p>Filippo Valsorda <a href=\"mailto:age@filippo.io\" data-bare-link=\"true\">age@filippo.io</a></p>" } { print }' "$f" > "$f.tmp"
mv "$f.tmp" "$f"
done
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: man-pages
path: |
@@ -42,10 +42,10 @@ jobs:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
with:
persist-credentials: true
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
name: man-pages
path: doc/
+11 -11
View File
@@ -21,10 +21,10 @@ jobs:
- windows-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-go@v6
- uses: actions/setup-go@v7
with:
go-version: ${{ matrix.go.go-version }}
- run: |
@@ -38,13 +38,13 @@ jobs:
- { go-version: stable }
- { go-version: oldstable }
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-go@v6
- uses: actions/setup-go@v7
with:
go-version: ${{ matrix.go.go-version }}
- uses: geomys/sandboxed-step@v1.2.1
- uses: geomys/sandboxed-step@v1.2.2
with:
run: |
go get -u -t ./...
@@ -52,24 +52,24 @@ jobs:
staticcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-go@v6
- uses: actions/setup-go@v7
with:
go-version: stable
- uses: geomys/sandboxed-step@v1.2.1
- uses: geomys/sandboxed-step@v1.2.2
with:
run: go run honnef.co/go/tools/cmd/staticcheck@latest ./...
govulncheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-go@v6
- uses: actions/setup-go@v7
with:
go-version: stable
- uses: geomys/sandboxed-step@v1.2.1
- uses: geomys/sandboxed-step@v1.2.2
with:
run: go run golang.org/x/vuln/cmd/govulncheck@latest ./...
+2 -1
View File
@@ -7,6 +7,7 @@
</p>
[![Go Reference](https://pkg.go.dev/badge/filippo.io/age.svg)](https://pkg.go.dev/filippo.io/age)
[![Dependencies](https://badges.api.sourcespotter.com/deps?firstparty=filippo.io&package=filippo.io%2Fage)](https://sourcespotter.com/deps/?firstparty=filippo.io&package=filippo.io%2Fage)
[![man page](<https://img.shields.io/badge/age(1)-man%20page-lightgrey>)](https://filippo.io/age/age.1)
[![C2SP specification](https://img.shields.io/badge/%C2%A7%23-specification-blueviolet)](https://age-encryption.org/v1)
@@ -151,7 +152,7 @@ On Windows, Linux, macOS, and FreeBSD you can use the pre-built binaries.
```
https://dl.filippo.io/age/latest?for=linux/amd64
https://dl.filippo.io/age/v1.3.0?for=darwin/arm64
https://dl.filippo.io/age/v1.3.1?for=darwin/arm64
...
```
+23 -3
View File
@@ -11,13 +11,33 @@ ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM1WpnEswJLPzvXJDiswowy48U+G+G1kmgwUE2eaRHZG
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAz2WM5CyPLqiNjk7CLl4roDXwKhQ0QExXLebukZEZFS
EOF
curl -JLO "https://dl.filippo.io/age/v1.3.0?for=darwin/arm64"
curl -JLO "https://dl.filippo.io/age/v1.3.0?for=darwin/arm64&proof"
curl -JLO "https://dl.filippo.io/age/v1.3.1?for=darwin/arm64"
curl -JLO "https://dl.filippo.io/age/v1.3.1?for=darwin/arm64&proof"
go install sigsum.org/sigsum-go/cmd/sigsum-verify@v0.13.1
sigsum-verify -k age-sigsum-key.pub -P sigsum-generic-2025-1 \
age-v1.3.0-darwin-arm64.tar.gz.proof < age-v1.3.0-darwin-arm64.tar.gz
age-v1.3.1-darwin-arm64.tar.gz.proof < age-v1.3.1-darwin-arm64.tar.gz
```
You can learn more about what's happening above in the [Sigsum
docs](https://www.sigsum.org/getting-started/).
### Release playbook
Dear future me, to sign a new release and produce Sigsum proofs, run the following
```
VERSION=v1.3.1
go install sigsum.org/sigsum-go/cmd/sigsum-verify@latest
go install github.com/tillitis/tkey-ssh-agent/cmd/tkey-ssh-agent@main
tkey-ssh-agent --agent-socket tkey-ssh-agent.sock --uss
passage -c other/tkey-ssh-sigsum-age
SSH_AUTH_SOCK=tkey-ssh-agent.sock ssh-add -L > tkey-ssh-agent.pub
passage other/sigsum-ratelimit > sigsum-ratelimit
gh release download $VERSION --repo FiloSottile/age --dir artifacts/
SSH_AUTH_SOCK=tkey-ssh-agent.sock sigsum-submit -k tkey-ssh-agent.pub -P sigsum-generic-2025-1 -a sigsum-ratelimit -d filippo.io artifacts/*
gh release upload $VERSION --repo FiloSottile/age artifacts/*.proof
```
In the future, we will move to reproducing the artifacts locally, and signing
those instead of the ones built by GitHub Actions.
+1 -13
View File
@@ -130,7 +130,7 @@ func encryptHdr(fileKey []byte, recipients ...Recipient) (*format.Header, error)
sort.Strings(l)
if i == 0 {
labels = l
} else if !slicesEqual(labels, l) {
} else if !slices.Equal(labels, l) {
return nil, incompatibleLabelsError(labels, l)
}
for _, s := range stanzas {
@@ -208,18 +208,6 @@ func wrapWithLabels(r Recipient, fileKey []byte) (s []*Stanza, labels []string,
return
}
func slicesEqual(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
}
for i := range s1 {
if s1[i] != s2[i] {
return false
}
}
return true
}
func incompatibleLabelsError(l1, l2 []string) error {
hasPQ1 := slices.Contains(l1, "postquantum")
hasPQ2 := slices.Contains(l2, "postquantum")
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.9.1
.\" http://github.com/apjanke/ronn-ng/tree/0.9.1
.TH "AGE\-INSPECT" "1" "December 2025" ""
.TH "AGE\-INSPECT" "1" "August 2026" ""
.SH "NAME"
\fBage\-inspect\fR \- inspect age(1) encrypted files
.SH "SYNOPSIS"
+1 -1
View File
@@ -195,7 +195,7 @@ Tip: for machine-readable output, use --json.
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>December 2025</li>
<li class='tc'>August 2026</li>
<li class='tr'>age-inspect(1)</li>
</ol>
+2 -2
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.9.1
.\" http://github.com/apjanke/ronn-ng/tree/0.9.1
.TH "AGE\-KEYGEN" "1" "December 2025" ""
.TH "AGE\-KEYGEN" "1" "August 2026" ""
.SH "NAME"
\fBage\-keygen\fR \- generate age(1) key pairs
.SH "SYNOPSIS"
@@ -53,7 +53,7 @@ AGE\-SECRET\-KEY\-1N9JEPW6DWJ0ZQUDX63F5A03GX8QUW7PXDE39N8UYF82VZ9PC8UFS3M7XA9
Write a new post\-quantum identity to \fBkey\.txt\fR:
.IP "" 4
.nf
$ age\-keygen \-o key\.txt
$ age\-keygen \-pq \-o key\.txt
Public key: age1pq1cd[\|\.\|\.\|\. 1950 more characters \|\.\|\.\|\.]
.fi
.IP "" 0
+2 -2
View File
@@ -130,7 +130,7 @@ AGE-SECRET-KEY-1N9JEPW6DWJ0ZQUDX63F5A03GX8QUW7PXDE39N8UYF82VZ9PC8UFS3M7XA9
<p>Write a new post-quantum identity to <code>key.txt</code>:</p>
<pre><code>$ age-keygen -o key.txt
<pre><code>$ age-keygen -pq -o key.txt
Public key: age1pq1cd[... 1950 more characters ...]
</code></pre>
@@ -150,7 +150,7 @@ age1pq1cd[... 1950 more characters ...]
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>December 2025</li>
<li class='tc'>August 2026</li>
<li class='tr'>age-keygen(1)</li>
</ol>
+1 -1
View File
@@ -52,7 +52,7 @@ Generate a new traditional identity:
Write a new post-quantum identity to `key.txt`:
$ age-keygen -o key.txt
$ age-keygen -pq -o key.txt
Public key: age1pq1cd[... 1950 more characters ...]
Convert an identity to a recipient:
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.9.1
.\" http://github.com/apjanke/ronn-ng/tree/0.9.1
.TH "AGE\-PLUGIN\-BATCHPASS" "1" "December 2025" ""
.TH "AGE\-PLUGIN\-BATCHPASS" "1" "August 2026" ""
.SH "NAME"
\fBage\-plugin\-batchpass\fR \- non\-interactive passphrase encryption plugin for age(1)
.SH "SYNOPSIS"
+1 -1
View File
@@ -174,7 +174,7 @@ persisted in the shell history or leaked to other users on multi-user systems.</
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>December 2025</li>
<li class='tc'>August 2026</li>
<li class='tr'>age-plugin-batchpass(1)</li>
</ol>
+1 -1
View File
@@ -1,6 +1,6 @@
.\" generated with Ronn-NG/v0.9.1
.\" http://github.com/apjanke/ronn-ng/tree/0.9.1
.TH "AGE" "1" "December 2025" ""
.TH "AGE" "1" "August 2026" ""
.SH "NAME"
\fBage\fR \- simple, modern, and secure file encryption
.SH "SYNOPSIS"
+1 -1
View File
@@ -461,7 +461,7 @@ $ age -d -i age-yubikey-identity-388178f3.txt secrets.txt.age
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>December 2025</li>
<li class='tc'>August 2026</li>
<li class='tr'>age(1)</li>
</ol>
+9 -9
View File
@@ -1,22 +1,22 @@
module filippo.io/age
go 1.24.0
go 1.25.0
// Release build version.
toolchain go1.25.5
toolchain go1.27.0
require (
filippo.io/edwards25519 v1.1.0
filippo.io/edwards25519 v1.2.0
filippo.io/hpke v0.4.0
filippo.io/nistec v0.0.4
golang.org/x/crypto v0.45.0
golang.org/x/sys v0.38.0
golang.org/x/term v0.37.0
golang.org/x/crypto v0.55.0
golang.org/x/sys v0.47.0
golang.org/x/term v0.45.0
)
// Test dependencies.
require (
c2sp.org/CCTV/age v0.0.0-20251208015420-e9274a7bdbfd
github.com/rogpeppe/go-internal v1.14.1
golang.org/x/tools v0.39.0 // indirect
c2sp.org/CCTV/age v0.0.0-20260605191406-1e3d2860d46e
github.com/rogpeppe/go-internal v1.16.0
golang.org/x/tools v0.49.0 // indirect
)
+14 -14
View File
@@ -1,18 +1,18 @@
c2sp.org/CCTV/age v0.0.0-20251208015420-e9274a7bdbfd h1:ZLsPO6WdZ5zatV4UfVpr7oAwLGRZ+sebTUruuM4Ra3M=
c2sp.org/CCTV/age v0.0.0-20251208015420-e9274a7bdbfd/go.mod h1:SrHC2C7r5GkDk8R+NFVzYy/sdj0Ypg9htaPXQq5Cqeo=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
c2sp.org/CCTV/age v0.0.0-20260605191406-1e3d2860d46e h1:N9DpijOhcuCLIlgcX/6qhBQeMQIlBxsVQITjbpJaBso=
c2sp.org/CCTV/age v0.0.0-20260605191406-1e3d2860d46e/go.mod h1:SrHC2C7r5GkDk8R+NFVzYy/sdj0Ypg9htaPXQq5Cqeo=
filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo=
filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc=
filippo.io/hpke v0.4.0 h1:p575VVQ6ted4pL+it6M00V/f2qTZITO0zgmdKCkd5+A=
filippo.io/hpke v0.4.0/go.mod h1:EmAN849/P3qdeK+PCMkDpDm83vRHM5cDipBJ8xbQLVY=
filippo.io/nistec v0.0.4 h1:F14ZHT5htWlMnQVPndX9ro9arf56cBhQxq4LnDI491s=
filippo.io/nistec v0.0.4/go.mod h1:PK/lw8I1gQT4hUML4QGaqljwdDaFcMyFKSXN7kjrtKI=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M=
golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis=
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
+2 -1
View File
@@ -76,6 +76,7 @@ func (w *WrappedBase64Encoder) writeWrapped(p []byte) (int, error) {
if w.buf.Len() != 0 {
panic("age: internal error: non-empty WrappedBase64Encoder.buf")
}
total := len(p)
for len(p) > 0 {
toWrite := min(ColumnsPerLine-(w.written%ColumnsPerLine), len(p))
n, _ := w.buf.Write(p[:toWrite])
@@ -91,7 +92,7 @@ func (w *WrappedBase64Encoder) writeWrapped(p []byte) (int, error) {
// are not recoverable anyway.
return 0, err
}
return len(p), nil
return total, nil
}
// LastLineIsEmpty returns whether the last output line was empty, either
+3 -3
View File
@@ -21,7 +21,7 @@ type Metadata struct {
Header int64 `json:"header"`
Armor int64 `json:"armor"`
Overhead int64 `json:"overhead"`
// Currently, we don't do any padding, not MinPayload == MaxPayload and
// Currently, we don't do any padding, so MinPayload == MaxPayload and
// MinPadding == MaxPadding == 0, but that might change in the future.
MinPayload int64 `json:"min_payload"`
MaxPayload int64 `json:"max_payload"`
@@ -61,9 +61,9 @@ func Inspect(r io.Reader, fileSize int64) (*Metadata, error) {
for _, s := range hdr.Recipients {
data.StanzaTypes = append(data.StanzaTypes, s.Type)
switch s.Type {
case "X25519", "ssh-rsa", "ssh-ed25519", "age-encryption.org/p256tag", "piv-p256":
case "X25519", "ssh-rsa", "ssh-ed25519", "p256tag", "piv-p256":
data.Postquantum = "no"
case "mlkem768x25519", "scrypt", "age-encryption.org/mlkem768p256tag":
case "mlkem768x25519", "scrypt", "mlkem768p256tag":
if data.Postquantum != "no" {
data.Postquantum = "yes"
}
+45
View File
@@ -1,12 +1,57 @@
package inspect
import (
"bytes"
"fmt"
"testing"
"filippo.io/age/internal/format"
"filippo.io/age/internal/stream"
)
// buildFile serializes a header with a single stanza of the given type,
// followed by the minimal valid encrypted payload (a 16-byte stream nonce
// and a single empty ChaCha20-Poly1305 chunk).
func buildFile(t *testing.T, stanzaType string) []byte {
t.Helper()
hdr := &format.Header{
Recipients: []*format.Stanza{{Type: stanzaType}},
MAC: make([]byte, 32),
}
buf := &bytes.Buffer{}
if err := hdr.Marshal(buf); err != nil {
t.Fatalf("Header.Marshal: %v", err)
}
// Append nonce (16 bytes) + poly1305 tag for empty chunk (16 bytes).
buf.Write(make([]byte, 16+16))
return buf.Bytes()
}
func TestInspectTagStanzas(t *testing.T) {
tests := []struct {
stanzaType string
want string
}{
{stanzaType: "p256tag", want: "no"},
{stanzaType: "mlkem768p256tag", want: "yes"},
}
for _, tt := range tests {
t.Run(tt.stanzaType, func(t *testing.T) {
f := buildFile(t, tt.stanzaType)
md, err := Inspect(bytes.NewReader(f), int64(len(f)))
if err != nil {
t.Fatalf("Inspect: %v", err)
}
if got := md.Postquantum; got != tt.want {
t.Errorf("Postquantum = %q, want %q", got, tt.want)
}
if len(md.StanzaTypes) != 1 || md.StanzaTypes[0] != tt.stanzaType {
t.Errorf("StanzaTypes = %v, want [%q]", md.StanzaTypes, tt.stanzaType)
}
})
}
}
func TestStreamOverhead(t *testing.T) {
tests := []struct {
payloadSize int64
+3 -14
View File
@@ -1,6 +1,6 @@
// Package plugin implements the age plugin protocol.
//
// [Recipient] and [Indentity] are plugin clients, that execute plugin binaries to
// [Recipient] and [Identity] are plugin clients, that execute plugin binaries to
// perform encryption and decryption operations.
//
// [Plugin] is a framework for writing age plugins, that exposes an [age.Recipient]
@@ -14,6 +14,7 @@ import (
"fmt"
"io"
"os"
"slices"
"strconv"
"filippo.io/age"
@@ -358,7 +359,7 @@ func wrapWithLabels(r age.Recipient, fileKey []byte) ([]*age.Stanza, []string, e
}
func checkLabels(ll, labels []string) error {
if !slicesEqual(ll, labels) {
if !slices.Equal(ll, labels) {
return fmt.Errorf("labels %q do not match previous recipients %q", ll, labels)
}
return nil
@@ -662,15 +663,3 @@ func (p *Plugin) writeError(args []string, err error) error {
}
return nil
}
func slicesEqual(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
}
for i := range s1 {
if s1[i] != s2[i] {
return false
}
}
return true
}