88 lines
2.7 KiB
Python
88 lines
2.7 KiB
Python
"""
|
||
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
|
||
'preferded': '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.preferred
|
||
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
|