Commit graph

26 commits

Author SHA1 Message Date
Legrandin
d8aa3d30d6 Remove Crypto.Random.Fortuna 2015-01-05 23:06:22 +01:00
Legrandin
a9df7886a9 Update epydoc configuration and remove warnings 2014-06-16 20:36:36 +02:00
Legrandin
afd6328f9c Simplify the random number generator
Replace the user-space RNG with a thin wrapper to os.urandom.
Remove all OS-specific RNG modules.
2014-06-16 20:36:35 +02:00
Legrandin
d83380a048 Removed support for Python<2.4 2014-06-16 20:36:35 +02:00
Dwayne Litzenberger
d044a47833 This is the PyCrypto 2.6.1 release.
-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iFYEABEKAAYFAlJcZFMACgkQm4qoyix3/7Df6wDfUkS+QVyb7quQJrBiLi3jLAin
 Otvcc25QTHgoTADePAglh6rbEOMNdyNUFinTeV1qwkOm/Q3YRiyiLA==
 =XujS
 -----END PGP SIGNATURE-----

Merge tag 'v2.6.1' (fix CVE-2013-1445)

This is the PyCrypto 2.6.1 release.

Dwayne Litzenberger (4):
      Random: Make Crypto.Random.atfork() set last_reseed=None (CVE-2013-1445)
      Fortuna: Add comments for reseed_interval and min_pool_size to FortunaAccumulator
      Update the ChangeLog
      Release v2.6.1
2013-10-20 13:28:46 -07:00
Dwayne Litzenberger
fa06af7fea Fortuna: Add comments for reseed_interval and min_pool_size to FortunaAccumulator 2013-10-14 14:37:36 -07:00
Dwayne Litzenberger
19dcf7b15d Random: Make Crypto.Random.atfork() set last_reseed=None (CVE-2013-1445)
== Summary ==

In PyCrypto before v2.6.1, the Crypto.Random pseudo-random number
generator (PRNG) exhibits a race condition that may cause it to generate
the same 'random' output in multiple processes that are forked from each
other.  Depending on the application, this could reveal sensitive
information or cryptographic keys to remote attackers.

An application may be affected if, within 100 milliseconds, it performs
the following steps (which may be summarized as "read-fork-read-read"):

1. Read from the Crypto.Random PRNG, causing an internal reseed;
2. Fork the process and invoke Crypto.Random.atfork() in the child;
3. Read from the Crypto.Random PRNG again, in at least two different
   processes (parent and child, or multiple children).

Only applications that invoke Crypto.Random.atfork() and perform the
above steps are affected by this issue.  Other applications are
unaffected.

Note: Some PyCrypto functions, such as key generation and PKCS#1-related
functions, implicitly read from the Crypto.Random PRNG.

== Technical details ==

Crypto.Random uses Fortuna[1] to generate random numbers.  The flow of
entropy looks something like this:

    /dev/urandom  -\
                    +-> "accumulator" --> "generator" --> output
    other sources -/   (entropy pools)     (AES-CTR)

- The "accumulator" maintains several pools that collect entropy from
  the environment.

- The "generator" is a deterministic PRNG that is reseeded by the
  accumulator.  Reseeding normally occurs during each request for random
  numbers, but never more than once every 100 ms (the "minimum reseed
  interval").

When a process is forked, the parent's state is duplicated in the child.
In order to continue using the PRNG, the child process must invoke
Crypto.Random.atfork(), which collects new entropy from /dev/urandom and
adds it to the accumulator.  When new PRNG output is subsequently
requested, some of the new entropy in the accumulator is used to reseed
the generator, causing the output of the child to diverge from its
parent.

However, in previous versions of PyCrypto, Crypto.Random.atfork() did
not explicitly reset the child's rate-limiter, so if the child requested
PRNG output before the minimum reseed interval of 100 ms had elapsed, it
would generate its output using state inherited from its parent.

This created a race condition between the parent process and its forked
children that could cause them to produce identical PRNG output for the
duration of the 100 ms minimum reseed interval.

== Demonstration ==

Here is some sample code that illustrates the problem:

    from binascii import hexlify
    import multiprocessing, pprint, time
    import Crypto.Random

    def task_main(arg):
        a = Crypto.Random.get_random_bytes(8)
        time.sleep(0.1)
        b = Crypto.Random.get_random_bytes(8)
        rdy, ack = arg
        rdy.set()
        ack.wait()
        return "%s,%s" % (hexlify(a).decode(),
                          hexlify(b).decode())

    n_procs = 4
    manager = multiprocessing.Manager()
    rdys = [manager.Event() for i in range(n_procs)]
    acks = [manager.Event() for i in range(n_procs)]
    Crypto.Random.get_random_bytes(1)
    pool = multiprocessing.Pool(processes=n_procs,
                                initializer=Crypto.Random.atfork)
    res_async = pool.map_async(task_main, zip(rdys, acks))
    pool.close()
    [rdy.wait() for rdy in rdys]
    [ack.set() for ack in acks]
    res = res_async.get()
    pprint.pprint(sorted(res))
    pool.join()

The output should be random, but it looked like this:

    ['c607803ae01aa8c0,2e4de6457a304b34',
     'c607803ae01aa8c0,af80d08942b4c987',
     'c607803ae01aa8c0,b0e4c0853de927c4',
     'c607803ae01aa8c0,f0362585b3fceba4']

== Solution ==

The solution is to upgrade to PyCrypto v2.6.1 or later, which properly
resets the rate-limiter when Crypto.Random.atfork() is invoked in the
child.

== References ==

[1] N. Ferguson and B. Schneier, _Practical Cryptography_,
    Indianapolis: Wiley, 2003, pp. 155-184.
2013-10-14 14:37:35 -07:00
Jason R. Coombs
10abfc8633 Fix error importing winrandom on Python 3
On Python 3, 'import winrandom' cannot be automatically converted to the relative import, so fails. This change fixes that behavior.
2013-05-25 01:22:15 -03:00
Dwayne Litzenberger
22d7760ae7 FortunaAccumulator: Use time.monotonic if available (i.e. Python 3.3 and later) 2013-04-21 23:24:23 -07:00
Dwayne Litzenberger
4e4cc0beef Fix dumb typo: "is 2" should be "== 2" 2013-02-17 19:00:50 -08:00
Dwayne Litzenberger
14ef4933c9 Fix LP#1061217: random.shuffle takes O(n^2) time
The previous implementation took O(n**2) time and O(n) auxiliary space.
We now use the Fisher-Yates algorithm, which takes O(n) time and O(1)
space.

Thanks to Sujay Jayakar and Andrew Cooke for pointing this out and
suggesting a solution.

Bug report: https://bugs.launchpad.net/pycrypto/+bug/1061217
2013-02-16 10:50:03 -08:00
Sebastian Ramacher
95d65366e9 Fix DevURandomRNG to work with Python3's new I/O stack. 2012-04-21 12:59:49 -04:00
Legrandin
114ca5b4d4 Merge from upstream 2011-12-22 14:55:40 +01:00
Dwayne C. Litzenberger
094d70b64d Python 3.x fixes:
- Use absolute imports
- Fix StringIO import so that 2to3 can translate it
2011-10-22 15:07:47 -04:00
Legrandin
c22fa18c0d Merged from upstream (py3k support) and modified so that all unit tests pass. 2011-10-18 23:20:26 +02:00
Legrandin
07e9e97e9d Add new() method to all remaining hash algorithms, so as to make them to work with PKCS#1 PSS. Add also test cases for it for every hash. 2011-02-07 22:32:49 +01:00
Thorsten Behrens
60896cc61a Fix AllOrNothing and random.sample()
o AllOrNothing no longer fails occasionally. Patch by Lorenz Quack
o random.sample() works on Python 2.1. Patch by Paul Koning and Lorenz
  Quack
2011-01-06 07:18:12 -05:00
Thorsten Behrens
b27696462b Improve random selftest
o Random selftest is improved, less likely to collide
o random.shuffle() is more pythonic
2011-01-05 07:54:04 -05:00
Thorsten Behrens
5dc2f8f216 Add unit tests for Crypto.Random.random
o Add unit tests
o Fix random.shuffle()
o random.sample() does not work on 2.1. This has not been fixed.
2010-12-31 00:15:34 -05:00
Thorsten Behrens
cb48387f66 PY3K _fastmath support
o _fastmath now builds and runs on PY3K
o Changes to setup.py to allow /usr/include for gmp.h
o Changes to setup.py to allow linking fastmath w/ static mpir
  on Windows without warning messages
o Changes to test_DSA/test_RSA to throw an exception if _fastmath
  is present but cannot be imported (due to an issue building
  _fastmath or the shared gmp/mpir libraries not being reachable)
o number.py has the code to flag a failing _fastmath, but that
  code is commented out for a better runtime experience
o Clean up the if for py21compat import - should have been == not is
o Clean up some '== None' occurences, now 'is None' instead
2010-12-29 13:21:05 -05:00
Thorsten Behrens
295ce314d9 Changes to allow pycrpyto to work on Python 3.x as well as 2.1 through 2.7 2010-12-28 16:26:52 -05:00
Dwayne C. Litzenberger
02e3976a18 Random: Improve the comment attached to _UserFriendlyRNG#_check_pid 2009-08-28 12:27:52 -04:00
Dwayne C. Litzenberger
d5d88413fc Random: Add Crypto.Random.get_random_bytes()
This should allow people to use something like this if they want
backwards-compatibility:

try:
     from Crypto.Random import get_random_bytes
except ImportError:
     try:
         from os import urandom as get_random_bytes
     except ImportError:
         get_random_bytes = open("/dev/urandom", "rb").read
2009-08-28 12:10:25 -04:00
Dwayne C. Litzenberger
a94b21dcb3 Random: Remove RandomPoolCompat
RandomPoolCompat seems to give people the wrong idea that it's okay to use
RandomPool if Crypto.Random is not available.

    try:
      from Crypto.Random import RandomPoolCompat as RandomPool
    except ImportError:
      from Crypto.Util.randpool import RandomPool

In order to discourage all use of RandomPool, I'm getting rid of
RandomPoolCompat.  Instead, Crypto.Util.randpool.RandomPool will be a wrapper
around Crypto.Random that emits a DeprecationWarning.
2009-08-28 12:10:24 -04:00
Dwayne C. Litzenberger
386de1947b Legal: Dedicate my files to the public domain.
In an attempt to simplify the copyright status of PyCrypto, I'm placing my
code into the public domain, and encouraging other contributors to do the
same.

I have used a public domain dedication that was recommended in a book on FOSS legal
issues[1], followed by the warranty disclaimer boilerplate from the MIT license.

[1] _Intellectual Property and Open Source: A Practical Guide to Protecting
    Code_, a book written by Van Lindberg and published by O'Reilly Media.
    (ISBN 978-0-596-51796-0)
2009-03-01 10:22:51 -05:00
Dwayne C. Litzenberger
ff8a657a8d cleanup: Move modules to "lib/Crypto" subdirectory.
This will avoid the previous situation where scripts like the old "test.py"
get included accidentally in a release.  It also frees us to put additional
build scripts in the top-level directory of the source tree.
2009-02-28 13:14:53 -05:00