Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/python-nbxmpp.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYann Leboulanger <asterix@lagaule.org>2013-12-14 13:04:51 +0400
committerYann Leboulanger <asterix@lagaule.org>2013-12-14 13:04:51 +0400
commitc4c7e1868968d5478c65da3af35052d51f2a41f4 (patch)
treecbc9f95443db4554ce598a2e35592056d2ef07f5
parent8eb22e12ca6366939fea39ed8f11be8df1b63dcb (diff)
[Fedor Brunner] Use better random number generator when openssl is available. Fixes #12
-rw-r--r--nbxmpp/auth_nb.py9
-rw-r--r--nbxmpp/bosh.py8
-rw-r--r--nbxmpp/rndg.py49
3 files changed, 57 insertions, 9 deletions
diff --git a/nbxmpp/auth_nb.py b/nbxmpp/auth_nb.py
index 720fac2..aaa8d0b 100644
--- a/nbxmpp/auth_nb.py
+++ b/nbxmpp/auth_nb.py
@@ -27,7 +27,6 @@ from .protocol import Node, NodeProcessed, isResultNode, Iq, Protocol, JID
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 hashlib
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 @@ class SASL(PlugIn):
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 @@ class SASL(PlugIn):
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 --git a/nbxmpp/bosh.py b/nbxmpp/bosh.py
index 47b1784..6eb5877 100644
--- a/nbxmpp/bosh.py
+++ b/nbxmpp/bosh.py
@@ -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 @@ from .simplexml import Node
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 @@ def get_rand_number():
# 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 --git a/nbxmpp/rndg.py b/nbxmpp/rndg.py
new file mode 100644
index 0000000..42d1851
--- /dev/null
+++ b/nbxmpp/rndg.py
@@ -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