package ext import ( "bytes" "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/gob" "errors" "io" ) type Token struct { UserID uint Username string } func ReadToken(data []byte, key []byte) (*Token, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } aesgcm, err := cipher.NewGCM(block) if err != nil { panic(err.Error()) } nonceSize := aesgcm.NonceSize() if len(data) < nonceSize { return nil, errors.New("nonce size greater than data's size") } nonce, ciphertext := data[:nonceSize], data[nonceSize:] plaintext, err := aesgcm.Open(nil, nonce, ciphertext, nil) if err != nil { return nil, err } r := bytes.NewReader(plaintext) var token Token dec := gob.NewDecoder(r) if err = dec.Decode(&token); err != nil { return nil, err } return &token, nil } func WriteToken(token *Token, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { return nil, err } aesgcm, err := cipher.NewGCM(block) if err != nil { return nil, err } var buffer bytes.Buffer enc := gob.NewEncoder(&buffer) if err := enc.Encode(token); err != nil { return nil, err } nonce := make([]byte, aesgcm.NonceSize()) if _, err = io.ReadFull(rand.Reader, nonce); err != nil { return nil, err } ciphertext := aesgcm.Seal(nonce, nonce, buffer.Bytes(), nil) return ciphertext, nil }