changeset ee5bca6b1591 in /home/hg/repos/python-nbxmpp
details:http://hg.gajim.org/python-nbxmpp?cmd=changeset;node=ee5bca6b1591 description: [Fedor Brunner] Use better random number generator when openssl is available. Fixes #12
diffstat:
nbxmpp/auth_nb.py | 9 ++++----- nbxmpp/bosh.py | 8 ++++---- nbxmpp/rndg.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 9 deletions(-)
diffs (125 lines):
diff -r 9486848a00ed -r ee5bca6b1591 nbxmpp/auth_nb.py --- a/nbxmpp/auth_nb.py Fri Dec 06 21:19:37 2013 +0100 +++ b/nbxmpp/auth_nb.py Sat Dec 14 10:04:51 2013 +0100 @@ -27,7 +27,6 @@ from .plugin import PlugIn from .smacks import Smacks import base64 -import random import itertools from . import dispatcher_nb import hashlib @@ -37,6 +36,8 @@ import logging log = logging.getLogger('nbxmpp.auth_nb')
+import rndg + def HH(some): return hashlib.md5(some).hexdigest() def H(some): return hashlib.md5(some).digest() def C(some): return b':'.join(some) @@ -440,8 +441,7 @@ else: self.resp['realm'] = self._owner.Server self.resp['nonce'] = chal['nonce'] - self.resp['cnonce'] = ''.join("%x" % randint(0, 2**28) for randint \ - in itertools.repeat(random.randint, 7)) + self.resp['cnonce'] = '%x' % rngd.getrandbits(196) self.resp['nc'] = ('00000001') self.resp['qop'] = 'auth' self.resp['digest-uri'] = 'xmpp/' + self._owner.Server @@ -471,8 +471,7 @@ def set_password(self, password): self.password = '' if password is None else password if self.mechanism == 'SCRAM-SHA-1': - nonce = ''.join('%x' % randint(0, 2 ** 28) for randint in \ - itertools.repeat(random.randint, 7)) + nonce = '%x' % rndg.getrandbits(196) self.scram_soup = 'n=' + self.username + ',r=' + nonce self.scram_gs2 = 'n,,' # No CB yet. sasl_data = base64.b64encode((self.scram_gs2 + self.scram_soup).\ diff -r 9486848a00ed -r ee5bca6b1591 nbxmpp/bosh.py --- a/nbxmpp/bosh.py Fri Dec 06 21:19:37 2013 +0100 +++ b/nbxmpp/bosh.py Sat Dec 14 10:04:51 2013 +0100 @@ -18,7 +18,7 @@ ## along with Gajim. If not, see http://www.gnu.org/licenses/.
-import locale, random +import locale from hashlib import sha1 from .transports_nb import NonBlockingTransport, NonBlockingHTTPBOSH,\ CONNECTED, CONNECTING, DISCONNECTED, DISCONNECTING,\ @@ -29,6 +29,8 @@ import logging log = logging.getLogger('nbxmpp.bosh')
+import rndg + KEY_COUNT = 10
# Fake file descriptor - it's used for setting read_timeout in idlequeue for @@ -486,9 +488,7 @@ # to 7881299347898368 messages to raise rid over 2**53 # (see http://www.xmpp.org/extensions/xep-0124.html#rids) # it's also used for sequence key initialization - r = random.Random() - r.seed() - return r.getrandbits(50) + return rndg.getrandbits(50)
diff -r 9486848a00ed -r ee5bca6b1591 nbxmpp/rndg.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nbxmpp/rndg.py Sat Dec 14 10:04:51 2013 +0100 @@ -0,0 +1,49 @@ +## rndg.py +## +## cryptographically secure pseudo-random number generator. +## When possible use OpenSSL PRNG combined with os.random, +## if OpenSSL PRNG is not available, use only os.random. +## +## Copyright (C) 2013 Fedor Brunner fedor.brunner@azet.sk +## +## This file is part of Gajim. +## +## Gajim is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published +## by the Free Software Foundation; version 3 only. +## +## Gajim is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Gajim. If not, see http://www.gnu.org/licenses/. + +USE_PYOPENSSL = False +try: + import OpenSSL.rand + import binascii, os + USE_PYOPENSSL = True +except ImportError: + import random + +if not USE_PYOPENSSL: + getrandbits = random.SystemRandom().getrandbits +else: + def getrandbits(k): + """getrandbits(k) -> x. Generates a long int with k random bits.""" + if k <= 0: + raise ValueError('number of bits must be greater than zero') + if k != int(k): + raise TypeError('number of bits should be an integer') + + bytes = (k + 7) // 8 # bits / 8 and rounded up + + # Add system entropy to OpenSSL PRNG + OpenSSL.rand.add(os.urandom(bytes), bytes) + # Extract random bytes from OpenSSL PRNG + random_str = OpenSSL.rand.bytes(bytes) + + x = long(binascii.hexlify(random_str), 16) + return x >> (bytes * 8 - k) # trim excess bits