|
|
@@ -1,13 +1,15 @@
|
|
1
|
1
|
package mtglib
|
|
2
|
2
|
|
|
3
|
3
|
import (
|
|
|
4
|
+ "crypto/rand"
|
|
4
|
5
|
"encoding/base64"
|
|
5
|
6
|
"encoding/hex"
|
|
6
|
|
- "errors"
|
|
7
|
7
|
"fmt"
|
|
8
|
8
|
"strings"
|
|
9
|
9
|
)
|
|
10
|
10
|
|
|
|
11
|
+const SecretKeyLength = 32
|
|
|
12
|
+
|
|
11
|
13
|
type Secret struct {
|
|
12
|
14
|
Key []byte
|
|
13
|
15
|
Host string
|
|
|
@@ -21,51 +23,53 @@ func (s *Secret) MarshalText() ([]byte, error) {
|
|
21
|
23
|
return []byte(s.String()), nil
|
|
22
|
24
|
}
|
|
23
|
25
|
|
|
24
|
|
-func (s *Secret) UnmarshalText(text []byte) error {
|
|
25
|
|
- sc, err := ParseSecret(string(text))
|
|
|
26
|
+func (s *Secret) UnmarshalText(data []byte) error {
|
|
|
27
|
+ text := string(data)
|
|
|
28
|
+
|
|
|
29
|
+ if text == "" {
|
|
|
30
|
+ return ErrSecretEmpty
|
|
|
31
|
+ }
|
|
|
32
|
+
|
|
|
33
|
+ decoded, err := base64.RawStdEncoding.DecodeString(text)
|
|
|
34
|
+ if err != nil && strings.HasPrefix(text, "ee") {
|
|
|
35
|
+ decoded, err = hex.DecodeString(strings.TrimPrefix(text, "ee"))
|
|
|
36
|
+ }
|
|
|
37
|
+
|
|
26
|
38
|
if err != nil {
|
|
27
|
|
- return err
|
|
|
39
|
+ return fmt.Errorf("incorrect secret format: %w", err)
|
|
|
40
|
+ }
|
|
|
41
|
+
|
|
|
42
|
+ if len(decoded) <= SecretKeyLength {
|
|
|
43
|
+ return fmt.Errorf("secret has incorrect length %d", len(text))
|
|
28
|
44
|
}
|
|
29
|
45
|
|
|
30
|
|
- *s = sc
|
|
|
46
|
+ s.Key = decoded[:SecretKeyLength]
|
|
|
47
|
+ s.Host = string(decoded[SecretKeyLength:])
|
|
31
|
48
|
|
|
32
|
49
|
return nil
|
|
33
|
50
|
}
|
|
34
|
51
|
|
|
35
|
52
|
func (s Secret) Base64() string {
|
|
36
|
|
- return s.String()
|
|
37
|
|
-}
|
|
38
|
|
-
|
|
39
|
|
-func (s Secret) EE() string {
|
|
40
|
|
- return "ee" + hex.EncodeToString(append(s.Key, s.Host...))
|
|
|
53
|
+ return base64.StdEncoding.EncodeToString(append(s.Key[:], s.Host...))
|
|
41
|
54
|
}
|
|
42
|
55
|
|
|
43
|
56
|
func (s Secret) String() string {
|
|
44
|
|
- return base64.StdEncoding.EncodeToString(append(s.Key, s.Host...))
|
|
|
57
|
+ return s.Base64()
|
|
45
|
58
|
}
|
|
46
|
59
|
|
|
47
|
|
-func ParseSecret(secret string) (Secret, error) {
|
|
48
|
|
- rv := Secret{}
|
|
49
|
|
-
|
|
50
|
|
- if secret == "" {
|
|
51
|
|
- return rv, errors.New("secret cannot be empty")
|
|
52
|
|
- }
|
|
53
|
|
-
|
|
54
|
|
- decoded, err := base64.RawStdEncoding.DecodeString(secret)
|
|
55
|
|
- if err != nil && strings.HasPrefix(secret, "ee") {
|
|
56
|
|
- decoded, err = hex.DecodeString(strings.TrimPrefix(secret, "ee"))
|
|
57
|
|
- }
|
|
|
60
|
+func (s Secret) EE() string {
|
|
|
61
|
+ return "ee" + hex.EncodeToString(append(s.Key[:], s.Host...))
|
|
|
62
|
+}
|
|
58
|
63
|
|
|
59
|
|
- if err != nil {
|
|
60
|
|
- return rv, fmt.Errorf("incorrect secret format: %w", err)
|
|
|
64
|
+func GenerateSecret(hostname string) Secret {
|
|
|
65
|
+ s := Secret{
|
|
|
66
|
+ Key: make([]byte, SecretKeyLength),
|
|
|
67
|
+ Host: hostname,
|
|
61
|
68
|
}
|
|
62
|
69
|
|
|
63
|
|
- if len(decoded) < 33 {
|
|
64
|
|
- return rv, fmt.Errorf("secret %s has incorrect length", secret)
|
|
|
70
|
+ if _, err := rand.Read(s.Key); err != nil {
|
|
|
71
|
+ panic(err)
|
|
65
|
72
|
}
|
|
66
|
73
|
|
|
67
|
|
- rv.Key = decoded[:32]
|
|
68
|
|
- rv.Host = string(decoded[32:])
|
|
69
|
|
-
|
|
70
|
|
- return rv, nil
|
|
|
74
|
+ return s
|
|
71
|
75
|
}
|