diff options
Diffstat (limited to 'src/M2Crypto/Rand.py')
-rw-r--r-- | src/M2Crypto/Rand.py | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/M2Crypto/Rand.py b/src/M2Crypto/Rand.py new file mode 100644 index 0000000..a178b1b --- /dev/null +++ b/src/M2Crypto/Rand.py @@ -0,0 +1,146 @@ +"""M2Crypto wrapper for OpenSSL PRNG. Requires OpenSSL 0.9.5 and above. + +Copyright (c) 1999-2003 Ng Pheng Siong. All rights reserved. +Copyright (c) 2014-2017 Matej Cepl. All rights reserved. + +See LICENCE for the license information. +""" +from __future__ import absolute_import + +from M2Crypto import m2, six +from typing import AnyStr, Tuple # noqa + + +__all__ = ['rand_seed', 'rand_add', 'load_file', 'save_file', 'rand_bytes', + 'rand_pseudo_bytes', 'rand_file_name', 'rand_status'] + + +class RandError(ValueError): + pass + +m2.rand_init(RandError) + + +def rand_add(blob, entropy): + # type: (bytes, float) -> None + """ + Mixes blob into the PRNG state. + + :param blob: added data + :param entropy: (the lower bound of) an estimate of how much randomness + is contained in blob, measured in bytes. + + Thus, if the data at buf are unpredictable to an adversary, this + increases the uncertainty about the state and makes the PRNG output less + predictable. Suitable input comes from user interaction (random key + presses, mouse movements) and certain hardware events. + + Details about sources of randomness and how to estimate their entropy + can be found in the literature, e.g. RFC 1750. + """ + m2.rand_add(blob, entropy) # pylint: disable=no-member + + +def rand_seed(seed): + # type: (bytes) -> None + """ + Equivalent to rand_add() when len(seed) == entropy. + + :param seed: added data (see description at rand_add) + """ + m2.rand_seed(seed) # pylint: disable=no-member + + +def rand_status(): + # type: () -> int + """ + Check whether there is enough entropy in PRNG. + + :return: 1 if the PRNG has been seeded with enough + data, 0 otherwise. + """ + return m2.rand_status() # pylint: disable=no-member + + +def rand_file_name(): + # type: () -> str + """ + Generate a default path for the random seed file. + + :return: string with the filename. + The seed file is $RANDFILE if that environment variable + is set, $HOME/.rnd otherwise. If $HOME is not set either, + an error occurs. + """ + return six.ensure_text(m2.rand_file_name()) # pylint: disable=no-member + + +def load_file(filename, max_bytes): + # type: (AnyStr, int) -> int + """ + Read a number of bytes from file filename and adds them to the PRNG. + + If max_bytes is non-negative, up to to max_bytes are read; starting with + OpenSSL 0.9.5, if max_bytes is -1, the complete file is read. + + :param filename: + :param max_bytes: + :return: the number of bytes read. + """ + return m2.rand_load_file(six.ensure_str(filename), max_bytes) # pylint: disable=no-member + + +def save_file(filename): + # type: (AnyStr) -> int + """ + Write a number of random bytes (currently 1024) to file. + + The file then can be used to initialize the PRNG by calling load_file() in + a later session. + + :param filename: + :return: returns the number of bytes written, and -1 if the bytes + written were generated without appropriate seed. + """ + return m2.rand_save_file(filename) # pylint: disable=no-member + + +def rand_bytes(num): + # type: (int) -> bytes + """ + Return n cryptographically strong pseudo-random bytes. + + An error occurs if the PRNG has not been seeded with enough randomness + to ensure an unpredictable byte sequence. + + :param num: number of bytes to be returned + :return: random bytes + """ + return m2.rand_bytes(num) # pylint: disable=no-member + + +def rand_pseudo_bytes(num): + # type: (int) -> Tuple[bytes, int] + """ + Return num pseudo-random bytes into buf. + + Pseudo-random byte sequences generated by this method will be unique + if they are of sufficient length, but are not necessarily + unpredictable. They can be used for non-cryptographic purposes and for + certain purposes in cryptographic protocols, but usually not for key + generation etc. + + Output of the function is mixed into the entropy pool before + retrieving the new pseudo-random bytes unless disabled at compile + time (see FAQ). + + :param num: number of bytes to be returned + :return: random bytes + """ + import warnings + if m2.OPENSSL_VERSION_NUMBER >= 0x10100000: + warnings.warn('The underlying OpenSSL method has been ' + + 'deprecated. Use Rand.rand_bytes instead.', + DeprecationWarning) + + return m2.rand_pseudo_bytes(num) # pylint: disable=no-member |