-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathconfig.go
201 lines (173 loc) · 5.52 KB
/
config.go
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// SPDX-FileCopyrightText: 2023 The go-mail Authors
//
// SPDX-License-Identifier: MIT
package openpgp
import (
"errors"
"fmt"
"os"
"github.com/wneessen/go-mail-middleware/log"
)
// PGPScheme is an alias type for an int
type PGPScheme int
// Action is an alias type for an int
type Action int
const (
// SchemePGPInline represents the PGP/Inline scheme
//
// Note: Inline PGP only supports plain text mails. Content bodies of type
// HTML (or alternative body parts of the same type) will be ignored
SchemePGPInline PGPScheme = iota
// SchemePGPMIME represents the OpenPGP/MIME (RFC 4880 and 3156) scheme
SchemePGPMIME // Not supported yet
)
const (
// ActionEncrypt will only encrypt the mail body but not sign the outcome
ActionEncrypt Action = iota
// ActionEncryptAndSign will encrypt the mail body and sign the the outcome accordingly
ActionEncryptAndSign
// ActionSign will only sign the mail body but not encrypt any data
ActionSign
)
var (
// ErrNoPrivKey should be returned if a private key is needed but not provided
ErrNoPrivKey = errors.New("no private key provided")
// ErrNoPubKey should be returned if a public key is needed but not provided
ErrNoPubKey = errors.New("no public key provided")
// ErrUnsupportedAction should be returned if a not supported action is set
ErrUnsupportedAction = errors.New("unsupported action")
)
// Config is the confiuration to use in Middleware creation
type Config struct {
// Action represents the encryption/signing action that the Middlware should perform
Action Action
// Logger represents a log that satisfies the log.Logger interface
Logger *log.Logger
// PrivKey represents the OpenPGP/GPG private key part used for signing the mail
PrivKey string
// PublicKey represents the OpenPGP/GPG public key used for encrypting the mail
PublicKey string
// Schema represents one of the supported PGP encryption schemes
Scheme PGPScheme
// passphrase is the passphrase for the private key
passphrase string
}
// Option returns a function that can be used for grouping SignerConfig options
type Option func(cfg *Config)
// NewConfigFromPubKeyByteSlice returns a new Config from a given OpenPGP/GPG public
// key byte slice.
func NewConfigFromPubKeyByteSlice(p []byte, o ...Option) (*Config, error) {
return NewConfig("", string(p), o...)
}
// NewConfigFromPrivKeyByteSlice returns a new Config from a given OpenPGP/GPG private
// key byte slice.
func NewConfigFromPrivKeyByteSlice(p []byte, o ...Option) (*Config, error) {
return NewConfig(string(p), "", o...)
}
// NewConfigFromKeysByteSlices returns a new Config from a given OpenPGP/GPG public
// and private keys byte slices.
func NewConfigFromKeysByteSlices(pr, pu []byte, o ...Option) (*Config, error) {
return NewConfig(string(pr), string(pu), o...)
}
// NewConfigFromPubKeyFile returns a new Config from a given OpenPGP/GPG public
// key file.
func NewConfigFromPubKeyFile(f string, o ...Option) (*Config, error) {
p, err := os.ReadFile(f)
if err != nil {
return nil, err
}
return NewConfig("", string(p), o...)
}
// NewConfigFromPrivKeyFile returns a new Config from a given OpenPGP/GPG private
// key file.
func NewConfigFromPrivKeyFile(f string, o ...Option) (*Config, error) {
p, err := os.ReadFile(f)
if err != nil {
return nil, err
}
return NewConfig(string(p), "", o...)
}
// NewConfigFromKeyFiles returns a new Config from a given OpenPGP/GPG private
// and public key files.
func NewConfigFromKeyFiles(pr, pu string, o ...Option) (*Config, error) {
prd, err := os.ReadFile(pr)
if err != nil {
return nil, err
}
pud, err := os.ReadFile(pu)
if err != nil {
return nil, err
}
return NewConfig(string(prd), string(pud), o...)
}
// NewConfig returns a new Config struct. All values can be prefilled/overriden
// using the With*() Option methods
func NewConfig(pr, pu string, o ...Option) (*Config, error) {
c := &Config{PrivKey: pr, PublicKey: pu}
// Override defaults with optionally provided Option functions
for _, co := range o {
if co == nil {
continue
}
co(c)
}
if c.PrivKey == "" && (c.Action == ActionSign || c.Action == ActionEncryptAndSign) {
return c, fmt.Errorf("message signing requires a private key: %w", ErrNoPrivKey)
}
if c.PublicKey == "" && (c.Action == ActionEncrypt || c.Action == ActionEncryptAndSign) {
return c, fmt.Errorf("message encryption requires a public key: %w", ErrNoPubKey)
}
// Create a slog.TextHandler logger if none was provided
if c.Logger == nil {
c.Logger = log.New(os.Stderr, "openpgp", log.LevelWarn)
}
return c, nil
}
// WithLogger sets a slog.Logger for the Config
func WithLogger(l *log.Logger) Option {
return func(c *Config) {
c.Logger = l
}
}
// WithScheme sets a PGPScheme for the Config
func WithScheme(s PGPScheme) Option {
return func(c *Config) {
c.Scheme = s
}
}
// WithAction sets a Action for the Config
func WithAction(a Action) Option {
return func(c *Config) {
c.Action = a
}
}
// WithPrivKeyPass sets a passphrase for the PrivKey in the Config
func WithPrivKeyPass(p string) Option {
return func(c *Config) {
c.passphrase = p
}
}
// String satisfies the fmt.Stringer interface for the PGPScheme type
func (s PGPScheme) String() string {
switch s {
case SchemePGPInline:
return "PGP/Inline"
case SchemePGPMIME:
return "PGP/MIME"
default:
return "unknown"
}
}
// String satisfies the fmt.Stringer interface for the Action type
func (a Action) String() string {
switch a {
case ActionEncrypt:
return "Encrypt-only"
case ActionEncryptAndSign:
return "Encrypt/Sign"
case ActionSign:
return "Sign-only"
default:
return "unknown"
}
}