-
Notifications
You must be signed in to change notification settings - Fork 22
/
server.go
138 lines (109 loc) · 3.21 KB
/
server.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
package internal
import (
crypt "crypto"
"crypto/rsa"
"os"
"path/filepath"
"strings"
"github.com/greenstatic/openspa/pkg/openspalib"
"github.com/greenstatic/openspa/pkg/openspalib/crypto"
"github.com/greenstatic/openspa/pkg/openspalib/tlv"
"github.com/pkg/errors"
)
func NewServerCipherSuite(c ServerConfigCrypto) (crypto.CipherSuite, error) {
privKey, err := rsaPrivateKeyFromFile(c.RSA.Server.PrivateKeyPath)
if err != nil {
return nil, errors.Wrap(err, "private key read")
}
l := NewPublicKeyLookupDir(c.RSA.Client.PublicKeyLookupDir)
resolve := NewPublicKeyResolveFromClientUUID(l)
cs := crypto.NewCipherSuite_RSA_SHA256_AES256CBC(privKey, resolve)
return cs, nil
}
var _ crypto.PublicKeyResolver = PublicKeyResolveFromClientUUID{}
type PublicKeyResolveFromClientUUID struct {
l crypto.PublicKeyLookuper
}
func NewPublicKeyResolveFromClientUUID(l crypto.PublicKeyLookuper) *PublicKeyResolveFromClientUUID {
p := &PublicKeyResolveFromClientUUID{
l: l,
}
return p
}
func (p PublicKeyResolveFromClientUUID) PublicKey(_, meta tlv.Container) (crypt.PublicKey, error) {
if meta == nil {
return nil, errors.New("no meta container")
}
uuid, err := openspalib.ClientUUIDFromContainer(meta)
if err != nil {
return nil, errors.Wrap(err, "client uuid from meta container")
}
pub, err := p.l.LookupPublicKey(uuid)
if err != nil {
return nil, errors.Wrap(err, "lookup public key")
}
return pub, nil
}
var _ crypto.PublicKeyLookuper = PublicKeyLookupDir{}
type PublicKeyLookupDir struct {
DirPath string
}
func NewPublicKeyLookupDir(dirPath string) *PublicKeyLookupDir {
p := &PublicKeyLookupDir{
DirPath: dirPath,
}
return p
}
func (p PublicKeyLookupDir) LookupPublicKey(clientUUID string) (crypt.PublicKey, error) {
de, err := os.ReadDir(p.DirPath)
if err != nil {
return nil, errors.Wrap(err, "read public key lookup dir")
}
for _, e := range de {
if name := e.Name(); !e.IsDir() && p.clientFilenameMatch(clientUUID, name) {
b, err := os.ReadFile(filepath.Join(p.DirPath, name))
if err != nil {
return nil, errors.Wrap(err, "client key file read")
}
pub, err := crypto.RSADecodePublicKey(string(b))
if err != nil {
return nil, errors.Wrap(err, "rsa decode client key")
}
return pub, nil
}
}
return nil, errors.New("no key found")
}
func (p PublicKeyLookupDir) clientFilenameMatch(clientUUID, filename string) bool {
if clientUUID == filename {
return true
}
fx := strings.Split(filename, ".")
if len(fx) > 1 {
fx = fx[:len(fx)-1]
}
return strings.Join(fx, ".") == clientUUID
}
func rsaPrivateKeyFromFile(privateKeyPath string) (*rsa.PrivateKey, error) {
content, err := os.ReadFile(privateKeyPath)
if err != nil {
return nil, errors.Wrap(err, "read file")
}
key, err := crypto.RSADecodePrivateKey(string(content))
if err != nil {
return nil, errors.Wrap(err, "rsa decode private key")
}
return key, nil
}
//nolint:unused
func rsaPublicKeyFromFile(publicKeyPath string) (*rsa.PublicKey, error) {
content, err := os.ReadFile(publicKeyPath)
if err != nil {
return nil, errors.Wrap(err, "read file")
}
key, err := crypto.RSADecodePublicKey(string(content))
if err != nil {
return nil, errors.Wrap(err, "rsa decode public key")
}
return key, nil
}