package urlshortener import ( "crypto/aes" "crypto/cipher" "crypto/rand" "encoding/base64" "fmt" "io" ) // this class works with AES. This solution without database. type LinkEncryption struct { Key string // this is secret key, must be 32-bit, if you want to use it } func (l *LinkEncryption) Shorten(plainText string) (string, error) { block, err := aes.NewCipher([]byte(l.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.URLEncoding.EncodeToString(cipherText), nil } func (l *LinkEncryption) Unshorten(encryptedText string) (string, error) { data, err := base64.URLEncoding.DecodeString(encryptedText) if err != nil { return "", err } block, err := aes.NewCipher([]byte(l.Key)) if err != nil { return "", err } gcm, err := cipher.NewGCM(block) if err != nil { return "", err } nonceSize := gcm.NonceSize() if len(data) < nonceSize { return "", fmt.Errorf("ciphertext too short") } nonce, cipherText := data[:nonceSize], data[nonceSize:] plainText, err := gcm.Open(nil, nonce, cipherText, nil) if err != nil { return "", err } return string(plainText), nil }