crypt.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import hashlib
  2. import hmac
  3. import msgpack
  4. import os
  5. import zlib
  6. from Crypto.Cipher import AES
  7. class CryptoManager(object):
  8. KEY_CREATE = 1
  9. KEY_READ = 2
  10. KEY_ID = 3
  11. KEY_ARCHIVE = 4
  12. KEY_CINDEX = 5
  13. def __init__(self, store):
  14. self.key_cache = {}
  15. self.store = store
  16. self.tid = store.tid
  17. self.id_key = '0' * 32
  18. self.read_key = os.urandom(32)
  19. self.create_key = os.urandom(32)
  20. def get_key(self, tid):
  21. try:
  22. return self.key_cache[tid]
  23. except KeyError:
  24. keys = self.load_key(tid)
  25. self.key_cache[tid] = keys
  26. return keys
  27. def load_key(self, tid):
  28. data = self.store.get('K', str(tid))
  29. id = data[:32]
  30. if self.id_hash(data[32:]) != id:
  31. raise Exception('Invalid key object found')
  32. key = msgpack.unpackb(data[32:])
  33. return key['create'], key['read']
  34. def store_key(self):
  35. key = {
  36. 'version': 1,
  37. 'read': self.read_key,
  38. 'create': self.create_key,
  39. }
  40. data = msgpack.packb(key)
  41. id = self.id_hash(data)
  42. self.store.put('K', str(self.tid), id + data)
  43. def id_hash(self, data):
  44. return hmac.new(self.id_key, data, hashlib.sha256).digest()
  45. def pack(self, data, key):
  46. data = zlib.compress(msgpack.packb(data))
  47. id = hmac.new(key, data, hashlib.sha256).digest()
  48. data = AES.new(key, AES.MODE_CFB, id[:16]).encrypt(data)
  49. return id + msgpack.packb((1, self.tid, data))
  50. def pack_read(self, data):
  51. return self.pack(data, self.read_key)
  52. def pack_create(self, data):
  53. return self.pack(data, self.create_key)
  54. def unpack(self, data, key_idx):
  55. id = data[:32]
  56. version, tid, data = msgpack.unpackb(data[32:])
  57. assert version == 1
  58. key = self.get_key(tid)[key_idx]
  59. data = AES.new(key, AES.MODE_CFB, id[:16]).decrypt(data)
  60. if hmac.new(key, data, hashlib.sha256).digest() != id:
  61. raise ValueError
  62. return msgpack.unpackb(zlib.decompress(data))
  63. def unpack_read(self, data):
  64. return self.unpack(data, 1)
  65. def unpack_create(self, data):
  66. return self.unpack(data, 0)