Skip to content

Instantly share code, notes, and snippets.

@fracasula
Last active August 27, 2024 10:50
Show Gist options
  • Save fracasula/38aa1a4e7481f9cedfa78a0cdd5f1865 to your computer and use it in GitHub Desktop.
Save fracasula/38aa1a4e7481f9cedfa78a0cdd5f1865 to your computer and use it in GitHub Desktop.
A simple example with Golang that uses AES-128 to encrypt and decrypt messages.
package mycrypto
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"io"
"time"
)
func EncryptMessage(key []byte, message string) (string, error) {
byteMsg := []byte(message)
block, err := aes.NewCipher(key)
if err != nil {
return "", fmt.Errorf("could not create new cipher: %v", err)
}
cipherText := make([]byte, aes.BlockSize+len(byteMsg))
iv := cipherText[:aes.BlockSize]
if _, err = io.ReadFull(rand.Reader, iv); err != nil {
return "", fmt.Errorf("could not encrypt: %v", err)
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(cipherText[aes.BlockSize:], byteMsg)
return base64.StdEncoding.EncodeToString(cipherText), nil
}
func DecryptMessage(key []byte, message string) (string, error) {
cipherText, err := base64.StdEncoding.DecodeString(message)
if err != nil {
return "", fmt.Errorf("could not base64 decode: %v", err)
}
block, err := aes.NewCipher(key)
if err != nil {
return "", fmt.Errorf("could not create new cipher: %v", err)
}
if len(cipherText) < aes.BlockSize {
return "", fmt.Errorf("invalid ciphertext block size")
}
iv := cipherText[:aes.BlockSize]
cipherText = cipherText[aes.BlockSize:]
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(cipherText, cipherText)
return string(cipherText), nil
}
package mycrypto
import (
"testing"
"github.com/stretchr/testify/require"
)
const isBase64 = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$"
func TestEncryptDecryptMessage(t *testing.T) {
key := []byte("0123456789abcdef") // must be of 16 bytes for this example to work
message := "Lorem ipsum dolor sit amet"
encrypted, err := EncryptMessage(key, message)
require.Nil(t, err)
require.Regexp(t, isBase64, encrypted)
decrypted, err := DecryptMessage(key, encrypted)
require.Nil(t, err)
require.Equal(t, message, decrypted)
}
@serafdev
Copy link

Bro thank you, I've been struggling with understanding the ciphertext block size and this code has cleared it out for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment