Implement XEP-0300 (Use of Cryptographic Hash Functions in XMPP)
This is used to provide hash agility support and let other XEPs select which hash function they support.
This commit is contained in:
parent
802949eba8
commit
3721bf9f6b
3 changed files with 131 additions and 0 deletions
16
slixmpp/plugins/xep_0300/__init__.py
Normal file
16
slixmpp/plugins/xep_0300/__init__.py
Normal file
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
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 slixmpp.plugins.base import register_plugin
|
||||
|
||||
from slixmpp.plugins.xep_0300 import stanza
|
||||
from slixmpp.plugins.xep_0300.stanza import Hash
|
||||
from slixmpp.plugins.xep_0300.hash import XEP_0300
|
||||
|
||||
|
||||
register_plugin(XEP_0300)
|
80
slixmpp/plugins/xep_0300/hash.py
Normal file
80
slixmpp/plugins/xep_0300/hash.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
"""
|
||||
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': hashlib.sha3_256,
|
||||
'sha3-512': 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):
|
||||
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
|
35
slixmpp/plugins/xep_0300/stanza.py
Normal file
35
slixmpp/plugins/xep_0300/stanza.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
"""
|
||||
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 slixmpp.xmlstream import ElementBase
|
||||
|
||||
|
||||
class Hash(ElementBase):
|
||||
name = 'hash'
|
||||
namespace = 'urn:xmpp:hashes:2'
|
||||
plugin_attrib = 'hash'
|
||||
interfaces = {'algo', 'value'}
|
||||
|
||||
allowed_algos = ['sha-1', 'sha-256', 'sha-512', 'sha3-256', 'sha3-512', 'BLAKE2b256', 'BLAKE2b512']
|
||||
|
||||
def set_algo(self, value):
|
||||
if value in self.allowed_algos:
|
||||
self._set_attr('algo', value)
|
||||
elif value in [None, '']:
|
||||
self._del_attr('algo')
|
||||
else:
|
||||
raise ValueError('Invalid algo: %s' % value)
|
||||
|
||||
def get_value(self):
|
||||
return self.xml.text
|
||||
|
||||
def set_value(self, value):
|
||||
self.xml.text = value
|
||||
|
||||
def del_value(self):
|
||||
self.xml.text = ''
|
Loading…
Reference in a new issue