Skip to content

iyassou/mpyaes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 

Repository files navigation

mpyaes

MicroPython utility library around ucryptolib.aes

What is this?

The ucryptolib MicroPython module provides an aes class that is capable of doing AES encryption. mpyaes provides an implementation of PKCS7 padding and other facilities around ucryptolib.aes.

Features

  • mpyaes.generate_key (mpyaes.generate_IV): generates a specified amount of pseudorandom bytes, making use of urandom.getrandbits. It's intended for (but not limited to) key (and IV) generation.
  • mpyaes.PKCS7: pads and verifies padding, raises mpyaes.PaddingError if the padding is incorrect.
  • mpyaes.AES: handles AES encryption and decryption.
  • mpyaes.new: returns an AES cipher object i.e. instantiates the mpyaes.AES class.

Usage

Key and IV generation

Keys and IVs are generated by mpyaes.generate_key(x[, seed]) and mpyaes.generate_IV(x[, seed]). mpyaes.generate_IV is an alias of mpyaes.generate_key. The only mandatory argument to mpyaes.generate_key is either the size in bytes of the key to be generated, or a bytes-like object which will be filled with the pseudorandom data. seed is optional, but if supplied will result in urandom.seed(seed) being executed.

>>> import mpyaes
>>> key = mpyaes.generate_key(32)
>>> key
bytearray(b'\xe5\x82\xe7\xc1\xcfP9\xab\x9e4-(\\}\xab\xaa\xf3\xe2S\x054d\xdf"\x82\xd0\xd8\'\x9ee\xc6\x1b')
>>> IV = mpyaes.generate_IV(16)
>>> IV
bytearray(b"\xfeYD\x91\xf2\xcd\xf1\xc6\xc9\xd0\x9c#\xf1\xad'\x9a")

With a buffer and seed value:

>>> key2 = bytearray(32)
>>> seed = 110011
>>> mpyaes.generate_key(key2, seed)
>>> key2
bytearray(b"\x81IV_i\xcd\xc5\xad9>\xe8'\x00\xf9<\x85")

Cipher object creation

Cipher objects are created using mpyaes.new(key, mode[, IV]). Note that keys and IVs are consumed once used to instantiate a cipher object, so save them to variables for sharing (as done in the previous section). Alternatively, if communicating with a device that implements the Yasmarang PRNG, you could use and save a seed.

>>> aes = mpyaes.new(key, mpyaes.MODE_CBC, IV)
>>> aes
<AES 256-bit CBC>

Encryption/Decryption

Padding of plaintexts is carried out by mpyaes.PKCS7.pad and similarly verified by mpyaes.PKCS7.verify with every call for encryption and decryption. Note that decrypted ciphertexts are stripped of their padding.

  • bytearray
>>> message = bytearray("https://www.youtube.com/watch?v=_HHlclssEP4")
>>> aes.encrypt(message)                # in place
>>> message
bytearray(b'\xe4\xb3\x90\xc3\x0b\x80%\xb3\xc2\n\xc3nY\xdfv\xc9\xd3X8\x82Y\xd8\xd7\xbc\xd0\xafP\xbdJ~\xe5\xdf\x8a\xbc\x9cU\xfd\xa3\x9a\x8d\x1a\xed\xdd\x99\x9a\xa5Ll\xff\xaa\xef\xf0\xfbU)o\xb11\xacC\x981\x0b\xdf')
>>> message = aes.decrypt(message)      # zero-copy
>>> message
bytearray(b'https://www.youtube.com/watch?v=_HHlclssEP4')
  • bytes/str
>>> message = "This is an example string."          # alternatively b'This is an example bytes.'
>>> message = aes.encrypt(message)                  # mpyaes.AES.encrypt([bytes, str]) returns a bytearray
>>> message
bytearray(b'^"\x06u\x95\xcb\xb4\xf6\xf0\x90\xd6\xc7T\xd0)\xe1\xf6GMh\xf9\x0b\xd5\xbf\xb3\x12n\x037\xa0K\xfb')
>>> message = aes.decrypt(message)                  # zero-copy
>>> message
bytearray(b'This is an example string.')
  • Files
>>> aes.encrypt_file('to_encrypt.txt', 'out.enc')   # mpyaes.AES.encrypt_file(input_file, output_file)
>>> aes.decrypt_file('out.enc', 'challenger.txt')   # mpyaes.AES.decrypt_file(input_file, output_file)
>>> with open('to_encrypt.txt', 'rb') as f, open('challenger.txt', 'rb') as g:
...     assert f.read() == g.read()
...
>>>

Notes

  • mpyaes makes use of generic MicroPython libraries to increase portability.
  • AES 128-bit and 256-bit, ECB and CBC modes were tested on an ESP32 running MicroPython 1.13.
  • CTR mode isn't supported on the ESP32, so I haven't tested it.