summaryrefslogtreecommitdiff
path: root/src/M2Crypto/Rand.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/M2Crypto/Rand.py')
-rw-r--r--src/M2Crypto/Rand.py146
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