kopia lustrzana https://gitlab.com/jaywink/federation
Enable generating encrypted JSON payloads with the Diaspora protocol
This adds possibility for private message support. JSON encrypted payload encryption and decryption is handled by the Diaspora `EncryptedPayload` class. Refs: #82merge-requests/130/head
rodzic
02d110caa9
commit
c1efc1add1
|
@ -35,6 +35,10 @@
|
|||
* Support fetching new style Diaspora protocol Webfinger (RFC 3033) ([related issue](https://github.com/jaywink/federation/issues/108))
|
||||
|
||||
The legaxy Webfinger is still used as fallback if the new Webfinger is not found.
|
||||
|
||||
* Enable generating encrypted JSON payloads with the Diaspora protocol which adds private message support. ([related issue](https://github.com/jaywink/federation/issues/82))
|
||||
|
||||
JSON encrypted payload encryption and decryption is handled by the Diaspora `EncryptedPayload` class.
|
||||
|
||||
### Changed
|
||||
* Refactoring for Diaspora `MagicEnvelope` class.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import json
|
||||
from base64 import b64decode
|
||||
from base64 import b64decode, b64encode
|
||||
|
||||
from Crypto.Cipher import PKCS1_v1_5, AES
|
||||
from Crypto.Random import get_random_bytes
|
||||
from lxml import etree
|
||||
|
||||
|
||||
|
@ -28,3 +29,33 @@ class EncryptedPayload:
|
|||
encrypter = AES.new(key, AES.MODE_CBC, iv)
|
||||
content = encrypter.decrypt(encrypted_magic_envelope)
|
||||
return etree.fromstring(pkcs7_unpad(content))
|
||||
|
||||
@staticmethod
|
||||
def get_aes_key_json():
|
||||
iv = get_random_bytes(AES.block_size)
|
||||
key = get_random_bytes(32)
|
||||
encrypter = AES.new(key, AES.MODE_CBC, iv)
|
||||
return {
|
||||
"key": b64encode(key),
|
||||
"iv": b64encode(iv),
|
||||
}, encrypter
|
||||
|
||||
@staticmethod
|
||||
def encrypt(payload, public_key):
|
||||
"""
|
||||
Encrypt a payload using an encrypted JSON wrapper.
|
||||
|
||||
See: <insert link to docs>
|
||||
|
||||
:param payload: Payload document as a string.
|
||||
:param public_key: Public key of recipient as an RSA object.
|
||||
:return: Encrypted JSON wrapper as dict.
|
||||
"""
|
||||
aes_key_json, encrypter = EncryptedPayload.get_aes_key_json()
|
||||
encrypted_me = encrypter.encrypt(payload)
|
||||
cipher = PKCS1_v1_5.new(public_key)
|
||||
aes_key = cipher.encrypt(aes_key_json)
|
||||
return {
|
||||
"aes_key": b64encode(aes_key),
|
||||
"encrypted_magic_envelope": b64encode(encrypted_me),
|
||||
}
|
||||
|
|
|
@ -230,12 +230,21 @@ class Protocol(BaseProtocol):
|
|||
return data[0:-data[-1]]
|
||||
|
||||
def build_send(self, entity, from_user, to_user=None, *args, **kwargs):
|
||||
"""Build POST data for sending out to remotes."""
|
||||
"""
|
||||
Build POST data for sending out to remotes.
|
||||
|
||||
:param entity: The outbound ready entity for this protocol.
|
||||
:param from_user: The user sending this payload. Must have ``private_key`` and ``handle`` properties.
|
||||
:param to_user: (Optional) user to send private payload to. Must have ``key`` as receiving user public key.
|
||||
:returns: dict or string depending on if private or public payload.
|
||||
"""
|
||||
if entity.outbound_doc is not None:
|
||||
# Use pregenerated outbound document
|
||||
xml = entity.outbound_doc
|
||||
else:
|
||||
xml = entity.to_xml()
|
||||
me = MagicEnvelope(etree.tostring(xml), private_key=from_user.private_key, author_handle=from_user.handle)
|
||||
# TODO wrap if doing encrypted delivery
|
||||
return me.render()
|
||||
rendered = me.render()
|
||||
if to_user:
|
||||
return EncryptedPayload.encrypt(rendered, to_user.key)
|
||||
return rendered
|
||||
|
|
|
@ -80,7 +80,7 @@ def send_document(url, data, timeout=10, *args, **kwargs):
|
|||
Additional ``*args`` and ``**kwargs`` will be passed on to ``requests.post``.
|
||||
|
||||
:arg url: Full url to send to, including protocol
|
||||
:arg data: POST data to send (dict)
|
||||
:arg data: Dictionary (will be form-encoded), bytes, or file-like object to send in the body
|
||||
:arg timeout: Seconds to wait for response (defaults to 10)
|
||||
:returns: Tuple of status code (int or None) and error (exception class instance or None)
|
||||
"""
|
||||
|
|
Ładowanie…
Reference in New Issue