Skip to content

Commit 6b01263

Browse files
committed
Cleaned up AES CTR.
1 parent 306be14 commit 6b01263

File tree

3 files changed

+25
-48
lines changed

3 files changed

+25
-48
lines changed

pyscrypt/aesctr.py

+4-10
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def __init__(self, nbits, initial_value = 1):
3030
if nbits % 8 != 0: raise ValueError('invalid counter length')
3131
self._counter = [ 0 ] * (nbits // 8)
3232

33+
# Initialize the vector with the initial value
3334
index = len(self._counter) - 1
3435
while initial_value:
3536
self._counter[index] = initial_value % 256
@@ -78,21 +79,14 @@ def encrypt(self, plaintext):
7879
encrypted = [ ]
7980
for c in plaintext:
8081
if len(self._remaining_counter) == 0:
81-
encrypted_counter = self._aes.encrypt(self._counter(), self._key, len(self._key))
82-
self._remaining_counter.extend(encrypted_counter)
82+
self._remaining_counter = self._aes.encrypt(self._counter(), self._key, len(self._key))
8383
encrypted.append(self._remaining_counter.pop(0) ^ ord(c))
8484

8585
return "".join(chr(c) for c in encrypted)
8686

8787
def decrypt(self, crypttext):
88-
decrypted = [ ]
89-
for c in crypttext:
90-
if len(self._remaining_counter) == 0:
91-
encrypted_counter = self._aes.encrypt(self._counter(), self._key, len(self._key))
92-
self._remaining_counter.extend(encrypted_counter)
93-
decrypted.append(self._remaining_counter.pop(0) ^ ord(c))
94-
95-
return "".join(chr(c) for c in decrypted)
88+
# AES-CTR is symetric
89+
return self.encrypt(crypttext)
9690

9791

9892
if __name__ == '__main__':

pyscrypt/file.py

+20-37
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
MODE_READ = 'r'
5959
MODE_WRITE = 'w'
6060

61-
BLOCK_SIZE = 16
61+
BLOCK_SIZE = 1024
6262

6363
class InvalidScryptFileFormat(Exception): pass
6464

@@ -308,47 +308,36 @@ def read(self, size = None):
308308
# end-of-file checksum) and decrypt into a decrypted buffer 1 block at a time
309309
while not self._read_finished:
310310

311-
# We have enough decrypted bytes (or will after decrypted a few encrypted blocks)
312-
if len(self._decrypted_buffer) + len(self._encrypted_buffer) - 32 >= size: break
311+
# We have enough decrypted bytes (or will after decrypting the encrypted buffer)
312+
available = len(self._decrypted_buffer) + len(self._encrypted_buffer) - 32
313+
if available >= size: break
313314

314-
# Read enough AES-256 blocks with a little extra for the possible final checksum
315-
count = int(BLOCK_SIZE * math.ceil(size / BLOCK_SIZE)) + 32
316-
data = ''
317-
while len(data) < count:
318-
chunk = self._fp.read(count - len(data))
319-
if not chunk: break
320-
data += chunk
315+
# Read a little extra for the possible final checksum
316+
data = self._fp.read(BLOCK_SIZE)
321317

322-
self._encrypted_buffer += data
323-
324-
# We didn't get as much as we wanted... The file must be done
325-
if len(data) != count:
318+
# No data left; we're done
319+
if not data:
326320
self._read_finished = True
327321
break
328322

329-
# Decrypt as many of the encrypted blocks as possible (leaving the final check sum)
330-
while len(self._encrypted_buffer) >= BLOCK_SIZE + 32:
331-
block = self._encrypted_buffer[:BLOCK_SIZE]
332-
self._decrypted_buffer += self._crypto.decrypt(block)
333-
self._checksumer.update(block)
334-
self._encrypted_buffer = self._encrypted_buffer[BLOCK_SIZE:]
323+
self._encrypted_buffer += data
324+
325+
# Decrypt as much of the encrypted data as possible (leaving the final check sum)
326+
safe = self._encrypted_buffer[:-32]
327+
self._encrypted_buffer = self._encrypted_buffer[-32:]
328+
self._decrypted_buffer += self._crypto.decrypt(safe)
329+
self._checksumer.update(safe)
335330

336-
# We read all the bytes, so what is left is possible a little more encrypted bytes and the checksum
331+
# We read all the bytes, only the checksum remains
337332
if self._read_finished:
338-
leftover = self._encrypted_buffer[:-32]
339-
checksum = self._encrypted_buffer[-32:]
340-
if leftover:
341-
self._decrypted_buffer += self._crypto.decrypt(leftover)
342-
self._checksumer.update(leftover)
343-
self._check_final_checksum(checksum)
333+
self._check_final_checksum(self._encrypted_buffer)
344334

345335
# Send back the number of bytes requests and remove them from the buffer
346336
decrypted = self._decrypted_buffer[:size]
347337
self._decrypted_buffer = self._decrypted_buffer[size:]
348338

349339
return decrypted
350340

351-
352341
# Write operations
353342
def flush(self):
354343
"Flush the underlying file object's I/O buffer."
@@ -422,13 +411,7 @@ def write(self, str):
422411
if not self._done_header:
423412
self._write_header()
424413

425-
self._decrypted_buffer += str
426-
427-
output = ''
428-
while len(self._decrypted_buffer) >= BLOCK_SIZE:
429-
block = self._crypto.encrypt(self._decrypted_buffer[:BLOCK_SIZE])
430-
output += block
431-
self._decrypted_buffer = self._decrypted_buffer[BLOCK_SIZE:]
432-
self._checksumer.update(block)
433-
self._fp.write(output)
414+
encrypted = self._crypto.encrypt(str)
415+
self._checksumer.update(encrypted)
416+
self._fp.write(encrypted)
434417

tests/run-tests-file.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
sf.close()
2525

2626
result = {True: "pass", False: "fail"}[decrypted == plaintext]
27-
print "Test Encrypt/Decrypt: text_length=%s result=%s" % (text_length, result)
27+
print "Test Encrypt/Decrypt: text_length=%s result=%s valid=%s" % (text_length, result, sf.valid)
2828

2929

3030
# Generate some files to make sure the tarsnap scrypt utility can read them

0 commit comments

Comments
 (0)