· 7 years ago · Jul 27, 2018, 04:32 PM
1from operator import or_ as bit_or
2from operator import xor as bit_xor
3from itertools import imap
4import hmac
5from pack.util import codec
6
7class CookieStore(object):
8 def __init__(self, secret_key):
9 if not secret_key:
10 self.secret_key = secure_random_bytes(16)
11 elif isinstance(secret_key, str):
12 self.secret_key = get_bytes(secret_key)
13 else:
14 self.secret_key = secret_key
15 def read_session(self, data):
16 if data:
17 return unseal(self.secret_key, data)
18 else:
19 return {}
20 def write_session(self, _, data):
21 return seal(self.secret_key, data)
22 def delete_session(self, _):
23 return seal(self.secret_key, {})
24
25def seal(key, data):
26 data = encrypt(key, get_bytes(repr(data)))
27 return "%s--%s" % (codec.base64_encode(data), hmac(key, data))
28
29def unseal(key, string):
30 "Restore a sealed object from a string."
31 data, mac = string.split("--")
32 data = codec.base64_decode(data)
33 if secure_compare(mac, hmac(key, data)):
34 return read_string(decrypt(key, data))
35
36def encrypt(key, data):
37 cipher =
38
39def decrypt(key, data):
40 cipher =
41
42def hmac(key, data):
43 return codec.base64_encode(hmac.new(key, data, hashlib.sha256).digest())
44
45def secure_compare(a, b):
46 if a and b and len(a) == len(b):
47 return 0 == reduce(bit_or,
48 imap(bit_xor, get_bytes(a), get_bytes(b)))
49 else:
50 return False
51
52def secure_random_bytes(size):
53 seed = bytearray
54
55def get_bytes(string):
56 return [ord(x) for x in string]