diff options
author | Jeremy T. Bouse <jbouse@debian.org> | 2009-11-27 16:20:12 -0500 |
---|---|---|
committer | Jeremy T. Bouse <jbouse@debian.org> | 2009-11-27 16:20:12 -0500 |
commit | ed280d5ac360e2af796e9bd973d7b4df89f0c449 (patch) | |
tree | ce892d6ce9dad8c0ecbc9cbe73f8095195bef0b4 /paramiko/rng.py | |
parent | 176c6caf4ea7918e1698438634b237fab8456471 (diff) | |
download | python-paramiko-ed280d5ac360e2af796e9bd973d7b4df89f0c449.tar python-paramiko-ed280d5ac360e2af796e9bd973d7b4df89f0c449.tar.gz |
Imported Upstream version 1.7.4upstream/1.7.4
Diffstat (limited to 'paramiko/rng.py')
-rw-r--r-- | paramiko/rng.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/paramiko/rng.py b/paramiko/rng.py new file mode 100644 index 0000000..46329d1 --- /dev/null +++ b/paramiko/rng.py @@ -0,0 +1,112 @@ +#!/usr/bin/python +# -*- coding: ascii -*- +# Copyright (C) 2008 Dwayne C. Litzenberger <dlitz@dlitz.net> +# +# This file is part of paramiko. +# +# Paramiko is free software; you can redistribute it and/or modify it under the +# terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 2.1 of the License, or (at your option) +# any later version. +# +# Paramiko is distrubuted 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 Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Paramiko; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import sys +import threading +from Crypto.Util.randpool import RandomPool as _RandomPool + +try: + import platform +except ImportError: + platform = None # Not available using Python 2.2 + +def _strxor(a, b): + assert len(a) == len(b) + return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), a, b)) + +## +## Find a strong random entropy source, depending on the detected platform. +## WARNING TO DEVELOPERS: This will fail on some systems, but do NOT use +## Crypto.Util.randpool.RandomPool as a fall-back. RandomPool will happily run +## with very little entropy, thus _silently_ defeating any security that +## Paramiko attempts to provide. (This is current as of PyCrypto 2.0.1). +## See http://www.lag.net/pipermail/paramiko/2008-January/000599.html +## and http://www.lag.net/pipermail/paramiko/2008-April/000678.html +## + +if ((platform is not None and platform.system().lower() == 'windows') or + sys.platform == 'win32'): + # MS Windows + from paramiko import rng_win32 + rng_device = rng_win32.open_rng_device() +else: + # Assume POSIX (any system where /dev/urandom exists) + from paramiko import rng_posix + rng_device = rng_posix.open_rng_device() + + +class StrongLockingRandomPool(object): + """Wrapper around RandomPool guaranteeing strong random numbers. + + Crypto.Util.randpool.RandomPool will silently operate even if it is seeded + with little or no entropy, and it provides no prediction resistance if its + state is ever compromised throughout its runtime. It is also not thread-safe. + + This wrapper augments RandomPool by XORing its output with random bits from + the operating system, and by controlling access to the underlying + RandomPool using an exclusive lock. + """ + + def __init__(self, instance=None): + if instance is None: + instance = _RandomPool() + self.randpool = instance + self.randpool_lock = threading.Lock() + self.entropy = rng_device + + # Stir 256 bits of entropy from the RNG device into the RandomPool. + self.randpool.stir(self.entropy.read(32)) + self.entropy.randomize() + + def stir(self, s=''): + self.randpool_lock.acquire() + try: + self.randpool.stir(s) + finally: + self.randpool_lock.release() + self.entropy.randomize() + + def randomize(self, N=0): + self.randpool_lock.acquire() + try: + self.randpool.randomize(N) + finally: + self.randpool_lock.release() + self.entropy.randomize() + + def add_event(self, s=''): + self.randpool_lock.acquire() + try: + self.randpool.add_event(s) + finally: + self.randpool_lock.release() + + def get_bytes(self, N): + self.randpool_lock.acquire() + try: + randpool_data = self.randpool.get_bytes(N) + finally: + self.randpool_lock.release() + entropy_data = self.entropy.read(N) + result = _strxor(randpool_data, entropy_data) + assert len(randpool_data) == N and len(entropy_data) == N and len(result) == N + return result + +# vim:set ts=4 sw=4 sts=4 expandtab: |