-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathv2loc.go
111 lines (88 loc) · 1.92 KB
/
v2loc.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
package paseto
import (
"errors"
"fmt"
"golang.org/x/crypto/chacha20poly1305"
)
const (
v2locHeader = "v2.local."
v2locKey = 32
v2locNonce = chacha20poly1305.NonceSizeX
)
func V2Encrypt(key []byte, payload, footer any, randBytes []byte) (string, error) {
payloadBytes, err := toBytes(payload)
if err != nil {
return "", fmt.Errorf("encode payload: %w", err)
}
footerBytes, err := toBytes(footer)
if err != nil {
return "", fmt.Errorf("encode footer: %w", err)
}
// step 0.
m := payloadBytes
k := key
f := footerBytes
// step 1.
if !constTimeEq(int32(len(k)), v2locKey) {
return "", errors.New("bad key")
}
// step 2.
h := []byte(v2locHeader)
// step 3.
b := randBytes
if b == nil {
b = readRand(v2locNonce)
}
// step 4.
n := doBLAKE2b(v2locNonce, b, m)
// step 5.
preAuth := pae(h, n, f)
// step 6.
c := doSealCHACHA(k, n, m, preAuth)
// step 7.
body := make([]byte, 0, len(n)+len(c))
body = append(body, n...)
body = append(body, c...)
return buildToken(h, body, f), nil
}
func V2Decrypt(token string, key []byte, payload, footer any) error {
// step 0.
m := token
k := key
// step 1.
if !constTimeEq(int32(len(k)), v2locKey) {
return errors.New("bad key")
}
// step 2.
// TODO: ?
// step 3.
h := []byte(v2locHeader)
// step 4.
body, footerBytes, err := splitToken(m, v2locHeader)
if err != nil {
return fmt.Errorf("decode token: %w", err)
}
if len(body) < v2locNonce {
return ErrIncorrectTokenFormat
}
n, c, f := body[:v2locNonce], body[v2locNonce:], footerBytes
// step 5.
preAuth := pae(h, n, f)
// step 6.
p, err := doOpenCHACHA(k, n, c, preAuth)
if err != nil {
return ErrInvalidTokenAuth
}
// step 7.
if payload != nil {
if err := fromBytes(p, payload); err != nil {
return fmt.Errorf("decode payload: %w", err)
}
}
if footer != nil {
if err := fromBytes(f, footer); err != nil {
return fmt.Errorf("decode footer: %w", err)
}
}
return nil
}