Advanced Golang Tutorials: AES-256 Encryption & Decryption



In this blog post, we will explore the Go code for AES-256 encryption and decryption. AES (Advanced Encryption Standard) is a symmetric encryption algorithm widely used for securing sensitive data. AES-256 refers to AES with a key length of 256 bits, providing a high level of security.
The code provided below implements two functions: EncryptAES256 and DecryptAES256. Let's dive into each function to understand their workings.

EncryptAES256 Function 

The EncryptAES256 function encrypts a given slice of data using AES-256 with a provided passphrase. Here's an overview of how it works:


func EncryptAES256(data []byte, passphrase string) (string, error) {
	if len(passphrase) < 32 {
		return "", errors.New("Passphrase must be 32 bytes")
	} else if len(passphrase) > 32 {
		// Use the first 32 bytes.
		passphrase = passphrase[:32]
	}

	block, err := aes.NewCipher([]byte(passphrase))
	if err != nil {
		return "", err
	}

	ciphertext := make([]byte, aes.BlockSize+len(data))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		return "", err
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], data)

	return base64.StdEncoding.EncodeToString(ciphertext), nil
}

  1. The function takes a slice of data and a passphrase as input parameters. 
  2. It checks the length of the passphrase. AES-256 requires a 32-byte passphrase, so if the provided passphrase is shorter than 32 bytes, an error is returned.
  3. If the passphrase is longer than 32 bytes, it is truncated to the first 32 bytes.
  4. The function creates a new AES cipher block using the passphrase. 
  5. An initialization vector (IV) is generated with a length equal to the AES block size (16 bytes) using io.ReadFull(rand.Reader, iv).
  6. A cipher feedback (CFB) encrypter is created using the AES cipher block and IV.
  7. The encryption process is performed by XORing the encrypted data with the original data using the XORKeyStream method of the encrypter.
  8. The ciphertext, consisting of the IV followed by the encrypted data, is encoded using base64 and returned as a string.
It's important to note that the IV is randomly generated for each encryption operation. The IV is a non-secret value that ensures the uniqueness of the encryption, even if the same data is encrypted multiple times with the same key.

DecryptAES256 Function

The DecryptAES256 function decrypts a given ciphertext using AES-256 with a provided passphrase. Let's examine its implementation:

func DecryptAES256(ciphertext string, passphrase string) ([]byte, error) {
	if len(passphrase) < 32 {
		return nil, errors.New("Passphrase must be 32 bytes")
	} else if len(passphrase) > 32 {
		// Use the first 32 bytes.
		passphrase = passphrase[:32]
	}

	key := []byte(passphrase)
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}

	ciphertextBytes, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		return nil, err
	}

	if len(ciphertextBytes) < aes.BlockSize {
		return nil, errors.New("ciphertext too short")
	}

	iv := ciphertextBytes[:aes.BlockSize]
	ciphertextBytes = ciphertextBytes[aes.BlockSize:]
    
    stream := cipher.NewCFBDecrypter(block, iv)

	stream.XORKeyStream(ciphertextBytes, ciphertextBytes)

	return ciphertextBytes, nil
}
  1. The `DecryptAES256` function takes a ciphertext string and a passphrase as input parameters.
  2. Similar to the `EncryptAES256` function, it checks the length of the passphrase. If it's shorter than 32 bytes, an error is returned. If it's longer, it is truncated to the first 32 bytes.
  3. The passphrase is converted to a byte slice.
  4. A new AES cipher block is created using the key derived from the passphrase.
  5. The input ciphertext is decoded from base64 to obtain the ciphertext bytes.
  6. The length of the ciphertext is checked to ensure it is not shorter than the AES block size. If it is, an error is returned.
  7. The first AES block-sized portion of the ciphertext is extracted as the IV.
  8. The remaining ciphertext bytes are extracted.
  9. A cipher feedback (CFB) decrypter is created using the AES cipher block and IV.
  10. The decryption process is performed by XORing the decrypted ciphertext with the ciphertext bytes using the `XORKeyStream` method of the decrypter. The result is stored in the `ciphertextBytes` slice.
  11. The decrypted data is returned as a byte slice.

It's worth noting that the encryption and decryption processes use the same key and IV to ensure proper decryption. The IV is essential for achieving secure encryption, as it adds randomness and prevents patterns from emerging in the encrypted data.

To use these functions, you can import the `crypto/aes`, `crypto/cipher`, `crypto/rand`, `encoding/base64`, and `io` packages. Make sure to handle any errors that may occur during the encryption or decryption process.

In conclusion, the provided Go code implements AES-256 encryption and decryption functions that can be used to protect sensitive data. Remember to handle key management securely and ensure the confidentiality of the passphrase used for encryption and decryption operations.

For those who would like to try out, here is the playground link

Please feel free to leave a comment below if you have any questions or would like to contribute to the post. Happy coding!
Author:

Software Developer, Codemio Admin

Disqus Comments Loading..