Created
November 23, 2016 21:40
-
-
Save promolic1/b3dd4fef36852844cbaed198d05b6be3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Just to avoid confusion, I wanted to point out a few things here. | |
For reference, all of the info I've gathered below is directly from the documentation found by running the following two lines of code through your Python interpreter: | |
>>> from Crypto.Cipher import AES | |
>>> help(AES) | |
Block Size vs Key Size | |
AES has a fixed data block size of 16 bytes (128 bits) | |
AES can have a key size of 128, 192, or 256 bits (16, 24, or 32 bytes) | |
This is the difference between AES-128, AES-192, and AES-256 | |
Lines 5 & 6 of your Gist are therefore understandably confusing/incorrect as you seem to be referring to key size, not block size. | |
Plaintext Length Requirements | |
In regards to the encrypt method, which you used on line 18, the following is true: | |
For MODE_ECB, MODE_CBC, and MODE_OFB, plaintext length (in bytes) must be a multiple of block_size. | |
For MODE_CFB, plaintext length (in bytes) must be a multiple of segment_size/8. | |
For MODE_CTR, plaintext can be of any length. | |
For MODE_OPENPGP, plaintext must be a multiple of block_size, unless it is the last chunk of the message. | |
In your comments on lines 8 - 10 you state that by virtue of using AES as a cipher, the plaintext must be a multiple of the block size, but this isn't entirely true. It depends on which chaining mode is being used. | |
The doc also states that for the new method, which you used on line 25, the only required parameter is the key (which you've stored in a variable called secret). You can optionally pass in mode, IV, counter, and/or segment_size. Since you only passed in the key, the cipher took on the default mode of MODE_ECB. In this case, the plaintext length (in bytes) does indeed need to be a multiple of the block size. | |
Randomness | |
To come up with a randomly generated key, as you did in line 22, another good alternative is to use the Crypto.Random package as such: | |
from Crypto import Random | |
key = Random.new().read(AES.block_size) | |
The above snippet of code will output 16 cryptographically random bytes and save them in the key variable, thereby effectively making the AES cipher instantiated with this key AES-128. You could do Random.new().read(32) for AES-256. | |
Final Thoughts | |
Per the info shown on the Block cipher mode of operation Wikipedia page's entry, use of ECB mode is highly discouraged. MODE_CBC and MODE_CFB tend to be the suggested modes but also require that you create an Initialization vector (IV). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from Crypto.Cipher import AES | |
import base64 | |
import os | |
# the block size for the cipher object; must be 16, 24, or 32 for AES | |
BLOCK_SIZE = 32 | |
# the character used for padding--with a block cipher such as AES, the value | |
# you encrypt must be a multiple of BLOCK_SIZE in length. This character is | |
# used to ensure that your value is always a multiple of BLOCK_SIZE | |
PADDING = '{' | |
# one-liner to sufficiently pad the text to be encrypted | |
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING | |
# one-liners to encrypt/encode and decrypt/decode a string | |
# encrypt with AES, encode with base64 | |
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s))) | |
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING) | |
# generate a random secret key | |
secret = os.urandom(BLOCK_SIZE) | |
# create a cipher object using the random secret | |
cipher = AES.new(secret) | |
# encode a string | |
encoded = EncodeAES(cipher, 'password') | |
print 'Encrypted string:', encoded | |
# decode the encoded string | |
decoded = DecodeAES(cipher, encoded) | |
print 'Decrypted string:', decoded |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment