Skip to content

Commit bade3ab

Browse files
committed
Addd documentation.
1 parent 6634ff6 commit bade3ab

File tree

1 file changed

+208
-1
lines changed

1 file changed

+208
-1
lines changed

README.md

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,208 @@
1-
In-progress... (2014-05-12)
1+
pyaes
2+
=====
3+
4+
A pure-Python implmentation of the AES block cipher algorithm and the common modes of operation (CBC, CFB, CTR, ECB and OFB).
5+
6+
7+
API
8+
---
9+
10+
All keys may be 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes) long.
11+
12+
To generate a random key use:
13+
```python
14+
import os
15+
16+
# 128 bit, 192 bit and 256 bit keys
17+
key_128 = os.urandom(16)
18+
key_192 = os.urandom(24)
19+
key_256 = os.urandom(32)
20+
```
21+
22+
To generate keys from simple-to-remember passwords, consider using a _password-based key-derivation function_ such as [scrypt](https://github.com/ricmoo/pyscrypt).
23+
24+
25+
### Common Modes of Operation
26+
27+
There are many modes of operations, each with various pros and cons. In general though, the **CBC** and **CTR** modes are recommended. The **ECB is NOT recommended.**, and is included primarilty for completeness.
28+
29+
Each of the following examples assumes the following key:
30+
```python
31+
import pyaes
32+
33+
# A 256 bit (32 byte) key
34+
key = "This_key_for_demo_purposes_only!"
35+
36+
# For some modes of operation we need a random initialization vector
37+
# of 16 bytes
38+
iv = "InitializationVe"
39+
```
40+
41+
42+
#### Counter Mode of Operation (recommended)
43+
44+
```python
45+
aes = pyaes.AESModeOfOperationCTR(key)
46+
plaintext = "Text may be any length you wish, no padding is required"
47+
ciphertext = aes.encrypt(plaintext)
48+
49+
# '''\xb6\x99\x10=\xa4\x96\x88\xd1\x89\x1co\xe6\x1d\xef;\x11\x03\xe3\xee
50+
# \xa9V?wY\xbfe\xcdO\xe3\xdf\x9dV\x19\xe5\x8dk\x9fh\xb87>\xdb\xa3\xd6
51+
# \x86\xf4\xbd\xb0\x97\xf1\t\x02\xe9 \xed'''
52+
print repr(ciphertext)
53+
54+
# The counter mode of operation maintains state, so decryption requires
55+
# a new instance be created
56+
aes = pyaes.AESModeOfOperationCTR(key)
57+
decrypted = aes.decrypt(ciphertext)
58+
59+
# True
60+
print decrypted == plaintext
61+
62+
# To use a custom initial value
63+
counter = pyaes.Counter(initial_value = 100)
64+
aes = pyaes.AESModeOfOperationCTR(key, counter = counter)
65+
ciphertext = aes.encrypt(plaintext)
66+
67+
# '''WZ\x844\x02\xbfoY\x1f\x12\xa6\xce\x03\x82Ei)\xf6\x97mX\x86\xe3\x9d
68+
# _1\xdd\xbd\x87\xb5\xccEM_4\x01$\xa6\x81\x0b\xd5\x04\xd7Al\x07\xe5
69+
# \xb2\x0e\\\x0f\x00\x13,\x07'''
70+
print repr(ciphertext)
71+
```
72+
73+
74+
#### Cipher-Block Chaining (recommended)
75+
76+
```python
77+
aes = pyaes.AESModeOfOperationCBC(key, iv = iv)
78+
plaintext = "TextMustBe16Byte"
79+
ciphertext = aes.encrypt(plaintext)
80+
81+
# '\xd6:\x18\xe6\xb1\xb3\xc3\xdc\x87\xdf\xa7|\x08{k\xb6'
82+
print repr(ciphertext)
83+
84+
85+
# The cipher-block chaining mode of operation maintains state, so
86+
# decryption requires a new instance be created
87+
aes = pyaes.AESModeOfOperationCBC(key, iv = iv)
88+
decrypted = aes.decrypt(ciphertext)
89+
90+
# True
91+
print decrypted == plaintext
92+
```
93+
94+
95+
#### Cipher Feedback
96+
97+
```python
98+
# Each block into the mode of operation must be a multiple of the segment
99+
# size. For this example we choose 8 bytes.
100+
aes = pyaes.AESModeOfOperationCFB(key, iv = iv, segment_size = 8)
101+
plaintext = "TextMustBeAMultipleOfSegmentSize"
102+
ciphertext = aes.encrypt(plaintext)
103+
104+
# '''v\xa9\xc1w"\x8aL\x93\xcb\xdf\xa0/\xf8Y\x0b\x8d\x88i\xcb\x85rmp
105+
# \x85\xfe\xafM\x0c)\xd5\xeb\xaf'''
106+
print repr(ciphertext)
107+
108+
109+
# The cipher-block chaining mode of operation maintains state, so
110+
# decryption requires a new instance be created
111+
aes = pyaes.AESModeOfOperationCFB(key, iv = iv, segment_size = 8)
112+
decrypted = aes.decrypt(ciphertext)
113+
114+
# True
115+
print decrypted == plaintext
116+
```
117+
118+
119+
#### Output Feedback Mode of Operation
120+
121+
```python
122+
aes = pyaes.AESModeOfOperationOFB(key, iv = iv)
123+
plaintext = "Text may be any length you wish, no padding is required"
124+
ciphertext = aes.encrypt(plaintext)
125+
126+
# '''v\xa9\xc1wO\x92^\x9e\rR\x1e\xf7\xb1\xa2\x9d"l1\xc7\xe7\x9d\x87(\xc26s
127+
# \xdd8\xc8@\xb6\xd9!\xf5\x0cM\xaa\x9b\xc4\xedLD\xe4\xb9\xd8\xdf\x9e\xac
128+
# \xa1\xb8\xea\x0f\x8ev\xb5'''
129+
print repr(ciphertext)
130+
131+
# The counter mode of operation maintains state, so decryption requires
132+
# a new instance be created
133+
aes = pyaes.AESModeOfOperationOFB(key, iv = iv)
134+
decrypted = aes.decrypt(ciphertext)
135+
136+
# True
137+
print decrypted == plaintext
138+
```
139+
140+
141+
#### Electronic Codebook (NOT recommended)
142+
143+
```python
144+
aes = pyaes.AESModeOfOperationECB(key)
145+
plaintext = "TextMustBe16Byte"
146+
ciphertext = aes.encrypt(plaintext)
147+
148+
# 'L6\x95\x85\xe4\xd9\xf1\x8a\xfb\xe5\x94X\x80|\x19\xc3'
149+
print repr(ciphertext)
150+
151+
152+
# Since there is no state stored in this mode of operation, it
153+
# is not necessary to create a new aes object for decryption.
154+
#aes = pyaes.AESModeOfOperationECB(key)
155+
decrypted = aes.decrypt(ciphertext)
156+
157+
# True
158+
print decrypted == plaintext
159+
```
160+
161+
162+
### AES block cipher
163+
164+
Generally you should use one of the modes of operation above. This may however be useful for experimenting with a custom mode of operation or dealing with encrypted blocks.
165+
166+
167+
The block cipher requires exactly one block of data to encrypt or decrypt, and each block is 16 bytes.
168+
169+
```python
170+
import pyaes
171+
172+
# 16 bytes long
173+
plaintext_block = "Hello World!!!!!"
174+
175+
aes = pyaes.AES()
176+
177+
ciphertext =
178+
```
179+
180+
Performance
181+
-----------
182+
183+
There is a test case provided in _/tests/test-aes.py_ which does some basic performance testing (its primary purpose is moreso as a regression test).
184+
185+
Based on that test, this library is about 30x slower than [PyCrypto](https://www.dlitz.net/software/pycrypto/) for CBC, ECB and OFB; about 80x slower for CFB; and 300x slower for CTR.
186+
187+
The PyCrypto documentation makes reference to the counter call being responsible for the speed problems of the counter (CTR) mode of operation, which is why they use a specially optimized counter. I will investigate this problem further in the future.
188+
189+
190+
FAQ
191+
---
192+
193+
#### Why do this?
194+
195+
The short answer, *why not?*
196+
197+
The longer answer, is for m [pyscrypt](https://github.com/ricmoo/pyscrypt) library. I required a pure-Python AES implementation that supported 256-bit keys with the counter (CTR) mode of operation. After searching, I found several implementations, but all were missing CTR or only supported 128 bit keys. After all the work of learning AES inside and out to implement the library, it was only a marginal amount of extra work to library-ify a more general solution. So, *why not?*
198+
199+
#### How do I get a question I have added?
200+
201+
E-mail me at pyaes@ricmoo.com with any questions, suggestions, comments, et cetera.
202+
203+
204+
#### Can I give you my money?
205+
206+
Umm... Ok? :-)
207+
208+
_Bitcoin_ - `1LNdGsYtZXWeiKjGba7T997qvzrWqLXLma`

0 commit comments

Comments
 (0)