Skip to content

Commit 9f49b46

Browse files
committed
cmd/age-plugin-tag,cmd/age-plugin-tagpq: new backward compatibility plugins
1 parent 8525d9b commit 9f49b46

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

cmd/age-plugin-tag/plugin-tag.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"log"
7+
"os"
8+
9+
"filippo.io/age"
10+
"filippo.io/age/plugin"
11+
"filippo.io/age/tag"
12+
)
13+
14+
const usage = `age-plugin-tag is an age plugin for P-256 tagged recipients. These are supported
15+
natively by age v1.3.0 and later, but this plugin can be placed in $PATH to add
16+
support to any version and implementation of age that supports plugins.
17+
18+
Usually, tagged recipients are the public side of private keys held in hardware,
19+
where the identity side is handled by a different plugin.`
20+
21+
func main() {
22+
flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", usage) }
23+
24+
p, err := plugin.New("tag")
25+
if err != nil {
26+
log.Fatal(err)
27+
}
28+
p.HandleRecipient(func(b []byte) (age.Recipient, error) {
29+
return tag.NewClassicRecipient(b)
30+
})
31+
os.Exit(p.Main())
32+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"log"
7+
"os"
8+
9+
"filippo.io/age"
10+
"filippo.io/age/plugin"
11+
"filippo.io/age/tag"
12+
)
13+
14+
const usage = `age-plugin-tagpq is an age plugin for ML-KEM-768 + P-256 post-quantum hybrid
15+
tagged recipients. These are supported natively by age v1.3.0 and later, but
16+
this plugin can be placed in $PATH to add support to any version and
17+
implementation of age that supports plugins.
18+
19+
Usually, tagged recipients are the public side of private keys held in hardware,
20+
where the identity side is handled by a different plugin.`
21+
22+
func main() {
23+
flag.Usage = func() { fmt.Fprintf(os.Stderr, "%s\n", usage) }
24+
25+
p, err := plugin.New("tagpq")
26+
if err != nil {
27+
log.Fatal(err)
28+
}
29+
p.HandleRecipient(func(b []byte) (age.Recipient, error) {
30+
return tag.NewHybridRecipient(b)
31+
})
32+
os.Exit(p.Main())
33+
}

doc/age.1.ronn

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,20 @@ instruct the user to perform encryption with the `-e`/`--encrypt` and
237237
doesn't make sense (such as a password-encryption plugin) may instruct the user
238238
to use the `-j` flag.
239239

240+
#### Tagged recipients
241+
242+
`age` can natively encrypt to recipients starting with `age1tag1` (using P-256
243+
ECDH) or `age1tagpq1` (using the ML-KEM-768 + P-256 post-quantum hybrid). These
244+
are intended to be the public side of private keys held in hardware.
245+
246+
They are directly supported to avoid the need to install the plugin, which may
247+
be platform-specific, on the encrypting side.
248+
249+
The tag reduces privacy, by allowing an observer to correlate files with a
250+
recipient (but not files amongst them without knowledge of the recipient),
251+
but this is also a desirable property for hardware keys that require user
252+
interaction for each decryption operation.
253+
240254
## EXIT STATUS
241255

242256
`age` will exit 0 if and only if encryption or decryption are successful for the

0 commit comments

Comments
 (0)