Commit 57bf6938 authored by Philipp Hörist's avatar Philipp Hörist

Merge branch 'master' into 'master'

1.0.1

Closes #161

See merge request !12
parents 1a5b58b7 e141482c
1.0.1 / 2017-01-14
- Better XEP Compliance
- Bugfixes
1.0.0 / 2016-12-04
- Bugfixes
......
[info]
name: OMEMO
short_name: omemo
version: 1.0.0
version: 1.0.1
description: OMEMO is an XMPP Extension Protocol (XEP) for secure multi-client end-to-end encryption based on Axolotl and PEP. You need to install some dependencys, you can find install instructions for your system in the Gitlab Wiki.
authors: Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
Daniel Gultsch <daniel@gultsch.de>
......
......@@ -29,11 +29,14 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import logging
from struct import pack, unpack
from Crypto.Cipher import AES
from Crypto.Util import strxor
log = logging.getLogger('gajim.plugin_system.omemo')
def gcm_rightshift(vec):
for x in range(15, 0, -1):
......@@ -140,13 +143,20 @@ def gcm_encrypt(k, iv, plaintext, auth_data):
def aes_encrypt(key, nonce, plaintext):
""" Use AES128 GCM with the given key and iv to encrypt the payload. """
c, t = gcm_encrypt(key, nonce, plaintext, '')
result = c + t
return result
return gcm_encrypt(key, nonce, plaintext, '')
def aes_decrypt(key, nonce, payload):
def aes_decrypt(_key, nonce, payload):
""" Use AES128 GCM with the given key and iv to decrypt the payload. """
ciphertext = payload[:-16]
mac = payload[-16:]
if len(_key) >= 32:
# XEP-0384
log.debug('XEP Compliant Key/Tag')
ciphertext = payload
key = _key[:16]
mac = _key[16:]
else:
# Legacy
log.debug('Legacy Key/Tag')
ciphertext = payload[:-16]
key = _key
mac = payload[-16:]
return gcm_decrypt(key, nonce, ciphertext, '', mac)
......@@ -19,6 +19,7 @@
import os
import logging
from cryptography.hazmat.primitives.ciphers import Cipher
from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.primitives.ciphers.modes import GCM
......@@ -32,11 +33,22 @@ if os.name == 'nt':
else:
from cryptography.hazmat.backends import default_backend
log = logging.getLogger('gajim.plugin_system.omemo')
def aes_decrypt(key, iv, payload):
def aes_decrypt(_key, iv, payload):
""" Use AES128 GCM with the given key and iv to decrypt the payload. """
data = payload[:-16]
tag = payload[-16:]
if len(_key) >= 32:
# XEP-0384
log.debug('XEP Compliant Key/Tag')
data = payload
key = _key[:16]
tag = _key[16:]
else:
# Legacy
log.debug('Legacy Key/Tag')
data = payload[:-16]
key = _key
tag = payload[-16:]
if os.name == 'nt':
_backend = backend
else:
......@@ -58,4 +70,4 @@ def aes_encrypt(key, iv, plaintext):
algorithms.AES(key),
GCM(iv),
backend=_backend).encryptor()
return encryptor.update(plaintext) + encryptor.finalize() + encryptor.tag
return encryptor.update(plaintext) + encryptor.finalize(), encryptor.tag
......@@ -226,12 +226,20 @@ class OmemoState:
log.error('No known devices')
return
payload, tag = encrypt(key, iv, plaintext)
# for XEP-384 Compliance uncomment
# key += tag
payload += tag
# Encrypt the message key with for each of receivers devices
for device in devices_list:
try:
if self.isTrusted(jid, device) == TRUSTED:
cipher = self.get_session_cipher(jid, device)
encrypted_keys[device] = cipher.encrypt(key).serialize()
cipher_key = cipher.encrypt(key)
prekey = isinstance(cipher_key, PreKeyWhisperMessage)
encrypted_keys[device] = (cipher_key.serialize(), prekey)
else:
log.debug('Skipped Device because Trust is: ' +
str(self.isTrusted(jid, device)))
......@@ -248,15 +256,15 @@ class OmemoState:
try:
if self.isTrusted(from_jid, device) == TRUSTED:
cipher = self.get_session_cipher(from_jid, device)
encrypted_keys[device] = cipher.encrypt(key).serialize()
cipher_key = cipher.encrypt(key)
prekey = isinstance(cipher_key, PreKeyWhisperMessage)
encrypted_keys[device] = (cipher_key.serialize(), prekey)
else:
log.debug('Skipped own Device because Trust is: ' +
str(self.isTrusted(from_jid, device)))
except:
log.warning('Failed to find key for device ' + str(device))
payload = encrypt(key, iv, plaintext)
result = {'sid': self.own_device_id,
'keys': encrypted_keys,
'jid': jid,
......@@ -279,6 +287,12 @@ class OmemoState:
log.error('No known devices')
return
payload, tag = encrypt(key, iv, plaintext)
# for XEP-384 Compliance uncomment
# key += tag
payload += tag
for tup in devices_list:
self.get_session_cipher(tup[0], tup[1])
......@@ -292,8 +306,9 @@ class OmemoState:
for rid, cipher in self.session_ciphers[jid_to].items():
try:
if self.isTrusted(jid_to, rid) == TRUSTED:
encrypted_keys[rid] = cipher.encrypt(key). \
serialize()
cipher_key = cipher.encrypt(key)
prekey = isinstance(cipher_key, PreKeyWhisperMessage)
encrypted_keys[rid] = (cipher_key.serialize(), prekey)
else:
log.debug('Skipped Device because Trust is: ' +
str(self.isTrusted(jid_to, rid)))
......@@ -313,7 +328,9 @@ class OmemoState:
try:
cipher = self.get_session_cipher(from_jid, dev)
if self.isTrusted(from_jid, dev) == TRUSTED:
encrypted_keys[dev] = cipher.encrypt(key).serialize()
cipher_key = cipher.encrypt(key)
prekey = isinstance(cipher_key, PreKeyWhisperMessage)
encrypted_keys[dev] = (cipher_key.serialize(), prekey)
else:
log.debug('Skipped own Device because Trust is: ' +
str(self.isTrusted(from_jid, dev)))
......@@ -321,8 +338,6 @@ class OmemoState:
log.exception('ERROR:')
log.warning('Failed to find key for device ' + str(dev))
payload = encrypt(key, iv, plaintext)
result = {'sid': self.own_device_id,
'keys': encrypted_keys,
'jid': jid,
......
......@@ -322,6 +322,8 @@ class Ui(object):
def removeUi(self):
self.actions_hbox.remove(self.omemobutton)
self.chat_control._show_lock_image(False, 'OMEMO', False, True,
False)
self.chat_control.prepare_context_menu = \
self.chat_control.omemo_orig_prepare_context_menu
self.chat_control.send_message = self.chat_control.orig_send_message
......
......@@ -79,9 +79,14 @@ class OmemoMessage(Node):
# , contact_jid, key, iv, payload, dev_id, my_dev_id):
Node.__init__(self, 'encrypted', attrs={'xmlns': NS_OMEMO})
header = Node('header', attrs={'sid': msg_dict['sid']})
for rid, key in msg_dict['keys'].items():
header.addChild('key', attrs={'rid': rid}).addData(b64encode(key))
for rid, (key, prekey) in msg_dict['keys'].items():
if prekey:
child = header.addChild('key',
attrs={'prekey': 'true', 'rid': rid})
else:
child = header.addChild('key',
attrs={'rid': rid})
child.addData(b64encode(key))
header.addChild('iv').addData(b64encode(msg_dict['iv']))
self.addChild(node=header)
self.addChild('payload').addData(b64encode(msg_dict['payload']))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment