AES Encryption and Decryption in Python [64, 128, 256] - Codeigo (2024)

Advanced Encryption Standard (AES) is a powerful and trustworthy cryptographic encryption tool to secure digital data. It accepts three key lengths – 128, 192, and 256 bits (16, 24 and 32 bytes, respectively).

AES cipher is abbreviated using the key length. For example, an AES cipher using a 256-bit key is abbreviated as AES 256. The longer the key, the more secure the system. Therefore, the rule of thumb is to use a 256-bit key.

AES is a symmetric encryption, meaning the same key (password or passphrase) is used for encrypting and decrypting data.

The AES algorithm works in 3 main steps:

  • Step 1: Generate the key – a secret passphrase to encrypt or decrypt data. This should be kept safe because anyone with this key can decrypt your data.
  • Step 2: Generate a cipher – an algorithm is used to perform encryption and decryption. There are several modes to choose from. We will cover the implementation of a few of them.
  • Step 3: Encrypt or decrypt data – AES encrypts and decrypts data in 16-bytes (128 bits) blocks.

There are different modes you can use to generate cipher text in Step 2: They include:

Mode of Operation Abbreviation Summary
Electronic Code Book AES-ECB Is often regarded as the easiest mode to implement, but it is the least secure.
Cipher Block Chaining AES-CBC Is a mode that uses the output of the previous block as input to the current block.
Cipher FeedBack AES-CFB Is a mode that allows for the encryption of individual bits or bytes.
Output FeedBack AES-OFB Is a mode that converts the block cipher into a stream cipher.
Counter AES-CTR Is a mode that uses a counter to generate the keystream for encryption.
Galois Counter Mode AES-GCM Is a mode that combines AES-CTR mode with authentication to provide security.

We will implement AES-ECB, AES-CBC, and AES-GCM in Python using the pycryptodome library. You can install the package using pip by running the command:

pip install pycryptodome

Note: pycryptodome is a fork of pycrypto. The latter is no longer maintained; therefore, install the former.

AES-ECB Encryption and Decryption in Python

ECB is the simplest and the least secure AES encryption algorithm. Each 16-byte (128 bits) block of plaintext is encrypted independently in this mode.

In this case, padding is needed to fit the data into the 16-byte blocks. Let’s see an example.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

from Crypto.Cipher import AES

from Crypto.Util.Padding import pad, unpad

from Crypto.Random import get_random_bytes

def encrypt(plaintext, key):

# Create an AES cipher object with the key and AES.MODE_ECB mode

cipher = AES.new(key, AES.MODE_ECB)

# Pad the plaintext and encrypt it

ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))

return ciphertext

def decrypt(ciphertext, key):

# Create an AES cipher object with the key and AES.MODE_ECB mode

cipher = AES.new(key, AES.MODE_ECB)

# Decrypt the ciphertext and remove the padding

decrypted_data = unpad(cipher.decrypt(ciphertext), AES.block_size)

return decrypted_data

# Example usage

plaintext = b"This is the message to be encrypted"

# Generate a random 256-bit (32-byte) key

# Key-length accepted: 16, 24, and 32 bytes.

key = get_random_bytes(32)# Generating keys/passphrase

print("Key:", key.hex())

# Encryption

encrypted_data = encrypt(plaintext, key)

print("Encrypted data:", encrypted_data)

# Decryption

decrypted_data = decrypt(encrypted_data, key)

print("Decrypted data:", decrypted_data)

Output:

Key: da131765104d989f1604621d4c5c383b547d46e9542bb000f3f5c6bc46858bd4Encrypted data: b"\xdc,\xe2\xd5\x1a\x15\xb7\x15\xd1\xfd\\<;<\xfe\xcd\xefbII'\xcb\xfe\x00\xfb\xac\xfcO\xfc\x8a\xb325\x8b\x91I\xea\xf4\xc9\xbd\xc7\xfcw,Z!\x1bT"Decrypted data: b'This is the message to be encrypted'

Explanation:

The encrypt function takes the plaintext and the key as inputs. It creates an AES cipher object using AES.new with the key and AES.MODE_ECB mode. The plaintext is padded using pad from Crypto.Util.Padding to ensure its length is a multiple of the AES block size (32). The padded plaintext is then encrypted using the cipher object, resulting in the ciphertext.

The decrypt function takes the ciphertext and the key as inputs. It creates an AES cipher object using AES.new with the key and AES.MODE_ECB mode. The ciphertext is decrypted using the cipher object. The padding is removed from the decrypted data using unpad from Crypto.Util.Padding, resulting in the original plaintext.

Implementation of AES-CBC Encryption and Decryption in Python

Each plaintext block (except the first block) is XORed (bitwise exclusive OR) with the previous ciphertext block before encryption. The XOR operation introduces diffusion to ensure identical plaintext blocks produce different ciphertext blocks, enhancing security.

An Initialization Vector (IV) is also needed for CBC. IV is a random value that serves as the initial input to the encryption algorithm. IV ensures that each encryption has a different ciphertext result.

Here is the implementation of the CBC encryption algorithm.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

from Crypto.Cipher import AES

from Crypto.Util.Padding import pad, unpad

from Crypto.Random import get_random_bytes

def encrypt(plaintext, key):

# Generate a random initialization vector (IV)

iv = get_random_bytes(AES.block_size)

# Create an AES cipher object with the key and AES.MODE_CBC mode

cipher = AES.new(key, AES.MODE_CBC, iv)

# Pad the plaintext and encrypt it

ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))

# Concatenate the IV and ciphertext

encrypted_data = iv + ciphertext

return encrypted_data

def decrypt(ciphertext, key):

# Extract the IV from the ciphertext

iv = ciphertext[: AES.block_size]

# Create an AES cipher object with the key, AES.MODE_CBC mode, and the extracted IV

cipher = AES.new(key, AES.MODE_CBC, iv)

# Decrypt the ciphertext and remove the padding

decrypted_data = unpad(cipher.decrypt(ciphertext[AES.block_size :]), AES.block_size)

return decrypted_data

# Example usage

plaintext = b"This is the message to be encrypted"

# Generate a random 256-bit (32-byte) key

# Key-length accepted: 16, 24, and 32 bytes.

key = get_random_bytes(24)

print("Key:", key.hex())

# Encryption

encrypted_data = encrypt(plaintext, key)

print("Encrypted data:", encrypted_data)

# Decryption

decrypted_data = decrypt(encrypted_data, key)

print("Decrypted data:", decrypted_data)

Output:

Key: 86e0f895f89701a174fdbe45ae82c126a3cb788111a1e1bdEncrypted data: b'U\xbe\xd6[\x12\xae\xebV\x14\xdf<\xdc^\xaf\xb3hWB\xb8#\x1c\x05E\xa6\xec\x0b\xf6\x96C\xb4x\xe6\x00\x13h\xe3\xb1*\n\xc2\x90\x8a\xba\xb0\x95[A;\xe5k\nz\xafA\x08>\xab\xf9M\xb9\xc9\xcc\xf9U'Decrypted data: b'This is the message to be encrypted'

AES-GCM Encryption Implementation in Python

This is a widely used encryption algorithm. It uses Galois Message Authentication Code (GMAC) for authentication and the Counter (CTR) encryption algorithm. One of the major selling points of this algorithm is that it allows for parallel processing, enabling efficient encryption and decryption of large amounts of data.

Here is an implementation in Python.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

from Crypto.Cipher import AES

from Crypto.Random import get_random_bytes

def encrypt_with_AES_GCM(message, secret_key):

# Create an AES-GCM cipher object

cipher = AES.new(secret_key, AES.MODE_GCM)

# Encrypt the message and generate the ciphertext and authentication tag

ciphertext, auth_tag = cipher.encrypt_and_digest(message)

# Return the encrypted message along with the nonce and authentication tag

return (ciphertext, cipher.nonce, auth_tag)

def decrypt_with_AES_GCM(encrypted_message, secret_key):

# Extract the ciphertext, nonce, and authentication tag from the encrypted message

ciphertext, nonce, auth_tag = encrypted_message

# Create an AES-GCM cipher object with the provided nonce

cipher = AES.new(secret_key, AES.MODE_GCM, nonce)

# Decrypt the ciphertext and verify the authenticity using the authentication tag

plaintext = cipher.decrypt_and_verify(ciphertext, auth_tag)

# Return the decrypted plaintext

return plaintext

# Generate a random 128-bit (16-byte) secret key

# Accepted values 16, 24, and 32 for 128, 192 and 256-bit keys, respectively.

secret_key = get_random_bytes(16)

print("Secret Key:", secret_key.hex())

# Message to be encrypted using AES-GCM

message = b"Password to be encrypted by AES-GCM algorithm"

# Encryption

encrypted_message = encrypt_with_AES_GCM(message, secret_key)

print( "Encrypted Message:",{

"ciphertext": encrypted_message[0].hex(),

"nonce": encrypted_message[1].hex(),

"auth_tag": encrypted_message[2].hex(),

})

# Decryption

decrypted_message = decrypt_with_AES_GCM(encrypted_message, secret_key)

print("Decrypted Message:", decrypted_message)

Output:

Secret Key: 0bc7ebda2f81bf9a5ff27a93e67ac048Encrypted Message: {'ciphertext': 'ef6706a067a3c56278afa8a79899b3d4eacf7dd7010f1c82db994b2e4b68ea29c4b7e8f61a504de8023397df10', 'nonce': 'e1984b7bc33be671e2e75febf5028f04', 'auth_tag': '5bc38b07dc0488070b85ee2c3a209cb2'}Decrypted Message: b'Password to be encrypted by AES-GCM algorithm'

Note: As mentioned earlier and shown in the examples above, AES does not accept 64-bit keys (8 bytes). If you must implement 64-bit encryption, check out this link.

Conclusion

AES is a very powerful encryption method for digital data. In this article, we discussed how AES encryption works (at a high level) and then implemented three AES algorithms in Python. After going through the guide, you should be able to easily implement the other modes mentioned at the beginning of this article.

AES Encryption and Decryption in Python [64, 128, 256] - Codeigo (2024)

References

Top Articles
Latest Posts
Article information

Author: Virgilio Hermann JD

Last Updated:

Views: 6312

Rating: 4 / 5 (61 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Virgilio Hermann JD

Birthday: 1997-12-21

Address: 6946 Schoen Cove, Sipesshire, MO 55944

Phone: +3763365785260

Job: Accounting Engineer

Hobby: Web surfing, Rafting, Dowsing, Stand-up comedy, Ghost hunting, Swimming, Amateur radio

Introduction: My name is Virgilio Hermann JD, I am a fine, gifted, beautiful, encouraging, kind, talented, zealous person who loves writing and wants to share my knowledge and understanding with you.