Aes Key Generation In Python

  1. Aes Key Generation In Python 8
  2. Aes Key Generation In Python Programming
  • What is PyCryptodome?
  • Generating A Key
  • Encrypting
  • Decrypting
  • Examples

What is PyCryptodome?

  • Python Generate An Aes Key - coffeeever. The secrets module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets. In particularly, secrets should be used in preference to the default pseudo-random number generator in the random.
  • Python Symmetric String Encryption with key generation using Cryptography. Supported Python versions. Example Code for Python based symmetric encryption using AES-GCM and generation of keys.

After we generate a new random ivwith the size of an AES block, 128bits. We now create our AES cipher with AES.new with our key, in mode CBC and with our just generated iv.

PyCryptodome is a self-contained Python package of low-level cryptographic primitives that supports Python 2.6 and 2.7, Python 3.4 and newer, and PyPy.

PyCryptodome is a fork of PyCrypto that has been enhanced to add more implementations and fixes to the original PyCrypto library. Where possible, most of the algorithms in this library are implemented in pure Python; only pieces that are extremely critical to performance (e.g. block ciphers) are implemented as C extensions.

The PyCryptodome library offers implementations for things like:

  • AES
  • Stream ciphers like Salsa20
  • Cryptographic hashes like SHA-2
  • Message Authentication Codes like HMAC
  • RSA asymmetric key generation

What Happened To PyCrypto?

Even though unstated on any official site by the owner (which is unfortunate), PyCrypto is currently unmaintained. The last commit that was made to the official GitHub repository was on Jun 21, 2014.

Since PyCrypto has been unmaintained for a few years, there have been a few security vulnerabilities found which are listed on www.cvedetails.com. This is quite a worry as PyCrypto examples are still prominent in Python security search results. Since there are no warnings in the project or on the repository, the best we can do is to tell people.

As PyCryptodome is a modified fork of PyCrypto, it can be used in some situations as a drop-in-replacement for PyCrypto; you can read more about that in the docs.

Installing PyCryptodome

The easiest way to install this library is to use pip. Open up the terminal/cmd and execute:

To make sure it installed correctly, open IDLE and execute:

If no errors appeared it has been installed correctly.

What is AES?

In this tutorial, I'll be using an implementation of Advanced Encryption Standard (AES) to encrypt strings and files. If you don't know what AES is, I highly recommend you understand what it is and how it works before you continue with the examples. Not understanding the different modes of AES and how it is designed could lead to insecure encryptions.

Aes Key Generation In Python

AES has a block size of 128 bits and this implementation of AES supports 3 sizes of keys, 16, 24 or 32 bytes long for AES-128, AES-192 or AES-256 respectively. Many modes are supported by this implementation of AES, including:

  • CBC: Cipher-Block Chaining
  • CFB: Cipher FeedBack
  • OFB: Output FeedBack
  • CTR: Counter
  • EAX: EAX

I have not included Electronic Code Book (ECB) due to the fact that it is not semantically secure. I do not recommend using this mode.

Generating A Key

Keys that are used in AES must be 128, 192, or 256 bits in size (for AES-128, AES-192 or AES-256 respectively). PyCryptodome supplies a function at Crypto.Random.get_random_bytes that returns a random byte string of a length we decide. To use this, import the function and pass a length to the function:

When running this snippet, a new key that is of type bytes will be generated on each run. When using this method for creating a key, it will need to be stored somewhere to be used again.

Remember, the key we will use to decrypt will have to be the same key we encrypted with. So don't lose the key otherwise you lose the file contents!

Storing a Key

Key generation may seem useless as you need to store it, but that is definitely not the case. Since this function creates truly random data, we could simply generate a key and then write it to a file on a USB (or some other secure place). When we encrypt/decrypt files, we then read this file from the USB and get the key out. Here is an example of this:

Even though generating keys like this is definitely one of the better options, some people would rather use passwords provided from users. This is quite understandable as it makes it easier for users to use the application

Generating A Key From A 'Password'

The idea here is to generate a byte sequence of appropriate length from a string provided from the user. To do this we can use Crypto.Protocol.KDF.PBKDF2 (API reference). PBKDF2 allows us to generate a key of any length by simply passing a password and salt.

PBKDF2 is used because PBKDF1 can only generate keys up to 160 bits long.

A salt is random data that is used as an additional input to a one-way function that 'hashes' data. How you store this is up to you, in short terms, it is combined with the password provided by the user so that the result cannot be looked up in a rainbow table. Even though not 100% recommended, I feel it can be more beneficial to simply generate a salt and hard-code it into your application. To generate a salt, we can use the same method that we used to generate a key:

Using the output from this snippet, you can now create a variable in your script and assign it to the value that was output. For example:

Now that the hard part is over, we can generate keys using user input. Passing the string provided by the user (password) and the salt that you just hard-coded in your script as well as declaring the output length, we can get the key.

Now in key, you will have the key that you can use in encryption. You do not have to store this key now as you can see that this can be generated every time regarding the user provides the same password.

Aes key generation in python code

Even though it may be ok to hard code a salt for your own projects, it is recommended to generate a new salt for each object encrypted. When storing data (as you will see later), you can write the salt to the beginning of the file (assuming your storage method is a file) as it is a fixed length. When decrypting the file, read out the salt first, then generate the key with the password and then continue to read the rest of the data out of the file to decrypt.

Encrypting

Now that we have the key, we can encrypt files. These methods encrypt bytes objects, so if you have a string, you can call .encode() on it, otherwise for other objects, make sure they are of type bytes.

In these examples, I will show a variable named key which will be where your key should be (as generated from the instructions above).

You can find examples in the documentation for legacy ciphers and modern ciphers; I will cover a couple of examples from the documentation to help you understand how to encrypt and save the data required for decryption.

Different modes will require you to store different values for decryption like an iv, nonce or tag. If you want to use a mode that I do not cover here, simply find the example in the docs (from the links above for legacy and modern ciphers) and identify what values need to be stored.

CBC Example

You can find this example in the docs. CBC requires you to pad your data to make sure the final block is filled with some data; not all modes require this (as I show in the next example).

CFB Example

You can find this example in the docs. CFB is very similar to CFB but does not require the data to be padded; this means the call pad(data, AES.block_size) from the CBC example can be replaced with data for CFB.

This CFB mode example is practically identical to the OFB mode (just need to change the mode in AES.new) and very close to CTR in the way that a nonce needs to be stored compared to the iv from CFB (the nonce is stored in cipher.nonce).

CFB, OFB and CTR to not require padding because they are stream ciphers, not block ciphers

EAX Example

You can find this example in the docs. Just like all the examples here and in the docs for AES, the steps are all the same, just different data needs to be stored for this mode being a nonce, tag and the ciphered data.

How To Use All The Outputs From These Encryptions?

Many of these modes will output more than one value; this could be in the form of an iv, nonce or something else. To pack all this data in a file, put the data that has static lengths (always the same) at the top of the file, then ciphered content after this. Now when you read out the file, you can read x amount of bytes using .read(x) to get the known-length values (can be multiple) and then call .read(-1) to get the rest of the data.

In the examples above, this is how I saved all the data required to a file, but you do not have to save the data this way. When only using the data internally or in something like a database, it can be easier to just keep them separate in their own variable or column.

Another way to do this would be to convert all the iv, nonce, tag and ciphered text output values to base64. You can now create a Python dictionary object using the names of these variables as keys and base64 values as the values and save this as a JSON file. This makes it very easy to write and read but will make larger files that take longer to read/write. For example:

Decrypting

Aes key generation in python code

Now that you have your data, stored it somewhere, you will want to read it and decrypt it. Based on the encryption examples above, these are the examples to decrypt. If you did not store the data in a file, you can populate the required fields using whatever method you used to store them.

CBC Example

When the file for the CBC encryption example was written, the iv was first written and then the ciphered data. Since we know the length of the iv (16 bytes), first read that from the start of the file and the read the rest of the file to get the ciphered data.

CFB Example

In the CFB encryption example the iv and ciphered data was saved to the output file.

EAX Example

In the EAX encryption example the nonce, tag and ciphered data was saved to the output file. We know the length of the nonce and tag values so we can read these out first and then the data after.

Examples

In these examples, I will use the CFB mode to show that the input data can be encrypted and then decrypted to give the original input data.

In each example I will generate a new key that will be used in the session; as described before, you will need to generate a key yourself and save it for encryption and decryption since encryption and decryption most likely won't be done in the same session (you can't rely on get_random_bytes to get your key back).

String Example Proof

In this proof, I will demonstrate how to encrypt and decrypt a string.

File Example Proof

In this proofm I will demonstrate how to encrypt and decrypt a file. This example will be a bit different from the examples above as I will be reading and writing to and from files using a buffer. This allows me to encrypt much larger files without the whole file having to be loaded into memory.

If you look at the size of the .encrypted file, you would notice it is 16 bytes larger than the file that was encrypted. This is because the iv is at the start of the file for you to read back out.

Aes

If are interested in hashing files in Python, check out my tutorial on How to Hash Files in Python.

AES (Advanced Encryption Standard) is a symmetric block cipher standardizedby NIST . It has a fixed data block size of 16 bytes.Its keys can be 128, 192, or 256 bits long.

AES is very fast and secure, and it is the de facto standard for symmetricencryption.

As an example, encryption can be done as follows:

The recipient can obtain the original message using the same keyand the incoming triple (nonce,ciphertext,tag):

Module’s constants for the modes of operation supported with AES:

Aes Key Generation In Python 8

var MODE_ECB:Electronic Code Book (ECB)
var MODE_CBC:Cipher-Block Chaining (CBC)
var MODE_CFB:Cipher FeedBack (CFB)
var MODE_OFB:Output FeedBack (OFB)
var MODE_CTR:CounTer Mode (CTR)
var MODE_OPENPGP:
OpenPGP Mode
var MODE_CCM:Counter with CBC-MAC (CCM) Mode
var MODE_EAX:EAX Mode
var MODE_GCM:Galois Counter Mode (GCM)
var MODE_SIV:Syntethic Initialization Vector (SIV)
var MODE_OCB:Offset Code Book (OCB)
Crypto.Cipher.AES.new(key, mode, *args, **kwargs)

Create a new AES cipher.

Aes Key Generation In Python Programming

Parameters:
  • key (bytes/bytearray/memoryview) –

    The secret key to use in the symmetric cipher.

    It must be 16, 24 or 32 bytes long (respectively for AES-128,AES-192 or AES-256).

    For MODE_SIV only, it doubles to 32, 48, or 64 bytes.

  • mode (One of the supported MODE_* constants) – The chaining mode to use for encryption or decryption.If in doubt, use MODE_EAX.
Keyword Arguments:
  • iv (bytes, bytearray, memoryview) –(Only applicable for MODE_CBC, MODE_CFB, MODE_OFB,and MODE_OPENPGP modes).

    The initialization vector to use for encryption or decryption.

    For MODE_CBC, MODE_CFB, and MODE_OFB it must be 16 bytes long.

    For MODE_OPENPGP mode only,it must be 16 bytes long for encryptionand 18 bytes for decryption (in the latter case, it isactually the encrypted IV which was prefixed to the ciphertext).

    If not provided, a random byte string is generated (you must thenread its value with the iv attribute).

  • nonce (bytes, bytearray, memoryview) –(Only applicable for MODE_CCM, MODE_EAX, MODE_GCM,MODE_SIV, MODE_OCB, and MODE_CTR).

    A value that must never be reused for any other encryption donewith this key (except possibly for MODE_SIV, see below).

    For MODE_EAX, MODE_GCM and MODE_SIV there are norestrictions on its length (recommended: 16 bytes).

    For MODE_CCM, its length must be in the range [7..13].Bear in mind that with CCM there is a trade-off between noncelength and maximum message size. Recommendation: 11 bytes.

    For MODE_OCB, its length must be in the range [1..15](recommended: 15).

    For MODE_CTR, its length must be in the range [0..15](recommended: 8).

    For MODE_SIV, the nonce is optional, if it is not specified,then no nonce is being used, which renders the encryptiondeterministic.

    If not provided, for modes other than MODE_SIV`, a randombyte string of the recommended length is used (you must thenread its value with the nonce attribute).

  • segment_size (integer) –(Only MODE_CFB).The number of bits the plaintext and ciphertextare segmented in. It must be a multiple of 8.If not specified, it will be assumed to be 8.

  • mac_len : (integer) –(Only MODE_EAX, MODE_GCM, MODE_OCB, MODE_CCM)Length of the authentication tag, in bytes.

    It must be even and in the range [4..16].The recommended value (and the default, if not specified) is 16.

  • msg_len : (integer) –(Only MODE_CCM). Length of the message to (de)cipher.If not specified, encrypt must be called with the entire message.Similarly, decrypt can only be called once.

  • assoc_len : (integer) –(Only MODE_CCM). Length of the associated data.If not specified, all associated data is buffered internally,which may represent a problem for very large messages.

  • initial_value : (integer or bytes/bytearray/memoryview) –(Only MODE_CTR).The initial value for the counter. If not present, the cipher willstart counting from 0. The value is incremented by one for each block.The counter number is encoded in big endian mode.

  • counter : (object) –Instance of Crypto.Util.Counter, which allows full customizationof the counter block. This parameter is incompatible to both nonceand initial_value.

  • use_aesni : (boolean) –Use Intel AES-NI hardware extensions (default: use if available).

Return:

an AES object, of the applicable mode.