Files
pg/peermap/auth/auth.go
2024-09-27 11:20:17 +08:00

75 lines
1.6 KiB
Go

package auth
import (
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"time"
"github.com/sigcn/pg/secure/aescbc"
)
var (
ErrInvalidToken = errors.New("invalid token")
ErrTokenExpired = errors.New("token expired")
)
type JSONSecret struct {
Network string `json:"n"`
Alias string `json:"n1"`
Neighbors []string `json:"ns"`
Deadline int64 `json:"t"`
}
type Net struct {
ID string
Alias string
Neighbors []string
}
type Authenticator struct {
key []byte
}
func NewAuthenticator(key string) *Authenticator {
sum := sha256.Sum256([]byte(key))
return &Authenticator{key: sum[:]}
}
func (auth *Authenticator) GenerateSecret(n Net, validDuration time.Duration) (string, error) {
b, err := json.Marshal(JSONSecret{
Network: n.ID,
Alias: n.Alias,
Neighbors: n.Neighbors,
Deadline: time.Now().Add(validDuration).Unix(),
})
if err != nil {
return "", err
}
chiperData, err := aescbc.Encrypt(auth.key, b)
return base64.URLEncoding.EncodeToString(chiperData), err
}
func (auth *Authenticator) ParseSecret(networkIDChiper string) (JSONSecret, error) {
chiperData, err := base64.URLEncoding.DecodeString(networkIDChiper)
if err != nil {
return JSONSecret{}, ErrInvalidToken
}
plainData, err := aescbc.Decrypt(auth.key, chiperData)
if err != nil {
return JSONSecret{}, ErrInvalidToken
}
var token JSONSecret
err = json.Unmarshal(plainData, &token)
if err != nil {
return JSONSecret{}, ErrInvalidToken
}
if time.Until(time.Unix(token.Deadline, 0)) <= 0 {
return token, ErrTokenExpired
}
return token, nil
}