When dealing with sensitive information, ensuring its confidentiality and integrity during transmission and storage is crucial. Galois/Counter Mode (GCM) provides both encryption and message authentication, making it a popular choice for protecting sensitive data. This article will guide you through implementing GCM mode encryption in the Go programming language.
What is GCM Mode?
GCM (Galois/Counter Mode) is a mode of operation for symmetric key cryptographic block ciphers. It is designed to provide both data authenticity through a MAC (Message Authentication Code) and data confidentiality. By combining these two features, GCM helps safeguard against unauthorized data tampering and access.
Prerequisites
To follow along with this guide, ensure that you have the following:
- Go installed on your machine.
- A basic understanding of Go programming language.
Encrypting Data Using GCM in Go
Let’s look at an example of how to encrypt data using the GCM mode of encryption in Go:
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"
)
func main() {
key := []byte("a very secret key!!") // 16, 24 or 32 bytes
plaintext := []byte("Sensitive data")
// Generates a new AES cipher using the secret key.
block, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
// Wrap the cipher block into a Galois Counter Mode.
nonce := make([]byte, 12) // GCM standard nonce size is 12 bytes
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
panic(err.Error())
}
aesGCM, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
// Encrypt and authenticate data.
ciphertext := aesGCM.Seal(nil, nonce, plaintext, nil)
fmt.Printf("Nonce: %x\n", nonce)
fmt.Printf("Ciphertext: %x\n", ciphertext)
}
In this code snippet:
- We start by defining a
keyandplaintext. The key length should be 16, 24, or 32 bytes for AES encryption. - We create a new AES cipher block with the provided key.
- We generate a random nonce of 12 bytes, which is the standard size for GCM.
- We initialize GCM using the cipher block.
- Finally, we use the GCM to encrypt the plaintext, producing ciphertext with an embedded authentication tag.
Decrypting Data with GCM in Go
Decrypting data encrypted with GCM mode in Go involves verifying the message authentication tag before decryption:
func decrypt(ciphertext, key, nonce []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
}
// Decrypt and authenticate data.
plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
if err != nil {
return nil, err
}
return plaintext, nil
}
func main() {
key := []byte("a very secret key!!")
nonce := []byte{...} // nonce used during encryption
ciphertext := []byte{...} // ciphertext received
plaintext, err := decrypt(ciphertext, key, nonce)
if err != nil {
fmt.Println("Failed to decrypt:", err)
} else {
fmt.Printf("Plaintext: %s\n", plaintext)
}
}
By using the function decrypt:
- We set up the cipher block and GCM instance as before.
- We decrypt the ciphertext while also verifying its integrity.
- The plaintext is only returned if the authentication is successful.
Security Considerations
When using GCM mode encryption, it's essential to take into account:
- Always use a unique nonce for every encryption operation with the same key to maintain data confidentiality.
- Keep your encryption keys secure, as anyone with the key can read the data.
- Verify that the libraries you utilize are up-to-date to avoid potential vulnerabilities.
By following these best practices, you can ensure that your data remains protected against unauthorized access or alterations.