/common/busrpc/busrpc/crypto.py

https://github.com/mpdehaan/virt-factory · Python · 153 lines · 135 code · 18 blank · 0 comment · 35 complexity · accf8dc7d156cc168e053efc3142822a MD5 · raw file

  1. import os
  2. import threading
  3. import cPickle
  4. from Crypto.Util.randpool import RandomPool
  5. from Crypto.Cipher import Blowfish
  6. from Crypto.Hash import SHA
  7. class CryptoException(Exception):
  8. def __init__(self, message):
  9. self.message = message
  10. def __str__(self):
  11. return repr(self.message)
  12. class CertManager(object):
  13. def __init__(self, keydir, hostname):
  14. self.keydir = keydir
  15. self.hostname = hostname
  16. if not self.keydir.endswith('/'):
  17. self.keydir += '/'
  18. self.private_keys = []
  19. self.pub_keys = {}
  20. self.private_key_lock = threading.RLock()
  21. self.pub_key_lock = threading.RLock()
  22. def decrypt_message(self, message):
  23. secure_host, encrypted_message = self._parse_secure_message(message)
  24. if secure_host == None:
  25. return message, False
  26. else:
  27. key = None
  28. try:
  29. key = self.load_pub_key(secure_host)
  30. retval = key.decrypt(encrypted_message)
  31. return retval.strip(), True
  32. finally:
  33. if not key == None:
  34. self.release_pub_key(secure_host, key)
  35. def encrypt_message(self, host, message):
  36. key = None
  37. try:
  38. while not len(message) % 8 == 0:
  39. message += ' '
  40. key = self.load_private_key()
  41. encrypted_message = key.encrypt(message)
  42. composed_message = ''.join(['secure-host:',
  43. host,
  44. '\n\n',
  45. encrypted_message])
  46. return composed_message
  47. finally:
  48. if not key == None:
  49. self.release_private_key(key)
  50. def load_private_key(self):
  51. key = None
  52. try:
  53. self.private_key_lock.acquire()
  54. if len(self.private_keys) > 0:
  55. key = self.private_keys.pop()
  56. else:
  57. key = self._load_private_key()
  58. finally:
  59. self.private_key_lock.release()
  60. return key
  61. def release_private_key(self, key):
  62. try:
  63. self.private_key_lock.acquire()
  64. self.private_keys.append(key)
  65. finally:
  66. self.private_key_lock.release()
  67. def load_pub_key(self, host):
  68. key = None
  69. try:
  70. self.pub_key_lock.acquire()
  71. if self.pub_keys.has_key(host):
  72. keys = self.pub_keys[host]
  73. if len(keys) > 0:
  74. key = keys.pop()
  75. if key == None:
  76. key = self._load_pub_key(host)
  77. finally:
  78. self.pub_key_lock.release()
  79. return key
  80. def release_pub_key(self, host, key):
  81. try:
  82. self.pub_key_lock.acquire()
  83. if not self.pub_keys.has_key(host):
  84. self.pub_keys[host] = []
  85. self.pub_keys[host].append(key)
  86. finally:
  87. self.pub_key_lock.release()
  88. def _load_pub_key(self, host):
  89. key = None
  90. file_name = self.keydir + host + '.key'
  91. if os.path.lexists(file_name):
  92. f = file(file_name)
  93. unpickler = cPickle.Unpickler(f)
  94. try:
  95. seed = unpickler.load()
  96. key = Blowfish.new(seed)
  97. finally:
  98. f.close()
  99. return key
  100. def _load_private_key(self):
  101. key = self._load_pub_key(self.hostname)
  102. if key == None:
  103. self._setup_dir(self.keydir)
  104. seed = self._generate_seed(8192)
  105. key = Blowfish.new(seed)
  106. file_name = self.keydir + self.hostname + '.key'
  107. f = file(file_name, "w")
  108. pickler = cPickle.Pickler(f)
  109. try:
  110. pickler.dump(seed)
  111. f.flush()
  112. finally:
  113. f.close()
  114. return key
  115. def _generate_seed(self, size):
  116. rp = RandomPool()
  117. for i in range(7):
  118. m = SHA.new()
  119. tempseed = rp.get_bytes(size)
  120. m.update(tempseed)
  121. rp.add_event(m.hexdigest())
  122. return rp.get_bytes(size)
  123. def _setup_dir(self, dirpath):
  124. if not os.path.exists(dirpath): os.makedirs(dirpath)
  125. def _parse_secure_message(self, message):
  126. parts = message.split('\n\n')
  127. secure_host = None
  128. message = None
  129. if len(parts) > 1:
  130. if parts[0].startswith('secure-host:'):
  131. line = parts[0].split(':')
  132. if len(line) > 1:
  133. secure_host = line[1].strip()
  134. message = parts[1]
  135. return secure_host, message