From d38937e672b5978d7614350b318eea8ba7646a4e Mon Sep 17 00:00:00 2001 From: Manuel Ebert Date: Wed, 16 Apr 2014 17:03:24 -0400 Subject: [PATCH] Use PKCS#7 for encryption Closes #156 --- jrnl/Journal.py | 17 +++++++++++++---- jrnl/util.py | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/jrnl/Journal.py b/jrnl/Journal.py index 7c83b2af..4fdffa14 100644 --- a/jrnl/Journal.py +++ b/jrnl/Journal.py @@ -66,11 +66,19 @@ class Journal(object): except ValueError: util.prompt("ERROR: Your journal file seems to be corrupted. You do have a backup, don't you?") sys.exit(1) - padding = " ".encode("utf-8") - if not plain.endswith(padding): # Journals are always padded + + padding_length = ord(plain[-1]) + if padding_length > AES.block_size and padding_length != 32: + # 32 is the space character and is kept for backwards compatibility + return None + elif padding_length == 32: + plain = plain.strip() + elif plain[-padding_length:] != util.int2byte(padding_length) * padding_length: + # Invalid padding! return None else: - return plain.decode("utf-8") + plain = plain[:-padding_length] + return plain.decode("utf-8") def _encrypt(self, plain): """Encrypt a plaintext string using self.key as the key""" @@ -80,7 +88,8 @@ class Journal(object): iv = Random.new().read(AES.block_size) crypto = AES.new(self.key, AES.MODE_CBC, iv) plain = plain.encode("utf-8") - plain += b" " * (AES.block_size - len(plain) % AES.block_size) + padding_length = AES.block_size - len(plain) % AES.block_size + plain += util.int2byte(padding_length) * padding_length return iv + crypto.encrypt(plain) def make_key(self, password): diff --git a/jrnl/util.py b/jrnl/util.py index 4b252cbd..3a92f0e4 100644 --- a/jrnl/util.py +++ b/jrnl/util.py @@ -141,3 +141,7 @@ def slugify(string): slug = re.sub(r'[-\s]+', '-', no_punctuation) return u(slug) +def int2byte(i): + """Converts an integer to a byte. + This is equivalent to chr() in Python 2 and bytes((i,)) in Python 3.""" + return chr(i) if PY2 else bytes((i,))