CryptMessagePlugin.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import base64
  2. import os
  3. from Plugin import PluginManager
  4. from Crypt import CryptBitcoin
  5. from lib.pybitcointools import bitcoin as btctools
  6. import CryptMessage
  7. @PluginManager.registerTo("UiWebsocket")
  8. class UiWebsocketPlugin(object):
  9. def encrypt(self, text, publickey):
  10. encrypted = CryptMessage.encrypt(text, CryptMessage.toOpensslPublickey(publickey))
  11. return encrypted
  12. def decrypt(self, encrypted, privatekey):
  13. back = CryptMessage.getEcc(privatekey).decrypt(encrypted)
  14. return back.decode("utf8")
  15. # - Actions -
  16. # Returns user's public key unique to site
  17. # Return: Public key
  18. def actionUserPublickey(self, to, index=0):
  19. publickey = self.user.getEncryptPublickey(self.site.address, index)
  20. self.response(to, publickey)
  21. # Encrypt a text using the publickey or user's sites unique publickey
  22. # Return: Encrypted text using base64 encoding
  23. def actionEciesEncrypt(self, to, text, publickey=0, return_aes_key=False):
  24. if type(publickey) is int: # Encrypt using user's publickey
  25. publickey = self.user.getEncryptPublickey(self.site.address, publickey)
  26. aes_key, encrypted = self.encrypt(text.encode("utf8"), publickey.decode("base64"))
  27. if return_aes_key:
  28. self.response(to, [base64.b64encode(encrypted), base64.b64encode(aes_key)])
  29. else:
  30. self.response(to, base64.b64encode(encrypted))
  31. # Decrypt a text using privatekey or the user's site unique private key
  32. # Return: Decrypted text or list of decrypted texts
  33. def actionEciesDecrypt(self, to, param, privatekey=0):
  34. if type(privatekey) is int: # Decrypt using user's privatekey
  35. privatekey = self.user.getEncryptPrivatekey(self.site.address, privatekey)
  36. if type(param) == list:
  37. encrypted_texts = param
  38. else:
  39. encrypted_texts = [param]
  40. texts = [] # Decoded texts
  41. for encrypted_text in encrypted_texts:
  42. try:
  43. text = self.decrypt(encrypted_text.decode("base64"), privatekey)
  44. texts.append(text)
  45. except Exception as err:
  46. texts.append(None)
  47. if type(param) == list:
  48. self.response(to, texts)
  49. else:
  50. self.response(to, texts[0])
  51. # Encrypt a text using AES
  52. # Return: Iv, AES key, Encrypted text
  53. def actionAesEncrypt(self, to, text, key=None, iv=None):
  54. from lib import pyelliptic
  55. if key:
  56. key = key.decode("base64")
  57. else:
  58. key = os.urandom(32)
  59. if iv: # Generate new AES key if not definied
  60. iv = iv.decode("base64")
  61. else:
  62. iv = pyelliptic.Cipher.gen_IV('aes-256-cbc')
  63. if text:
  64. encrypted = pyelliptic.Cipher(key, iv, 1, ciphername='aes-256-cbc').ciphering(text.encode("utf8"))
  65. else:
  66. encrypted = ""
  67. self.response(to, [base64.b64encode(key), base64.b64encode(iv), base64.b64encode(encrypted)])
  68. # Decrypt a text using AES
  69. # Return: Decrypted text
  70. def actionAesDecrypt(self, to, *args):
  71. from lib import pyelliptic
  72. if len(args) == 3: # Single decrypt
  73. encrypted_texts = [(args[0], args[1])]
  74. keys = [args[2]]
  75. else: # Batch decrypt
  76. encrypted_texts, keys = args
  77. texts = [] # Decoded texts
  78. for iv, encrypted_text in encrypted_texts:
  79. encrypted_text = encrypted_text.decode("base64")
  80. iv = iv.decode("base64")
  81. text = None
  82. for key in keys:
  83. ctx = pyelliptic.Cipher(key.decode("base64"), iv, 0, ciphername='aes-256-cbc')
  84. try:
  85. decrypted = ctx.ciphering(encrypted_text)
  86. if decrypted and decrypted.decode("utf8"): # Valid text decoded
  87. text = decrypted
  88. except Exception, err:
  89. pass
  90. texts.append(text)
  91. if len(args) == 3:
  92. self.response(to, texts[0])
  93. else:
  94. self.response(to, texts)
  95. @PluginManager.registerTo("User")
  96. class UserPlugin(object):
  97. def getEncryptPrivatekey(self, address, param_index=0):
  98. assert param_index >= 0 and param_index <= 1000
  99. site_data = self.getSiteData(address)
  100. if site_data.get("cert"): # Different privatekey for different cert provider
  101. index = param_index + self.getAddressAuthIndex(site_data["cert"])
  102. else:
  103. index = param_index
  104. if "encrypt_privatekey_%s" % index not in site_data:
  105. address_index = self.getAddressAuthIndex(address)
  106. crypt_index = address_index + 1000 + index
  107. site_data["encrypt_privatekey_%s" % index] = CryptBitcoin.hdPrivatekey(self.master_seed, crypt_index)
  108. self.log.debug("New encrypt privatekey generated for %s:%s" % (address, index))
  109. return site_data["encrypt_privatekey_%s" % index]
  110. def getEncryptPublickey(self, address, param_index=0):
  111. assert param_index >= 0 and param_index <= 1000
  112. site_data = self.getSiteData(address)
  113. if site_data.get("cert"): # Different privatekey for different cert provider
  114. index = param_index + self.getAddressAuthIndex(site_data["cert"])
  115. else:
  116. index = param_index
  117. if "encrypt_publickey_%s" % index not in site_data:
  118. privatekey = self.getEncryptPrivatekey(address, param_index)
  119. publickey = btctools.encode_pubkey(btctools.privtopub(privatekey), "bin_compressed")
  120. site_data["encrypt_publickey_%s" % index] = base64.b64encode(publickey)
  121. return site_data["encrypt_publickey_%s" % index]