""" Slixmpp: The Slick XMPP Library Copyright (C) 2017 Emmanuel Gil Peyrot This file is part of Slixmpp. See the file LICENSE for copying permission. """ from base64 import b64encode import hashlib import logging from slixmpp.plugins import BasePlugin from slixmpp.plugins.xep_0300 import stanza, Hash log = logging.getLogger(__name__) class XEP_0300(BasePlugin): name = 'xep_0300' description = 'XEP-0300: Use of Cryptographic Hash Functions in XMPP' dependencies = {'xep_0030'} stanza = stanza default_config = { 'block_size': 1024 * 1024, # One MiB 'prefered': 'sha-256', 'enable_sha-1': False, 'enable_sha-256': True, 'enable_sha-512': True, 'enable_sha3-256': True, 'enable_sha3-512': True, 'enable_BLAKE2b256': True, 'enable_BLAKE2b512': True, } _hashlib_function = { 'sha-1': hashlib.sha1, 'sha-256': hashlib.sha256, 'sha-512': hashlib.sha512, 'sha3-256': lambda: hashlib.sha3_256(), 'sha3-512': lambda: hashlib.sha3_512(), 'BLAKE2b256': lambda: hashlib.blake2b(digest_size=32), 'BLAKE2b512': lambda: hashlib.blake2b(digest_size=64), } def plugin_init(self): namespace = 'urn:xmpp:hash-function-text-names:%s' self.enabled_hashes = [] for algo in self._hashlib_function: if getattr(self, 'enable_' + algo, False): # XXX: this is a hack for Python 3.5 or below, which # don’t support sha3 or blake2b… try: self._hashlib_function[algo]() except AttributeError: log.warn('Algorithm %s unavailable, disabling.', algo) else: self.enabled_hashes.append(namespace % algo) def session_bind(self, jid): self.xmpp['xep_0030'].add_feature(Hash.namespace) for namespace in self.enabled_hashes: self.xmpp['xep_0030'].add_feature(namespace) def plugin_end(self): for namespace in self.enabled_hashes: self.xmpp['xep_0030'].del_feature(namespace) self.xmpp['xep_0030'].del_feature(feature=Hash.namespace) def compute_hash(self, filename, function=None): if function is None: function = self.prefered h = self._hashlib_function[function]() with open(filename, 'rb') as f: while True: block = f.read(self.block_size) if not block: break h.update(block) hash_elem = Hash() hash_elem['algo'] = function hash_elem['value'] = b64encode(h.digest()) return hash_elem