mirror of
https://github.com/FiloSottile/age.git
synced 2025-12-23 13:35:14 +00:00
tag/internal/age-plugin-tagtest: add plugin for testing tag recipients
This commit is contained in:
committed by
Filippo Valsorda
parent
7fa810b20a
commit
ba67de8a4e
61
tag/internal/age-plugin-tagtest/plugin-tagtest.go
Normal file
61
tag/internal/age-plugin-tagtest/plugin-tagtest.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// Command age-plugin-tagtest is a that decrypts files encrypted to fixed
|
||||||
|
// age1tag1... or age1tagpq1... recipients for testing purposes.
|
||||||
|
//
|
||||||
|
// It can be used with the "-j" flag:
|
||||||
|
//
|
||||||
|
// go install ./tag/internal/age-plugin-tagtest
|
||||||
|
// age -d -j tagtest file.age
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"filippo.io/age"
|
||||||
|
"filippo.io/age/plugin"
|
||||||
|
"filippo.io/age/tag/internal/tagtest"
|
||||||
|
)
|
||||||
|
|
||||||
|
const classicRecipient = "age1tag1qwe0kafsjrar4txm6heqnhpfuggzr0gvznz7fvygxrlq90u5mq2pysxtw6h"
|
||||||
|
|
||||||
|
const hybridRecipient = "age1tagpq14h4z7cks9sxftfc8tq4xektt4854ur9rv76tvujdvtzk2fmyywkvh9z2emz3x4epvhz7qdt2v7uksyyq2cdzf3k04ny0g5sc3u4heqh3r9v4cnwhfjw0a2azpgmnk9xk02wvywt5szcq6q3jvwsjxvkn3tsk52vqjczdcvc398ym4j6cvqas4w99gkgt7ur3fmt4g873phr23tgxw3f7wgsz9zxz7m8cp27vpq3h5vc8nssjemtr2etmtmqkg4fzn2u9x9zvtysuya5yrytgx482ftx9864h8a6pprarxd3d0qe8nw2at5ekg3tsahtef7kawasxjamyckw2ans6v933vuypcfrra32f89r2v72mka9hhc55s49xe2khfsq7w9r2zynuzfx4fg6v7jjncsc87rw2yy8qp8hr27edus6zw5xd6m3hax2nxhl2dys9792z3wp5c034sfkrxe86guj7pfdh7sytzrufl9euhuhyf9w6c7z2nwf7v5v8f2s4gplgvfx4jj4le22k2qn242qkqkcwx7llfyrct7jm2wcv0ytypeh6h93ezgtd7q6zr428qze3dec5jxlc5xxjetyephp42fljft3s02p0570kjwyfeyjcnks2vglkvyus5g9l4z6m0gf8wu22ygfm40028txwjlxvvgnn7c36z783c6tmc9k5nef8nucj6u3ustff5vhtnzhnscsvsz79wzrkv3sujtntx4wezucy6lp49flmnyydn3khk2xsesw0ekn4u44nzqw2g2rjyrrl7crshlzttgpe0jvqycjzp9kmtz23t3yu0w9j4n344nnrf88k2jqqfpjxte38pcn0epr879pqsuvajxrkmsas89pvfrzwcewneujn08guj5pvvrtn5hzzg2y6u4wwjqqxx4x8w65yc4dchf750dft8kgcttt2f6j0j5v8s7tkaua78tte7artdfar544vl0rau79h95mc4ghp887z82s6rq93txpkvan86n963kagqkldngnkjcn28zdrh38vdxj002zqs9mx7zjvg3ynzdfhfakkynt9fyqpaxpsdrsqrycuhw5ykwgjz6wldef7xtu6p689234hstxe7v8e5422f2dy8ystn57z3fvy9yfrm4t3lye6ejk5n6x8zqexmql7lx965xcxuuy38xzyt8j9qprnwgfqgx54l4tnjdpzdde6xgmwtnpkfwvyr7rkgnavvjn6a3e56wtvjx3evmhjjxvukpq5zqrj0s4sntkz3yeszs5dty8q0q6m7dgp6mjpvaer0c4343g72eycfqzkjupeaemh0n8e935hqs8fh3jgk7fzyxctzuqlx6d2q9jaf8r9wu4sjxj5w6ppw7m9c3hxrzpcv2uek3kxnndgf2hd99q9v2ux8pjkv29ntslvnvhy09dvcy9578rt89gf4cj4cu79zjxtlj3dpct6rjme02zj3qspsade96njkkufu9zuq2lk3qwvddpxjkqm2hnpqwck54zug7ctvkgvk325lwkg4q5rf73zkgys5e9y8jqc96ntdyl4r78lgtw4k5uljk5ttf46s3gc0rq0jwmddnxt875twwq92505zh3zkse5ag2dhjjxyfzkn7xv3j0kv9r3jzpvgep8fq6z8mar509u4fvnhvthp2ah0r45lsyq0mm6fwkcs30v8k9wzvgt6uvcty6qsjvarjs3htym69zu43m4jd3k4tllrr8c05v6p6spuhup4hkk2p9fp9lxafe3pntcn4nk83gzhjjpcjwyg7jcyz5uancu0fakgz27up7ymzp2xv3sqyqewkkqynskw9qkvysrncxj0cy7dt6q8dsseuwmc2urfmcvkykf82wfa54t85hqx8gywhmhzunm2x0d66a4pwl0xl78fhkces5dpq8pfnp35m5a3u8vdam64zx5s5x9cmnrx3zr066f4f8hlecqnq2fd5quw79ljg3q5nvs6ggmm4gkc"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
c := tagtest.NewClassicIdentity("age-plugin-tagtest").Recipient().String()
|
||||||
|
if c != classicRecipient {
|
||||||
|
log.Fatalf("unexpected classic recipient: %s", c)
|
||||||
|
}
|
||||||
|
h := tagtest.NewHybridIdentity("age-plugin-tagtest").Recipient().String()
|
||||||
|
if h != hybridRecipient {
|
||||||
|
log.Fatalf("unexpected hybrid recipient: %s", h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
p, err := plugin.New("tagtest")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
p.HandleIdentity(func(b []byte) (age.Identity, error) {
|
||||||
|
if len(b) != 0 {
|
||||||
|
return nil, fmt.Errorf("unexpected identity data")
|
||||||
|
}
|
||||||
|
return &tagtestIdentity{}, nil
|
||||||
|
})
|
||||||
|
os.Exit(p.Main())
|
||||||
|
}
|
||||||
|
|
||||||
|
type tagtestIdentity struct{}
|
||||||
|
|
||||||
|
func (i *tagtestIdentity) Unwrap(ss []*age.Stanza) ([]byte, error) {
|
||||||
|
classic := tagtest.NewClassicIdentity("age-plugin-tagtest")
|
||||||
|
if key, err := classic.Unwrap(ss); err == nil {
|
||||||
|
return key, nil
|
||||||
|
} else if !errors.Is(err, age.ErrIncorrectIdentity) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hybrid := tagtest.NewHybridIdentity("age-plugin-tagtest")
|
||||||
|
return hybrid.Unwrap(ss)
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"crypto/ecdh"
|
"crypto/ecdh"
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"filippo.io/age"
|
"filippo.io/age"
|
||||||
"filippo.io/age/internal/format"
|
"filippo.io/age/internal/format"
|
||||||
@@ -18,16 +17,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ClassicIdentity struct {
|
type ClassicIdentity struct {
|
||||||
t *testing.T
|
|
||||||
k hpke.PrivateKey
|
k hpke.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ age.Identity = &ClassicIdentity{}
|
var _ age.Identity = &ClassicIdentity{}
|
||||||
|
|
||||||
func NewClassicIdentity(t *testing.T) *ClassicIdentity {
|
func NewClassicIdentity(seed string) *ClassicIdentity {
|
||||||
k, err := hpke.DHKEM(ecdh.P256()).GenerateKey()
|
k, err := hpke.DHKEM(ecdh.P256()).DeriveKeyPair([]byte(seed))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to generate key: %v", err)
|
panic(fmt.Sprintf("failed to generate key: %v", err))
|
||||||
}
|
}
|
||||||
return &ClassicIdentity{k: k}
|
return &ClassicIdentity{k: k}
|
||||||
}
|
}
|
||||||
@@ -36,11 +34,11 @@ func (i *ClassicIdentity) Recipient() *tag.Recipient {
|
|||||||
uncompressed := i.k.PublicKey().Bytes()
|
uncompressed := i.k.PublicKey().Bytes()
|
||||||
p, err := nistec.NewP256Point().SetBytes(uncompressed)
|
p, err := nistec.NewP256Point().SetBytes(uncompressed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.t.Fatalf("failed to parse public key: %v", err)
|
panic(fmt.Sprintf("failed to parse public key: %v", err))
|
||||||
}
|
}
|
||||||
r, err := tag.NewClassicRecipient(p.BytesCompressed())
|
r, err := tag.NewClassicRecipient(p.BytesCompressed())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.t.Fatalf("failed to create recipient: %v", err)
|
panic(fmt.Sprintf("failed to create recipient: %v", err))
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -89,16 +87,15 @@ func (i *ClassicIdentity) Unwrap(ss []*age.Stanza) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HybridIdentity struct {
|
type HybridIdentity struct {
|
||||||
t *testing.T
|
|
||||||
k hpke.PrivateKey
|
k hpke.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ age.Identity = &HybridIdentity{}
|
var _ age.Identity = &HybridIdentity{}
|
||||||
|
|
||||||
func NewHybridIdentity(t *testing.T) *HybridIdentity {
|
func NewHybridIdentity(seed string) *HybridIdentity {
|
||||||
k, err := hpke.MLKEM768P256().GenerateKey()
|
k, err := hpke.MLKEM768P256().DeriveKeyPair([]byte(seed))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to generate key: %v", err)
|
panic(fmt.Sprintf("failed to generate key: %v", err))
|
||||||
}
|
}
|
||||||
return &HybridIdentity{k: k}
|
return &HybridIdentity{k: k}
|
||||||
}
|
}
|
||||||
@@ -106,7 +103,7 @@ func NewHybridIdentity(t *testing.T) *HybridIdentity {
|
|||||||
func (i *HybridIdentity) Recipient() *tag.Recipient {
|
func (i *HybridIdentity) Recipient() *tag.Recipient {
|
||||||
r, err := tag.NewHybridRecipient(i.k.PublicKey().Bytes())
|
r, err := tag.NewHybridRecipient(i.k.PublicKey().Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
i.t.Fatalf("failed to create recipient: %v", err)
|
panic(fmt.Sprintf("failed to create recipient: %v", err))
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestClassicRoundTrip(t *testing.T) {
|
func TestClassicRoundTrip(t *testing.T) {
|
||||||
i := tagtest.NewClassicIdentity(t)
|
i := tagtest.NewClassicIdentity("test")
|
||||||
r := i.Recipient()
|
r := i.Recipient()
|
||||||
|
|
||||||
if r.Hybrid() {
|
if r.Hybrid() {
|
||||||
@@ -62,7 +62,7 @@ func TestClassicRoundTrip(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHybridRoundTrip(t *testing.T) {
|
func TestHybridRoundTrip(t *testing.T) {
|
||||||
i := tagtest.NewHybridIdentity(t)
|
i := tagtest.NewHybridIdentity("test")
|
||||||
r := i.Recipient()
|
r := i.Recipient()
|
||||||
|
|
||||||
if !r.Hybrid() {
|
if !r.Hybrid() {
|
||||||
@@ -113,7 +113,7 @@ func TestTagHybridMixingRestrictions(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
tagHybrid := tagtest.NewHybridIdentity(t).Recipient()
|
tagHybrid := tagtest.NewHybridIdentity("test").Recipient()
|
||||||
|
|
||||||
// Hybrid tag recipients can be used together with hybrid recipients.
|
// Hybrid tag recipients can be used together with hybrid recipients.
|
||||||
hybrid, err := age.GenerateHybridIdentity()
|
hybrid, err := age.GenerateHybridIdentity()
|
||||||
@@ -133,7 +133,7 @@ func TestTagHybridMixingRestrictions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Classic tag and X25519 recipients can be mixed (both are non-PQ).
|
// Classic tag and X25519 recipients can be mixed (both are non-PQ).
|
||||||
tagClassic := tagtest.NewClassicIdentity(t).Recipient()
|
tagClassic := tagtest.NewClassicIdentity("test").Recipient()
|
||||||
if _, err := age.Encrypt(io.Discard, tagClassic, x25519.Recipient()); err != nil {
|
if _, err := age.Encrypt(io.Discard, tagClassic, x25519.Recipient()); err != nil {
|
||||||
t.Errorf("expected classic tag + X25519 to work, got %v", err)
|
t.Errorf("expected classic tag + X25519 to work, got %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user