aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2013-10-30 14:29:58 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2013-10-30 14:29:58 -0700
commitbbeba7176d77df0ca47e2bad8a4f66915f07609d (patch)
treedb92dc119db209749cbf61e9355b07861f54e40a
parent02fad008d3e99a49871144b56a692c2237a0d396 (diff)
downloadcryptography-bbeba7176d77df0ca47e2bad8a4f66915f07609d.tar.gz
cryptography-bbeba7176d77df0ca47e2bad8a4f66915f07609d.tar.bz2
cryptography-bbeba7176d77df0ca47e2bad8a4f66915f07609d.zip
Implemented decryption
-rw-r--r--cryptography/fernet.py29
1 files changed, 29 insertions, 0 deletions
diff --git a/cryptography/fernet.py b/cryptography/fernet.py
index a0996afc..549abb36 100644
--- a/cryptography/fernet.py
+++ b/cryptography/fernet.py
@@ -3,6 +3,8 @@ import os
import struct
import time
+import six
+
from cryptography.hazmat.primitives import padding, hashes
from cryptography.hazmat.primitives.hmac import HMAC
from cryptography.hazmat.primitives.block import BlockCipher, ciphers, modes
@@ -34,3 +36,30 @@ class Fernet(object):
return base64.urlsafe_b64encode(
b"\x80" + struct.pack(">Q", current_time) + iv + ciphertext + hmac
)
+
+ def decrypt(self, data, ttl=None):
+ # TODO: whole function is a giant hack job with no error checking
+ data = base64.urlsafe_b64decode(data)
+ assert data[0] == b"\x80"
+ if ttl is not None:
+ if struct.unpack(">Q", data[1:9])[0] + ttl > int(time.time()):
+ raise ValueError
+ h = HMAC(self.signing_key, digestmod=hashes.SHA256)
+ h.update(data[:-32])
+ hmac = h.digest()
+ if not constant_time_compare(hmac, data[-32:]):
+ raise ValueError
+ unencryptor = BlockCipher(ciphers.AES(self.encryption_key), modes.CBC(data[9:25])).unencryptor()
+ plaintext_padded = unencryptor.update(data[25:-32]) + unencryptor.finalize()
+ unpadder = padding.PKCS7(ciphers.AES.block_size).unpadder()
+ return unpadder.update(plaintext_padded) + unpadder.finalize()
+
+def constant_time_compare(a, b):
+ # TOOD: replace with a cffi function
+ assert isinstance(a, bytes) and isinstance(b, bytes)
+ if len(a) != len(b):
+ return False
+ result = 0
+ for i in xrange(len(a)):
+ result |= six.indexbytes(a, i) ^ six.indexbytes(b, i)
+ return result == 0