lens @ 8eeddc0bfb574aada6bb76638957421b52344bb0

 1package ext
 2
 3import (
 4	"bytes"
 5	"crypto/aes"
 6	"crypto/cipher"
 7	"crypto/rand"
 8	"encoding/gob"
 9	"errors"
10	"io"
11)
12
13type Token struct {
14	UserID   uint
15	Username string
16}
17
18func ReadToken(data []byte, key []byte) (*Token, error) {
19	block, err := aes.NewCipher(key)
20	if err != nil {
21		return nil, err
22	}
23
24	aesgcm, err := cipher.NewGCM(block)
25	if err != nil {
26		panic(err.Error())
27	}
28
29	nonceSize := aesgcm.NonceSize()
30	if len(data) < nonceSize {
31		return nil, errors.New("nonce size greater than data's size")
32	}
33
34	nonce, ciphertext := data[:nonceSize], data[nonceSize:]
35	plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil)
36	if err != nil {
37		return nil, err
38	}
39
40	r := bytes.NewReader(plaintext)
41	var token Token
42	dec := gob.NewDecoder(r)
43	if err = dec.Decode(&token); err != nil {
44		return nil, err
45	}
46	return &token, nil
47}
48
49func WriteToken(token *Token, key []byte) ([]byte, error) {
50	block, err := aes.NewCipher(key)
51	if err != nil {
52		return nil, err
53	}
54
55	aesgcm, err := cipher.NewGCM(block)
56	if err != nil {
57		return nil, err
58	}
59
60	var buffer bytes.Buffer
61	enc := gob.NewEncoder(&buffer)
62	if err := enc.Encode(token); err != nil {
63		return nil, err
64	}
65	nonce := make([]byte, aesgcm.NonceSize())
66	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
67		return nil, err
68	}
69
70	ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil)
71	return ciphertext, nil
72}