paramiko.osrandom

Package paramiko :: Module osrandom |
[frames] | no frames]

# Source Code for Module paramiko.osrandom

      1  #!/usr/bin/python
      2  # -*- coding: ascii -*-
      3  # Copyright (C) 2008  Dwayne C. Litzenberger <dlitz@dlitz.net>
      4  #
      5  # This file is part of paramiko.
      6  #
      7  # Paramiko is free software; you can redistribute it and/or modify it under the
      8  # terms of the GNU Lesser General Public License as published by the Free
      9  # Software Foundation; either version 2.1 of the License, or (at your option)
     10  # any later version.
     11  #
     12  # Paramiko is distrubuted in the hope that it will be useful, but WITHOUT ANY
     13  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     14  # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
     15  # details.
     16  #
     17  # You should have received a copy of the GNU Lesser General Public License
     18  # along with Paramiko; if not, write to the Free Software Foundation, Inc.,
     19  # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     20
     21  import sys
     22
     23  ##
     24  ## Find potential random number sources
     25  ##
     26
     27  # Try to open /dev/urandom now so that paramiko will be able to access
     28  # it even if os.chroot() is invoked later.
     29  try:
     30      _dev_urandom = open("/dev/urandom", "rb", 0)
     31  except EnvironmentError:
     32      _dev_urandom = None
     33
     34  # Try to import the "winrandom" module
     35  try:
     36      from Crypto.Util import winrandom
     37  except ImportError:
     38      winrandom = None
     39
     40  # Lastly, try to get the plain "RandomPool"
     41  # (sometimes windows doesn't even have winrandom!)
     42  try:
     43      from Crypto.Util.randpool import RandomPool
     44  except ImportError:
     45      RandomPool = None
     46
     47
     48  ##
     49  ## Define RandomPool classes
     50  ##
     51
     52 -def _workaround_windows_cryptgenrandom_bug(self):
     53      # According to "Cryptanalysis of the Random Number Generator of the
     54      # Windows Operating System", by Leo Dorrendorf and Zvi Gutterman
     55      # and Benny Pinkas <http://eprint.iacr.org/2007/419>,
     56      # CryptGenRandom only updates its internal state using kernel-provided
     57      # random data every 128KiB of output.
     58      self.get_bytes(128*1024)    # discard 128 KiB of output
     59
     60
     61 -class BaseOSRandomPool(object):
     62 -    def __init__(self, numbytes=160, cipher=None, hash=None):
     63          pass
     64
     65 -    def stir(self, s=''):
     66          pass
     67
     68 -    def randomize(self, N=0):
     69          self.stir()
     70
     71 -    def add_event(self, s=None):
     72          pass
     73
     74
     75 -class WinRandomPool(BaseOSRandomPool):
     76      """RandomPool that uses the C{winrandom} module for input"""
     77 -    def __init__(self, numbytes=160, cipher=None, hash=None):
     78          self._wr = winrandom.new()
     79          self.get_bytes = self._wr.get_bytes
     80          self.randomize()
     81
     82 -    def stir(self, s=''):
     83          _workaround_windows_cryptgenrandom_bug(self)
     84
     85
     86 -class DevUrandomPool(BaseOSRandomPool):
     87      """RandomPool that uses the C{/dev/urandom} special device node for input"""
     88 -    def __init__(self, numbytes=160, cipher=None, hash=None):
     89          self.randomize()
     90
     91 -    def get_bytes(self, n):
     92          bytes = ""
     93          while len(bytes) < n:
     94              bytes += _dev_urandom.read(n - len(bytes))
     95          return bytes
     96
     97
     98 -class FallbackRandomPool (BaseOSRandomPool):
     99 -    def __init__(self):
    100          self._wr = RandomPool()
    101          self.randomize()
    102
    103 -    def get_bytes(self, n):
    104          return self._wr.get_bytes(n)
    105
    106
    107  ##
    108  ## Detect default random number source
    109  ##
    110  osrandom_source = None
    111
    112  # Try /dev/urandom
    113  if osrandom_source is None and _dev_urandom is not None:
    114      osrandom_source = "/dev/urandom"
    115      DefaultRandomPoolClass = DevUrandomPool
    116
    117  # Try winrandom
    118  if osrandom_source is None and winrandom is not None:
    119      osrandom_source = "winrandom"
    120      DefaultRandomPoolClass = WinRandomPool
    121
    122  # Try final fallback
    123  if osrandom_source is None and RandomPool is not None:
    124      osrandom_source = "randompool"
    125      DefaultRandomPoolClass = FallbackRandomPool
    126
    127  # Give up
    128  if osrandom_source is None:
    129      raise ImportError("Cannot find OS entropy source")
    130
    131
    132  ##
    133  ## Define wrapper class
    134  ##
    135
    136 -class OSRandomPool(object):
    137      """RandomPool wrapper.
    138
    139      The C{randpool} attribute of this object may be modified by users of this class at runtime.
    140      """
    141
    142 -    def __init__(self, instance=None):
    143          if instance is None:
    144              instance = DefaultRandomPoolClass()
    145          self.randpool = instance
    146
    147 -    def stir(self, s=''):
    148          self.randpool.stir(s)
    149
    150 -    def randomize(self, N=0):
    151          self.randpool.randomize(N)
    152
    153 -    def add_event(self, s=None):
    154          self.randpool.add_event(s)
    155
    156 -    def get_bytes(self, N):
    157          return self.randpool.get_bytes(N)
    158
    159  # vim:set ts=4 sw=4 sts=4 expandtab:
    160