29/02/2020 - GO
You can use example below for data encryption and decryption purposes in Golang. It uses a static secret key and is ideal if the encryption and decryption take place in same machine. You can use the encrypted data in URL.
Alternative to base64
below, you can use hex.EncodeToString/hex.DecodeString
functions.
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
)
func main() {
// You can generate this only once and use as an environment variable.
secret, err := secret()
if err != nil {
panic(fmt.Sprintf("unable to create secret key: %v", err))
}
message := "I am a very secret message"
fmt.Println("Message:", message)
encrypted, err := encrypt(message, secret)
if err != nil {
panic(fmt.Sprintf("unable to encrypt the data: %v", err))
}
fmt.Println("Encrypted:", encrypted)
decrypted, err := decrypt(encrypted, secret)
if err != nil {
panic(fmt.Sprintf("unable to decrypt the data: %v", err))
}
fmt.Println("Decrypted:", decrypted)
}
// secret returns a 32 bytes AES key.
func secret() ([]byte, error) {
key := make([]byte, 16)
if _, err := rand.Read(key); err != nil {
return nil, err
}
return key, nil
}
// encrypt encrypts plain string with a secret key and returns encrypt string.
func encrypt(plainData string, secret []byte) (string, error) {
cipherBlock, err := aes.NewCipher(secret)
if err != nil {
return "", err
}
aead, err := cipher.NewGCM(cipherBlock)
if err != nil {
return "", err
}
nonce := make([]byte, aead.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return "", err
}
return base64.URLEncoding.EncodeToString(aead.Seal(nonce, nonce, []byte(plainData), nil)), nil
}
// decrypt decrypts encrypt string with a secret key and returns plain string.
func decrypt(encodedData string, secret []byte) (string, error) {
encryptData, err := base64.URLEncoding.DecodeString(encodedData)
if err != nil {
return "", err
}
cipherBlock, err := aes.NewCipher(secret)
if err != nil {
return "", err
}
aead, err := cipher.NewGCM(cipherBlock)
if err != nil {
return "", err
}
nonceSize := aead.NonceSize()
if len(encryptData) < nonceSize {
return "", err
}
nonce, cipherText := encryptData[:nonceSize], encryptData[nonceSize:]
plainData, err := aead.Open(nil, nonce, cipherText, nil)
if err != nil {
return "", err
}
return string(plainData), nil
}
$ go run -race main.go
Message: I am a very secret message
Encrypted: tW-khZy3YYpYytPjfffrwHXaaNqMZxugqeBx5vkgc75Nd8HUky8duwit8CiGOUecN5ZxxRox
Decrypted: I am a very secret message
$ go run -race main.go
Message: I am a very secret message
Encrypted: Xbvm0z0wC1eHJqaWZn03vDYUdO4NgtWvXEN_aqjQaKw6J_oKXlOVXOyRp8N8s0qtEHUm93Ny
Decrypted: I am a very secret message
$ go run -race main.go
Message: I am a very secret message
Encrypted: 13hKVuxfVVcRMD3-aW5eiXRGgWChIws56px7pc41yTYkdoJ-obIaBu3-p9SLIIvMY_4aeP9y
Decrypted: I am a very secret message
$ go run -race main.go
Message: I am a very secret message
Encrypted: 8XCqFxJkZKGKC1rYmxU_1-HvYVWwJvN3WmkRSZBHFSKSEaJBmvDuP0HHAwjjE_hvWxgT2jLY
Decrypted: I am a very secret message
$ go run -race main.go
Message: I am a very secret message
Encrypted: 3o8p-xTEcDtSvz6PRdIbK9TRqBmrPohxh6XM33hlMnsZCvkZDbp5Eo4_mqAELZof91sFyvdY
Decrypted: I am a very secret message