AES Encryption and Decryption in GoLang, PHP, and both with full codes.

Aziza Kasenova
Insider Engineering
4 min readMar 6, 2023

Assume a developer of Instagram or WhatsApp or any other app can see your messages precisely in their storage. All data you’ve ever shared, chatted, and sent. Would you want this? All over the world, there’s now a tendency to keep this data encrypted.

What is encryption?

Encryption is a way to store human-understandable information in a non-human-understandable format.

Assume that you send a Hello, Bryan! message over some tool. That piece of text is being encrypted before it’s saved to the database, so that some random characters will be stored in it, without leaving a clue that cipher text can contain an original Hello, Bryan! text.

Before exporting it to another user or dashboard, that information is decrypted, again outside of the database, leaving only the cipher text in, without rewriting with an original text.

Encryption main idea graph

For this purpose, the key must be kept secret, so that it will not be visible to everyone. Nowadays, all of the cloud giants offer different key management systems like KMS (Key Management System) for AWS.

Since why encryption is needed is pretty obvious, let’s move to how can we encrypt and decrypt in GoLang and PHP.

Note: This article will consider 256-bit AES encryption, which is the most complex and the hardest to crack [1].

Encrypting and decrypting in GoLang

TLDR; The full code is available as a gist and at the end of this section.

1. Encryption

You’ll need a 32-digit cipher secret key and 16-digit initialization vector, iv:

key := "my32digitkey12345678901234567890"
iv := "my16digitIvKey12"

Consider whether you store them as environmental variables or retrieve them from somewhere, it’s important they’re not hard-coded.

For the encryption and decryption, we’ll use a built-in package aes. First, initialization must take place:

block, err := aes.NewCipher([]byte(key))

Note that the NewCipher returns an error as a second parameter [2], so you can log those errors.

Then, create a byte array of the plain text’s length and start encrypting:

mode := cipher.NewCBCEncrypter(block, []byte(iv))
mode.CryptBlocks(ciphertext, plainTextBlock)

convert the result to Base64 encoding:

str := base64.StdEncoding.EncodeToString(ciphertext)

and voila, your text is now encrypted. Make sure to have an error as a second return parameter just in case you need to log it. Again, the full code (with all the required If conditions we’ve faced) is available below as a GitHub gist.

2. Decryption

Don’t forget your secret and iv key. First, decode the string:

ciphertext, err := base64.StdEncoding.DecodeString(encrypted)

Again, create a cipher with aes.NewCipher :

block, err := aes.NewCipher([]byte(key))

and decrypt it:

mode := cipher.NewCBCDecrypter(block, []byte(iv))
mode.CryptBlocks(ciphertext, ciphertext)
ciphertext = PKCS5UnPadding(ciphertext)

Note thePKCS5UnPadding function here, it pads a certain blob of data with necessary data to be used in AES block cipher.

The outcome of running both functions is as below:

Result of function in Go

The full code is as below, also available under this Go playground:

AES Encryption and Decryption in Go Lang

Note that, depending on your use case you might want to get rid of padding. For that occasion, use the value right before PKCS5UnPadding is called.

Encrypting and decrypting in PHP

TLDR; The full code is available as a gist at the end of this section.

1. Encryption

A function for it in PHP is openssl_encrypt. From its manual, it encrypts the data (parameter 1) with a given method (parameter 2), using the key and iv (parameters 3 and 5 respectively) [3]. Parameter 4 is to distinguish whether the data will be returned as it is, OPENSSL_RAW_DATA, or with no padding, OPENSSL_ZERO_PADDING.

So, set your key and iv:

$key= "my32digitkey12345678901234567890";
$iv = "my16digitIvKey12";

(Note again they’re given hard-coded here for better visualization, normally they need to be stored in the key management service)

Call the openssl_encrypt with its parameters:

$encrypted = openssl_encrypt(
$plainText,
'AES-256-CBC',
$key,
0,
$iv
);
echo "This is encrypted: {$encrypted}\n";

2. Decryption

A decryption can happen with openssl_decrypt, which has the same 5 first parameters as its opposite, openssl_encrypt [4]:

$decrypted = openssl_decrypt(
$encrypted,
'AES-256-CBC',
$key,
0,
$iv
);
echo "This is a decrypted: {$decrypted}\n";

The result is as below:

Result of function in PHP

and it’s the same as the one written in GoLang, so you can use them when converting Go-saved and encrypted data in PHP or vice versa.

Again, the full code is available as a gist:

AES Encryption and Decryption in PHP

Note that, depending on your use case you might want to get rid of padding. For that occasion, use the OPENSSL_ZERO_PADDING value as a parameter.

Hope you enjoyed reading it! 🤞

Open to your comments and suggestions in comments 📝.
And feel free to contact me on
LinkedIn as well.

Let me know if you need to encrypt/decrypt the same in NodeJS as well.

References:

[1] B. Daniel, “What Is AES Encryption? [The Definitive Q&A Guide],” www.trentonsystems.com, Mar. 31, 2021. https://www.trentonsystems.com/blog/aes-encryption-your-faqs-answered

[2] “aes package — crypto/aes — Go Packages,” pkg.go.dev. https://pkg.go.dev/crypto/aes#NewCipher (accessed Dec. 30, 2022).‌

[3] “PHP: openssl_encrypt — Manual,” www.php.net. https://www.php.net/manual/en/function.openssl-encrypt.php

[4] “PHP: openssl_decrypt — Manual,” www.php.net. https://www.php.net/manual/en/function.openssl-decrypt.php (accessed Dec. 30, 2022).

--

--