package token import ( "crypto/aes" "crypto/cipher" "crypto/rand" "crypto/sha256" "encoding/base64" "fmt" "io" "syscall" "os" "golang.org/x/term" ) func Must[T any](v T, err error) T { if err != nil { panic(err) } return v } func Token() string { hash := sha256.Sum256(Password()) v, err := Decrypt(string(Must(io.ReadAll(Must(os.Open("encrypted"))))), hash[:]) if err != nil { panic(err) } return v } func Password() []byte { print("Password: ") p, err := term.ReadPassword(int(syscall.Stdin)) if err != nil { panic(err) } return p } func Encrypt(plainText string, key []byte) (string, error) { block, err := aes.NewCipher(key) if err != nil { return "", err } gcm, err := cipher.NewGCM(block) if err != nil { return "", err } nonce := make([]byte, gcm.NonceSize()) if _, err := io.ReadFull(rand.Reader, nonce); err != nil { return "", err } ciphertext := gcm.Seal(nonce, nonce, []byte(plainText), nil) return base64.StdEncoding.EncodeToString(ciphertext), nil } func Decrypt(cipherText string, key []byte) (string, error) { ciphertext, err := base64.StdEncoding.DecodeString(cipherText) if err != nil { return "", err } block, err := aes.NewCipher(key) if err != nil { return "", err } gcm, err := cipher.NewGCM(block) if err != nil { return "", err } nonceSize := gcm.NonceSize() if len(ciphertext) < nonceSize { return "", fmt.Errorf("ciphertext too short") } nonce, ciphertext := ciphertext[:nonceSize], ciphertext[nonceSize:] plainText, err := gcm.Open(nil, nonce, ciphertext, nil) if err != nil { return "", err } return string(plainText), nil }