1diff --git a/pkg/ext/auth.go b/pkg/ext/auth.go
2deleted file mode 100644
3index ed122bb6b2631d882efac0f6191fe3c29e0dd050..0000000000000000000000000000000000000000
4--- a/pkg/ext/auth.go
5+++ /dev/null
6@@ -1,72 +0,0 @@
7-package ext
8-
9-import (
10- "bytes"
11- "crypto/aes"
12- "crypto/cipher"
13- "crypto/rand"
14- "encoding/gob"
15- "errors"
16- "io"
17-)
18-
19-type Token struct {
20- UserID uint
21- Username string
22-}
23-
24-func ReadToken(data []byte, key []byte) (*Token, error) {
25- block, err := aes.NewCipher(key)
26- if err != nil {
27- return nil, err
28- }
29-
30- aesgcm, err := cipher.NewGCM(block)
31- if err != nil {
32- panic(err.Error())
33- }
34-
35- nonceSize := aesgcm.NonceSize()
36- if len(data) < nonceSize {
37- return nil, errors.New("nonce size greater than data's size")
38- }
39-
40- nonce, ciphertext := data[:nonceSize], data[nonceSize:]
41- plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
42- if err != nil {
43- return nil, err
44- }
45-
46- r := bytes.NewReader(plaintext)
47- var token Token
48- dec := gob.NewDecoder(r)
49- if err = dec.Decode(&token); err != nil {
50- return nil, err
51- }
52- return &token, nil
53-}
54-
55-func WriteToken(token *Token, key []byte) ([]byte, error) {
56- block, err := aes.NewCipher(key)
57- if err != nil {
58- return nil, err
59- }
60-
61- aesgcm, err := cipher.NewGCM(block)
62- if err != nil {
63- return nil, err
64- }
65-
66- var buffer bytes.Buffer
67- enc := gob.NewEncoder(&buffer)
68- if err := enc.Encode(token); err != nil {
69- return nil, err
70- }
71- nonce := make([]byte, aesgcm.NonceSize())
72- if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
73- return nil, err
74- }
75-
76- ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil)
77- return ciphertext, nil
78-}
79diff --git a/pkg/ext/auth_test.go b/pkg/ext/auth_test.go
80deleted file mode 100644
81index dc72a0cd66d92a1a07de9ee36a08120d954f6e60..0000000000000000000000000000000000000000
82--- a/pkg/ext/auth_test.go
83+++ /dev/null
84@@ -1,40 +0,0 @@
85-//go:build unit
86-
87-package ext
88-
89-import (
90- "testing"
91-
92- "git.sr.ht/~gabrielgio/img/pkg/testkit"
93-)
94-
95-func TestReadWriteToken(t *testing.T) {
96- t.Parallel()
97-
98- testCases := []struct {
99- name string
100- key []byte
101- token *Token
102- }{
103- {
104- name: "Normal write",
105- key: []byte("AES256Key-32Characters1234567890"),
106- token: &Token{
107- UserID: 3,
108- Username: "username",
109- },
110- },
111- }
112-
113- for _, tc := range testCases {
114- t.Run(tc.name, func(t *testing.T) {
115- data, err := WriteToken(tc.token, tc.key)
116- testkit.TestFatalError(t, "WriteToken", err)
117-
118- token, err := ReadToken(data, tc.key)
119- testkit.TestFatalError(t, "ReadToken", err)
120-
121- testkit.TestValue(t, "ReadWriteToken", token, tc.token)
122- })
123- }
124-}
125diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go
126index 2dd1cca57f49e61df5123bdb61fa71dd6439d99d..bcc6c5feb3fa1e30f54afc64d96dfc2c6ad5ca2d 100644
127--- a/pkg/ext/middleware.go
128+++ b/pkg/ext/middleware.go
129@@ -8,6 +8,7 @@ "github.com/sirupsen/logrus"
130 "github.com/valyala/fasthttp"
131
132 "git.sr.ht/~gabrielgio/img/pkg/database/repository"
133+ "git.sr.ht/~gabrielgio/img/pkg/service"
134 )
135
136 func HTML(next fasthttp.RequestHandler) fasthttp.RequestHandler {
137@@ -77,7 +78,7 @@ a.entry.Error(err)
138 return
139 }
140
141- token, err := ReadToken(auth, a.key)
142+ token, err := service.ReadToken(auth, a.key)
143 if err != nil {
144 a.entry.Error(err)
145 ctx.Redirect(redirectLogin, 307)
146@@ -92,9 +93,9 @@ next(ctx)
147 }
148 }
149
150-func GetTokenFromCtx(ctx *fasthttp.RequestCtx) *Token {
151+func GetTokenFromCtx(ctx *fasthttp.RequestCtx) *service.Token {
152 tokenValue := ctx.UserValue("token")
153- if token, ok := tokenValue.(*Token); ok {
154+ if token, ok := tokenValue.(*service.Token); ok {
155 return token
156 }
157 return nil
158@@ -113,7 +114,7 @@
159 func (i *InitialSetupMiddleware) Check(next fasthttp.RequestHandler) fasthttp.RequestHandler {
160 return func(ctx *fasthttp.RequestCtx) {
161 // if user has been set to context it is logged in already
162- _, ok := ctx.UserValue("token").(*Token)
163+ _, ok := ctx.UserValue("token").(*service.Token)
164 if ok {
165 next(ctx)
166 return
167diff --git a/pkg/service/auth.go b/pkg/service/auth.go
168index 761c70b4e0a416d0f556bb929318f1e1170f11c4..1966e702241f86248aeb5101a1d2463bfa280a01 100644
169--- a/pkg/service/auth.go
170+++ b/pkg/service/auth.go
171@@ -1,12 +1,18 @@
172 package service
173
174 import (
175+ "bytes"
176 "context"
177+ "crypto/aes"
178+ "crypto/cipher"
179+ "crypto/rand"
180+ "encoding/gob"
181+ "errors"
182+ "io"
183
184 "golang.org/x/crypto/bcrypt"
185
186 "git.sr.ht/~gabrielgio/img/pkg/database/repository"
187- "git.sr.ht/~gabrielgio/img/pkg/ext"
188 )
189
190 type AuthController struct {
191@@ -42,11 +48,11 @@ if err := bcrypt.CompareHashAndPassword(hashedPassword, password); err != nil {
192 return nil, err
193 }
194
195- token := &ext.Token{
196+ token := &Token{
197 UserID: id,
198 Username: string(username),
199 }
200- return ext.WriteToken(token, c.key)
201+ return WriteToken(token, c.key)
202 }
203
204 // InitialRegister register a initial user, it will validate if there is another
205@@ -75,3 +81,64 @@ })
206
207 return err
208 }
209+
210+type Token struct {
211+ UserID uint
212+ Username string
213+}
214+
215+func ReadToken(data []byte, key []byte) (*Token, error) {
216+ block, err := aes.NewCipher(key)
217+ if err != nil {
218+ return nil, err
219+ }
220+
221+ aesgcm, err := cipher.NewGCM(block)
222+ if err != nil {
223+ panic(err.Error())
224+ }
225+
226+ nonceSize := aesgcm.NonceSize()
227+ if len(data) < nonceSize {
228+ return nil, errors.New("nonce size greater than data's size")
229+ }
230+
231+ nonce, ciphertext := data[:nonceSize], data[nonceSize:]
232+ plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
233+ if err != nil {
234+ return nil, err
235+ }
236+
237+ r := bytes.NewReader(plaintext)
238+ var token Token
239+ dec := gob.NewDecoder(r)
240+ if err = dec.Decode(&token); err != nil {
241+ return nil, err
242+ }
243+ return &token, nil
244+}
245+
246+func WriteToken(token *Token, key []byte) ([]byte, error) {
247+ block, err := aes.NewCipher(key)
248+ if err != nil {
249+ return nil, err
250+ }
251+
252+ aesgcm, err := cipher.NewGCM(block)
253+ if err != nil {
254+ return nil, err
255+ }
256+
257+ var buffer bytes.Buffer
258+ enc := gob.NewEncoder(&buffer)
259+ if err := enc.Encode(token); err != nil {
260+ return nil, err
261+ }
262+ nonce := make([]byte, aesgcm.NonceSize())
263+ if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
264+ return nil, err
265+ }
266+
267+ ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil)
268+ return ciphertext, nil
269+}
270diff --git a/pkg/service/auth_test.go b/pkg/service/auth_test.go
271index 35b247575a785ddb5db5c0df0b810c2b6ec08fd8..7083d0c90ea75569f4e2532f86228a57c49df253 100644
272--- a/pkg/service/auth_test.go
273+++ b/pkg/service/auth_test.go
274@@ -64,7 +64,7 @@
275 auth, err := scene.controller.Login(scene.ctx, []byte(tc.username), tc.password)
276 testkit.TestFatalError(t, "Login", err)
277
278- token, err := ext.ReadToken(auth, key)
279+ token, err := ReadToken(auth, key)
280 testkit.TestFatalError(t, "Login", err)
281
282 testkit.TestValue(t, "Login", tc.username, token.Username)
283@@ -76,3 +76,34 @@
284 func remove[T any](slice []T, s int) []T {
285 return append(slice[:s], slice[s+1:]...)
286 }
287+
288+func TestReadWriteToken(t *testing.T) {
289+ t.Parallel()
290+
291+ testCases := []struct {
292+ name string
293+ key []byte
294+ token *Token
295+ }{
296+ {
297+ name: "Normal write",
298+ key: []byte("AES256Key-32Characters1234567890"),
299+ token: &Token{
300+ UserID: 3,
301+ Username: "username",
302+ },
303+ },
304+ }
305+
306+ for _, tc := range testCases {
307+ t.Run(tc.name, func(t *testing.T) {
308+ data, err := WriteToken(tc.token, tc.key)
309+ testkit.TestFatalError(t, "WriteToken", err)
310+
311+ token, err := ReadToken(data, tc.key)
312+ testkit.TestFatalError(t, "ReadToken", err)
313+
314+ testkit.TestValue(t, "ReadWriteToken", token, tc.token)
315+ })
316+ }
317+}