From 23c965e7864bd9f37cf2c6076895c9bec395f00c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 25 Jul 2017 10:33:17 -0400 Subject: Delete rand.py (#675) --- CHANGELOG.rst | 4 ++ src/OpenSSL/__init__.py | 4 +- src/OpenSSL/rand.py | 169 ----------------------------------------------- tests/test_rand.py | 172 ------------------------------------------------ 4 files changed, 6 insertions(+), 343 deletions(-) delete mode 100644 src/OpenSSL/rand.py delete mode 100644 tests/test_rand.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7b2f4db..213c397 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,10 @@ Backward-incompatible changes: - Dropped support for Python 3.3. `#677 `_ +- Removed the deprecated ``OpenSSL.rand`` module. + This is being done ahead of our normal deprecation schedule due to its lack of use and the fact that it was becoming a maintenance burden. + ``os.urandom()`` should be used instead. + `#675 `_ Deprecations: diff --git a/src/OpenSSL/__init__.py b/src/OpenSSL/__init__.py index b827e3c..810d00d 100644 --- a/src/OpenSSL/__init__.py +++ b/src/OpenSSL/__init__.py @@ -5,7 +5,7 @@ pyOpenSSL - A simple wrapper around the OpenSSL library """ -from OpenSSL import rand, crypto, SSL +from OpenSSL import crypto, SSL from OpenSSL.version import ( __author__, __copyright__, __email__, __license__, __summary__, __title__, __uri__, __version__, @@ -13,7 +13,7 @@ from OpenSSL.version import ( __all__ = [ - "SSL", "crypto", "rand", + "SSL", "crypto", "__author__", "__copyright__", "__email__", "__license__", "__summary__", "__title__", "__uri__", "__version__", diff --git a/src/OpenSSL/rand.py b/src/OpenSSL/rand.py deleted file mode 100644 index e2f6373..0000000 --- a/src/OpenSSL/rand.py +++ /dev/null @@ -1,169 +0,0 @@ -""" -PRNG management routines, thin wrappers. -""" - -import warnings -from functools import partial - -from six import integer_types as _integer_types - -from OpenSSL._util import ( - ffi as _ffi, - lib as _lib, - exception_from_error_queue as _exception_from_error_queue, - path_string as _path_string) - - -warnings.warn( - "OpenSSL.rand is deprecated - you should use os.urandom instead", - DeprecationWarning, stacklevel=3 -) - - -class Error(Exception): - """ - An error occurred in an :mod:`OpenSSL.rand` API. - - If the current RAND method supports any errors, this is raised when needed. - The default method does not raise this when the entropy pool is depleted. - - Whenever this exception is raised directly, it has a list of error messages - from the OpenSSL error queue, where each item is a tuple *(lib, function, - reason)*. Here *lib*, *function* and *reason* are all strings, describing - where and what the problem is. - - See :manpage:`err(3)` for more information. - """ - - -_raise_current_error = partial(_exception_from_error_queue, Error) - -_unspecified = object() - -_builtin_bytes = bytes - - -def bytes(num_bytes): - """ - Get some random bytes from the PRNG as a string. - - This is a wrapper for the C function ``RAND_bytes``. - - :param num_bytes: The number of bytes to fetch. - - :return: A string of random bytes. - """ - if not isinstance(num_bytes, _integer_types): - raise TypeError("num_bytes must be an integer") - - if num_bytes < 0: - raise ValueError("num_bytes must not be negative") - - result_buffer = _ffi.new("unsigned char[]", num_bytes) - result_code = _lib.RAND_bytes(result_buffer, num_bytes) - if result_code == -1: - # TODO: No tests for this code path. Triggering a RAND_bytes failure - # might involve supplying a custom ENGINE? That's hard. - _raise_current_error() - - return _ffi.buffer(result_buffer)[:] - - -def add(buffer, entropy): - """ - Mix bytes from *string* into the PRNG state. - - The *entropy* argument is (the lower bound of) an estimate of how much - randomness is contained in *string*, measured in bytes. - - For more information, see e.g. :rfc:`1750`. - - :param buffer: Buffer with random data. - :param entropy: The entropy (in bytes) measurement of the buffer. - - :return: :obj:`None` - """ - if not isinstance(buffer, _builtin_bytes): - raise TypeError("buffer must be a byte string") - - if not isinstance(entropy, int): - raise TypeError("entropy must be an integer") - - # TODO Nothing tests this call actually being made, or made properly. - _lib.RAND_add(buffer, len(buffer), entropy) - - -def seed(buffer): - """ - Equivalent to calling :func:`add` with *entropy* as the length of *buffer*. - - :param buffer: Buffer with random data - - :return: :obj:`None` - """ - if not isinstance(buffer, _builtin_bytes): - raise TypeError("buffer must be a byte string") - - # TODO Nothing tests this call actually being made, or made properly. - _lib.RAND_seed(buffer, len(buffer)) - - -def status(): - """ - Check whether the PRNG has been seeded with enough data. - - :return: 1 if the PRNG is seeded enough, 0 otherwise. - """ - return _lib.RAND_status() - - -def cleanup(): - """ - Erase the memory used by the PRNG. - - This is a wrapper for the C function ``RAND_cleanup``. - - :return: :obj:`None` - """ - # TODO Nothing tests this call actually being made, or made properly. - _lib.RAND_cleanup() - - -def load_file(filename, maxbytes=_unspecified): - """ - Read *maxbytes* of data from *filename* and seed the PRNG with it. - - Read the whole file if *maxbytes* is not specified or negative. - - :param filename: The file to read data from (``bytes`` or ``unicode``). - :param maxbytes: (optional) The number of bytes to read. Default is to - read the entire file. - - :return: The number of bytes read - """ - filename = _path_string(filename) - - if maxbytes is _unspecified: - maxbytes = -1 - elif not isinstance(maxbytes, int): - raise TypeError("maxbytes must be an integer") - - return _lib.RAND_load_file(filename, maxbytes) - - -def write_file(filename): - """ - Write a number of random bytes (currently 1024) to the file *path*. This - file can then be used with :func:`load_file` to seed the PRNG again. - - :param filename: The file to write data to (``bytes`` or ``unicode``). - - :return: The number of bytes written. - """ - filename = _path_string(filename) - return _lib.RAND_write_file(filename) - - -# TODO There are no tests for the RAND strings being loaded, whatever that -# means. -_lib.ERR_load_RAND_strings() diff --git a/tests/test_rand.py b/tests/test_rand.py deleted file mode 100644 index 41a4f27..0000000 --- a/tests/test_rand.py +++ /dev/null @@ -1,172 +0,0 @@ -# Copyright (c) Frederick Dean -# See LICENSE for details. - -""" -Unit tests for `OpenSSL.rand`. -""" - -import os -import stat -import sys - -import pytest - -from OpenSSL import rand - -from .util import NON_ASCII - - -class TestRand(object): - - @pytest.mark.parametrize('args', [ - (None,), - (b"foo",), - ]) - def test_bytes_wrong_args(self, args): - """ - `OpenSSL.rand.bytes` raises `TypeError` if called with a non-`int` - argument. - """ - with pytest.raises(TypeError): - rand.bytes(*args) - - def test_insufficient_memory(self): - """ - `OpenSSL.rand.bytes` raises `MemoryError` or `OverflowError` if more - bytes are requested than will fit in memory. - """ - with pytest.raises((MemoryError, OverflowError)): - rand.bytes(sys.maxsize + 1) - - def test_bytes(self): - """ - Verify that we can obtain bytes from rand_bytes() and that they are - different each time. Test the parameter of rand_bytes() for - bad values. - """ - b1 = rand.bytes(50) - assert len(b1) == 50 - b2 = rand.bytes(num_bytes=50) # parameter by name - assert b1 != b2 # Hip, Hip, Horay! FIPS complaince - b3 = rand.bytes(num_bytes=0) - assert len(b3) == 0 - with pytest.raises(ValueError) as exc: - rand.bytes(-1) - assert str(exc.value) == "num_bytes must not be negative" - - @pytest.mark.parametrize('args', [ - (b"foo", None), - (None, 3), - ]) - def test_add_wrong_args(self, args): - """ - `OpenSSL.rand.add` raises `TypeError` if called with arguments not of - type `str` and `int`. - """ - with pytest.raises(TypeError): - rand.add(*args) - - def test_add(self): - """ - `OpenSSL.rand.add` adds entropy to the PRNG. - """ - rand.add(b'hamburger', 3) - - @pytest.mark.parametrize('args', [ - (None,), - (42,), - ]) - def test_seed_wrong_args(self, args): - """ - `OpenSSL.rand.seed` raises `TypeError` if called with - a non-`str` argument. - """ - with pytest.raises(TypeError): - rand.seed(*args) - - def test_seed(self): - """ - `OpenSSL.rand.seed` adds entropy to the PRNG. - """ - rand.seed(b'milk shake') - - def test_status(self): - """ - `OpenSSL.rand.status` returns `1` if the PRNG has sufficient entropy, - `0` otherwise. - """ - # It's hard to know what it is actually going to return. Different - # OpenSSL random engines decide differently whether they have enough - # entropy or not. - assert rand.status() in (0, 1) - - def test_cleanup(self): - """ - `OpenSSL.rand.cleanup` releases the memory used by the PRNG and - returns `None`. - """ - assert rand.cleanup() is None - - @pytest.mark.parametrize('args', [ - ("foo", None), - (None, 1), - ]) - def test_load_file_wrong_args(self, args): - """ - `OpenSSL.rand.load_file` raises `TypeError` when with arguments - not of type `str` and `int`. - """ - with pytest.raises(TypeError): - rand.load_file(*args) - - @pytest.mark.parametrize('args', [ - None, - 1, - ]) - def test_write_file_wrong_args(self, args): - """ - `OpenSSL.rand.write_file` raises `TypeError` when called with - a non-`str` argument. - """ - with pytest.raises(TypeError): - rand.write_file(*args) - - def _read_write_test(self, path): - """ - Verify that ``rand.write_file`` and ``rand.load_file`` can be used. - """ - # Create the file so cleanup is more straightforward - with open(path, "w"): - pass - - try: - # Write random bytes to a file - rand.write_file(path) - - # Verify length of written file - size = os.stat(path)[stat.ST_SIZE] - assert size == 1024 - - # Read random bytes from file - rand.load_file(path) - rand.load_file(path, 4) # specify a length - finally: - # Cleanup - os.unlink(path) - - def test_bytes_paths(self, tmpfile): - """ - Random data can be saved and loaded to files with paths specified as - bytes. - """ - path = tmpfile - path += NON_ASCII.encode(sys.getfilesystemencoding()) - self._read_write_test(path) - - def test_unicode_paths(self, tmpfile): - """ - Random data can be saved and loaded to files with paths specified as - unicode. - """ - path = tmpfile.decode('utf-8') + NON_ASCII - self._read_write_test(path) -- cgit v1.2.1