1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
package encoder
import (
"encoding/base64"
"os"
"strings"
"testing"
)
func testKeyring(t *testing.T) string {
t.Helper()
path := t.TempDir() + "/pubring.mix"
var content strings.Builder
for i, name := range []string{"entry", "middle", "exit"} {
keyID := strings.Repeat(string(rune('a'+i)), 32)
publicKey := strings.Repeat(string(rune('d'+i)), 64)
content.WriteString(name + " " + name + "@example.org " + keyID + " 4:0.2c E 2025-01-01 2099-12-31\n\n")
content.WriteString("-----Begin Mix Key-----\n" + keyID + "\n" + publicKey + "\n-----End Mix Key-----\n")
}
if err := os.WriteFile(path, []byte(content.String()), 0600); err != nil {
t.Fatal(err)
}
return path
}
func TestValidateEmail(t *testing.T) {
r := Request{Kind: Email, PublicKeyring: "/tmp/pubring.mix", Entry: "entry", Chain: []string{"entry"}, To: "user@example.org", Body: "hello"}
if err := Validate(r); err != nil {
t.Fatal(err)
}
}
func TestValidateRejectsPlainIncompleteRequest(t *testing.T) {
r := Request{Kind: Email, PublicKeyring: "/tmp/pubring.mix", Entry: "entry", Chain: []string{"entry"}, To: "bad", Body: "hello"}
if err := Validate(r); err == nil {
t.Fatal("expected invalid recipient")
}
}
func TestValidateUsenetRequiresGatewayRecipient(t *testing.T) {
r := Request{Kind: Usenet, PublicKeyring: "/tmp/pubring.mix", Chain: []string{"entry"}, Newsgroup: "misc.test", Body: "hello"}
if err := Validate(r); err == nil {
t.Fatal("expected missing Usenet gateway recipient to be rejected")
}
r.To = "mail2news@example.org"
if err := Validate(r); err != nil {
t.Fatalf("expected valid Usenet request: %v", err)
}
}
func TestComposeUsenetGatewayHeaders(t *testing.T) {
plain, err := composeMessage(Request{
Kind: Usenet, To: "mail2news@example.org", Subject: "test", Newsgroup: "misc.test", Body: "hello",
})
if err != nil {
t.Fatal(err)
}
text := string(plain)
if !strings.Contains(text, "To: mail2news@example.org\n") || !strings.Contains(text, "Newsgroups: misc.test\n") {
t.Fatalf("missing Usenet delivery headers: %q", text)
}
}
func TestEncodeProducesYAMNArmor(t *testing.T) {
keyring := testKeyring(t)
result, err := Encode(Request{
Kind: Email, PublicKeyring: keyring, Entry: "entry", Chain: []string{"entry"},
From: "Anonymous <anon@example.org>", To: "user@example.org", Subject: "test", Body: "hello",
})
if err != nil {
t.Fatal(err)
}
if result.EntryAddress != "entry@example.org" {
t.Fatalf("unexpected entry address: %q", result.EntryAddress)
}
text := string(result.Envelope)
if !strings.Contains(text, "-----BEGIN REMAILER MESSAGE-----") || !strings.Contains(text, "-----END REMAILER MESSAGE-----") {
t.Fatal("missing YAMN armor markers")
}
lines := strings.Split(text, "\n")
start := 0
for i, line := range lines {
if line == "-----BEGIN REMAILER MESSAGE-----" {
start = i + 3
break
}
}
var encoded strings.Builder
for _, line := range lines[start:] {
if line == "" || strings.HasPrefix(line, "-----END") {
break
}
encoded.WriteString(line)
}
packet, err := base64.StdEncoding.DecodeString(encoded.String())
if err != nil {
t.Fatal(err)
}
if len(packet) != messageBytes {
t.Fatalf("unexpected packet size: got %d, want %d", len(packet), messageBytes)
}
}
func TestEncodeMultiHop(t *testing.T) {
result, err := Encode(Request{
Kind: Email, PublicKeyring: testKeyring(t), Entry: "entry",
Chain: []string{"entry", "middle", "exit"}, To: "user@example.org", Body: "hello",
})
if err != nil {
t.Fatal(err)
}
if len(result.Envelope) == 0 || result.EntryAddress != "entry@example.org" {
t.Fatal("multi-hop envelope was not produced")
}
}
|