~vishvananda/nova/network-refactor

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/python/randbytes.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- test-case-name: twisted.test.test_randbytes -*-
 
2
# Copyright (c) 2007 Twisted Matrix Laboratories.
 
3
# See LICENSE for details.
 
4
 
 
5
"""
 
6
Cryptographically secure random implementation, with fallback on normal random.
 
7
"""
 
8
 
 
9
# System imports
 
10
import warnings, os, random
 
11
 
 
12
getrandbits = getattr(random, 'getrandbits', None)
 
13
 
 
14
try:
 
15
    from Crypto.Util import randpool
 
16
except ImportError:
 
17
    randpool = None
 
18
 
 
19
 
 
20
 
 
21
class SecureRandomNotAvailable(RuntimeError):
 
22
    """
 
23
    Exception raised when no secure random algorithm is found.
 
24
    """
 
25
 
 
26
 
 
27
 
 
28
class SourceNotAvailable(RuntimeError):
 
29
    """
 
30
    Internal exception used when a specific random source is not available.
 
31
    """
 
32
 
 
33
 
 
34
 
 
35
class RandomFactory(object):
 
36
    """
 
37
    Factory providing L{secureRandom} and L{insecureRandom} methods.
 
38
 
 
39
    You shouldn't have to instantiate this class, use the module level
 
40
    functions instead: it is an implementation detail and could be removed or
 
41
    changed arbitrarily.
 
42
 
 
43
    @ivar randomPool: pool of random data.
 
44
    @type randomPool: C{randpool.RandomPool}
 
45
 
 
46
    @cvar randomSources: list of file sources used when os.urandom is not
 
47
        available.
 
48
    @type randomSources: C{tuple}
 
49
    """
 
50
    randpool = randpool
 
51
    randomPool = None
 
52
    randomSources = ('/dev/urandom',)
 
53
    getrandbits = getrandbits
 
54
 
 
55
 
 
56
    def _osUrandom(self, nbytes):
 
57
        """
 
58
        Wrapper around C{os.urandom} that cleanly manage its absence.
 
59
        """
 
60
        try:
 
61
            return os.urandom(nbytes)
 
62
        except (AttributeError, NotImplementedError), e:
 
63
            raise SourceNotAvailable(e)
 
64
 
 
65
 
 
66
    def _fileUrandom(self, nbytes):
 
67
        """
 
68
        Wrapper around random file sources.
 
69
 
 
70
        This method isn't meant to be call out of the class and could be
 
71
        removed arbitrarily.
 
72
        """
 
73
        for src in self.randomSources:
 
74
            try:
 
75
                f = file(src, 'rb')
 
76
            except (IOError, OSError):
 
77
                pass
 
78
            else:
 
79
                bytes = f.read(nbytes)
 
80
                f.close()
 
81
                return bytes
 
82
        raise SourceNotAvailable("File sources not available: %s" %
 
83
                                 (self.randomSources,))
 
84
 
 
85
 
 
86
    def _cryptoRandom(self, nbytes):
 
87
        """
 
88
        Wrapper around Crypo random pool.
 
89
        """
 
90
        if self.randpool is not None:
 
91
            if self.randomPool is None:
 
92
                self.randomPool = self.randpool.RandomPool()
 
93
                self.randomPool.stir()
 
94
            return self.randomPool.get_bytes(nbytes)
 
95
        raise SourceNotAvailable("PyCrypto isn't installed")
 
96
 
 
97
 
 
98
    def secureRandom(self, nbytes, fallback=False):
 
99
        """
 
100
        Return a number of secure random bytes.
 
101
 
 
102
        @param nbytes: number of bytes to generate.
 
103
        @type nbytes: C{int}
 
104
        @param fallback: Whether the function should fallback on non-secure
 
105
            random or not.  Default to C{False}.
 
106
        @type fallback: C{bool}
 
107
 
 
108
        @return: a string of random bytes.
 
109
        @rtype: C{str}
 
110
        """
 
111
        for src in ("_osUrandom", "_fileUrandom", "_cryptoRandom"):
 
112
            try:
 
113
                return getattr(self, src)(nbytes)
 
114
            except SourceNotAvailable:
 
115
                pass
 
116
        if fallback:
 
117
            warnings.warn(
 
118
                "Neither PyCrypto nor urandom available - "
 
119
                "proceeding with non-cryptographically secure random source",
 
120
                category=RuntimeWarning,
 
121
                stacklevel=2
 
122
            )
 
123
            return self.insecureRandom(nbytes)
 
124
        else:
 
125
            raise SecureRandomNotAvailable("No secure random source available")
 
126
 
 
127
 
 
128
    def _randBits(self, nbytes):
 
129
        """
 
130
        Wrapper around C{os.getrandbits}.
 
131
        """
 
132
        if self.getrandbits is not None:
 
133
            n = self.getrandbits(nbytes * 8)
 
134
            hexBytes = ("%%0%dx" % (nbytes * 2)) % n
 
135
            return hexBytes.decode('hex')
 
136
        raise SourceNotAvailable("random.getrandbits is not available")
 
137
 
 
138
 
 
139
    def _randRange(self, nbytes):
 
140
        """
 
141
        Wrapper around C{random.randrange}.
 
142
        """
 
143
        bytes = ""
 
144
        for i in xrange(nbytes):
 
145
            bytes += chr(random.randrange(0, 255))
 
146
        return bytes
 
147
 
 
148
 
 
149
    def insecureRandom(self, nbytes):
 
150
        """
 
151
        Return a number of non secure random bytes.
 
152
 
 
153
        @param nbytes: number of bytes to generate.
 
154
        @type nbytes: C{int}
 
155
 
 
156
        @return: a string of random bytes.
 
157
        @rtype: C{str}
 
158
        """
 
159
        for src in ("_randBits", "_randRange"):
 
160
            try:
 
161
                return getattr(self, src)(nbytes)
 
162
            except SourceNotAvailable:
 
163
                pass
 
164
 
 
165
 
 
166
 
 
167
factory = RandomFactory()
 
168
 
 
169
secureRandom = factory.secureRandom
 
170
 
 
171
insecureRandom = factory.insecureRandom
 
172
 
 
173
del factory
 
174
 
 
175
 
 
176
__all__ = ["secureRandom", "insecureRandom", "SecureRandomNotAvailable"]
 
177