added support for RNGs from oqs/rand.h

added support for RNGs from oqs/rand.h

added support for RNGs from oqs/rand.h
diff --git a/.gitignore b/.gitignore
index 3e067e9..6894774 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,119 @@
 __pycache__
 liboqs.so
 *.pyc
-test-results
\ No newline at end of file
+test-results
+
+.swp
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# dotenv
+.env
+
+# virtualenv
+.venv
+venv/
+ENV/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+
+# PyCharm & virtualenv
+.idea
+bin/
+include/
+lib/
+spell/
+pip-selfcheck.json
+pyvenv.cfg
+
+# vim
+*.swp
\ No newline at end of file
diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
index 0000000..d77a849
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1,11 @@
+Version 0.2.1 - January xx, 2020
+    - Added a signature example
+    - Added partial support for RNGs from <oqs/rand.h>
+    - Added an RNG example
+
+Version 0.2.0 - October 8, 2019
+    - This release updates for compatibility with liboqs 0.2.0, which contains
+      new/updated algorithms based on NIST Round 2 submissions.
+
+Version 0.1.0 - April 23, 2019
+    - Initial release
diff --git a/LICENSE.txt b/LICENSE.txt
index 21b15ef..07bc6e8 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2018 Open Quantum Safe
+Copyright (c) 2018-2020 Open Quantum Safe
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index b1acdac..4606a95 100644
--- a/README.md
+++ b/README.md
@@ -33,25 +33,29 @@
 
 The project contains the following files:
 
- - **`oqs/wrapper.py`: a Python 3 module wrapper for the liboqs C library.**
- - `examples/example.py`: illustrates the usage of the liboqs-python wrapper.
- - `tests/test_*.py`: unit tests for the liboqs-python wrapper.
+ - **`oqs/oqs.py`: a Python 3 module wrapper for the liboqs C library.**
+ - `oqs/rand.py`: a Python 3 module supporting RNGs from `<oqs/rand.h>`
+ - `examples/kem.py`: key encapsulation example
+ - `examples/rand.py`: RNG example
+ - `examples/sig.py`: signature example
+ - `tests`: unit tests
 
 Usage
 -----
 
-liboqs-python defines two main classes: `KeyEncapsulation` and `Signature`, providing post-quantum key encapsulation and signture mechanisms, respectively. Each must be instantiated with a string identifying one of mechanisms supported by liboqs; these can be enumerated using the `get_enabled_KEM_mechanisms` and `get_enabled_sig_mechanisms` functions. The `example.py` file demonstrates the wrapper's API.
+liboqs-python defines two main classes: `KeyEncapsulation` and `Signature`, providing post-quantum key encapsulation and signture mechanisms, respectively. Each must be instantiated with a string identifying one of mechanisms supported by liboqs; these can be enumerated using the `get_enabled_KEM_mechanisms` and `get_enabled_sig_mechanisms` functions. The files in `examples/` demonstrate the wrapper's API.
+Support for alternative RNGs is provided via the `randombytes[*]` functions.
 
 liboqs installation
 -------------------
 
 liboqs-python depends on the liboqs C library; it must be compiled as a Linux/macOS library or Windows DLL, and installed in one of:
 
-- any file path specified by the `LIBOQS_INSTALL_PATH` environment variable (e.g. `LIBOQS_INSTALL_PATH="/path/to/liboqs.so"`)
+- any file path specified by the `LIBOQS_INSTALL_PATH` environment variable (e.g. `LIBOQS_INSTALL_PATH="/usr/local/bin/liboqs.so"`; **do not forget to specify `liboqs.so` at the end**)
 - system-wide folder
 - the liboqs Python module's current folder
 
-`wrapper.py` checks the above locations in that order. At present, only liboqs master branch can be installed; see the [liboqs project](https://github.com/open-quantum-safe/liboqs/) for installation instructions.
+`oqs/oqs.py` checks the above locations in that order. At present, only liboqs master branch can be installed; see the [liboqs project](https://github.com/open-quantum-safe/liboqs/) for installation instructions.
 
 liboqs-python does not depend on any other Python packages. The package isn't hosted on PyPI yet, but can be installed into a virtualenv using:
 
@@ -71,9 +75,9 @@
 
 As any python module, liboqs wrapper components can be imported into python programs with `import oqs`.
 
-To run the example program:
+To run an example program:
 
-	python3 examples/example.py
+	python3 examples/kem.py
 
 To run the unit tests with a test runner (e.g. nose or rednose (`apt install python3-nose python3-rednose` or `pip3 install nose rednose`)):
 
@@ -113,6 +117,7 @@
 
 - Ben Davies (University of Waterloo)
 - Christian Paquin (Microsoft Research)
+- Vlad Gheorghiu (evolutionQ, University of Waterloo)
 
 ### Support
 
diff --git a/RELEASE.md b/RELEASE.md
index ed92794..ff74517 100644
--- a/RELEASE.md
+++ b/RELEASE.md
@@ -1,23 +1,25 @@
-liboqs-python version 0.2.0
+liboqs-python version 0.2.1
 ===========================
 
 About
 -----
 
-The **Open Quantum Safe (OQS) project** has the goal of developing and prototyping quantum-resistant cryptography.  More information on OQS can be found on our website: https://openquantumsafe.org/ and on Github at https://github.com/open-quantum-safe/.  
+The **Open Quantum Safe (OQS) project** has the goal of developing and prototyping quantum-resistant cryptography. More information on OQS can be found on our website: https://openquantumsafe.org/ and on Github at https://github.com/open-quantum-safe/.  
 
-**liboqs** is an open source C library for quantum-resistant cryptographic algorithms.  See more about liboqs at [https://github.com/open-quantum-safe/liboqs/](https://github.com/open-quantum-safe/liboqs/), including a list of supported algorithms.
+**liboqs** is an open source C library for quantum-resistant cryptographic algorithms. See more about liboqs at [https://github.com/open-quantum-safe/liboqs/](https://github.com/open-quantum-safe/liboqs/), including a list of supported algorithms.
 
-**liboqs-python** is an open source Python 3 wrapper for the liboqs C library for quantum-resistant cryptographic algorithms.  Details about liboqs-python can be found in [README.md](https://github.com/open-quantum-safe/liboqs-python/blob/master/README.md).  See in particular limitations on intended use.
+**liboqs-python** is an open source Python 3 wrapper for the liboqs C library for quantum-resistant cryptographic algorithms. Details about liboqs-python can be found in [README.md](https://github.com/open-quantum-safe/liboqs-python/blob/master/README.md). See in particular limitations on intended use.
 
 Release notes
 =============
 
-This release of liboqs-python was released on October 8, 2019.  Its release page on GitHub is https://github.com/open-quantum-safe/liboqs-python/releases/tag/0.2.0.
+This release of liboqs-python was released on January xx, 2020. Its release page on GitHub is https://github.com/open-quantum-safe/liboqs-python/releases/tag/0.2.1.
 
 What's New
 ----------
 
-This is the second release of liboqs-python.
+This is the third release of liboqs-python. 
+This release added partial support for RNGs from `<oqs/rand.h>`, together
+with a signature example and an RNG example.
+For a list of changes see [CHANGES.txt](https://github.com/open-quantum-safe/liboqs-python/blob/master/CHANGES.txt).
 
-This release updates for compatibility with liboqs 0.2.0, which contains new/updated algorithms based on NIST Round 2 submissions.
diff --git a/examples/example.py b/examples/example.py
deleted file mode 100644
index 68c79ca..0000000
--- a/examples/example.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# illustrates how to use the python OQS wrapper
-
-from pprint import pprint
-import oqs
-
-
-#######################################################################
-# KEM example
-#######################################################################
-
-kems = oqs.get_enabled_KEM_mechanisms()
-
-print('Enabled KEM mechanisms:')
-pprint(kems)
-
-# create client and server with default KEM mechanism
-kemalg = "DEFAULT"
-with oqs.KeyEncapsulation(kemalg) as client:
-    with oqs.KeyEncapsulation(kemalg) as server:
-        print("\nStarting key encapsulation")
-        pprint(client.details)
-
-        # client generates its keypair
-        public_key = client.generate_keypair()
-        # optionally, the secret key can be obtained by calling export_secret_key()
-        # and the client can later be reinstantiated with the key pair:
-        # secret_key = client.export_secret_key()
-        # store key pair, wait... (session resumption):
-        # client = oqs.OQS_KEM(kemalg, secret_key)
-
-        # the server encapsulates its secret using the client's public key
-        ciphertext, shared_secret_server = server.encap_secret(public_key)
-
-        # the client decapsulates the the server's ciphertext to obtain the shared secret
-        shared_secret_client = client.decap_secret(ciphertext)
-
-        if shared_secret_client == shared_secret_server:
-            print("success: shared secrets are equal")
-        else:
-            print("error: shared secrets are NOT equal")
-
-print()
-
-#######################################################################
-# Signature example
-#######################################################################
-
-sigs = oqs.get_enabled_sig_mechanisms()
-
-print('Enabled Signature mechanisms:')
-pprint(sigs)
-
-# create signer and verifier with default signature mechanism
-sigalg = "DEFAULT"
-with oqs.Signature(sigalg) as signer:
-    with oqs.Signature(sigalg) as verifier:
-        print("\nStarting signature")
-        pprint(signer.details)
-
-        # the signer generates its keypair
-        signer_public_key = signer.generate_keypair()
-        # optionally, the secret key can be obtained by calling export_secret_key()
-        # and the signer can later be reinstantiated with the key pair:
-        # signer_secret_key = signer.export_secret_key()
-        # store key pair, wait... (session resumption):
-        # signer = oqs.OQS_SIG(sigalg, signer_secret_key)
-
-        # the message to sign
-        message = b'This is the message to sign'
-
-        # the signer signs the message
-        signature = signer.sign(message)
-
-        # the verifier verifies the signature on the message
-        is_valid = verifier.verify(message, signature, signer_public_key)
-
-        if is_valid:
-            print("signature is valid")
-        else:
-            print("signature is invalid")
diff --git a/examples/kem.py b/examples/kem.py
new file mode 100644
index 0000000..2890de7
--- /dev/null
+++ b/examples/kem.py
@@ -0,0 +1,36 @@
+# key encapsulation Python example
+
+from pprint import pprint
+import oqs
+
+#######################################################################
+# KEM example
+#######################################################################
+
+kems = oqs.get_enabled_KEM_mechanisms()
+
+print('Enabled KEM mechanisms:')
+pprint(kems)
+
+# create client and server with default KEM mechanisms
+kemalg = "DEFAULT"
+with oqs.KeyEncapsulation(kemalg) as client:
+    with oqs.KeyEncapsulation(kemalg) as server:
+        print("\nKey encapsulation details:")
+        pprint(client.details)
+
+        # client generates its keypair
+        public_key = client.generate_keypair()
+        # optionally, the secret key can be obtained by calling export_secret_key()
+        # and the client can later be re-instantiated with the key pair:
+        # secret_key = client.export_secret_key()
+        # store key pair, wait... (session resumption):
+        # client = oqs.KeyEncapsulation(kemalg, secret_key)
+
+        # the server encapsulates its secret using the client's public key
+        ciphertext, shared_secret_server = server.encap_secret(public_key)
+
+        # the client decapsulates the the server's ciphertext to obtain the shared secret
+        shared_secret_client = client.decap_secret(ciphertext)
+        
+        print("\nShared secretes coincide:", shared_secret_client == shared_secret_server)
diff --git a/examples/rand.py b/examples/rand.py
new file mode 100644
index 0000000..2a3c93d
--- /dev/null
+++ b/examples/rand.py
@@ -0,0 +1,23 @@
+# various RNGs Python example
+
+import oqs.rand as oqsrand  # must be explicitly imported
+
+#######################################################################
+# randomness example
+#######################################################################
+
+# set the entropy seed to some random values
+entropy_seed = [0] * 48
+entropy_seed[0] = 100
+entropy_seed[20] = 200
+entropy_seed[47] = 150
+
+oqsrand.randombytes_nist_kat_init(bytes(entropy_seed))
+oqsrand.randombytes_switch_algorithm('NIST-KAT')
+print('{:17s}'.format("NIST-KAT:"), ' '.join('{:02X}'.format(x) for x in oqsrand.randombytes(32)))
+
+oqsrand.randombytes_switch_algorithm("OpenSSL")
+print('{:17s}'.format("OpenSSL:"), ' '.join('{:02X}'.format(x) for x in oqsrand.randombytes(32)))
+
+oqsrand.randombytes_switch_algorithm("system")
+print('{:17s}'.format("System (default):"), ' '.join('{:02X}'.format(x) for x in oqsrand.randombytes(32)))
diff --git a/examples/sig.py b/examples/sig.py
new file mode 100644
index 0000000..77860aa
--- /dev/null
+++ b/examples/sig.py
@@ -0,0 +1,38 @@
+# signature Python example
+
+from pprint import pprint
+import oqs
+
+#######################################################################
+# signature example
+#######################################################################
+
+sigs = oqs.get_enabled_sig_mechanisms()
+
+print('Enabled signature mechanisms:')
+pprint(sigs)
+
+message = "This is the message to sign".encode()
+
+# create signer and verifier with default signature mechanisms
+sigalg = "DEFAULT"
+with oqs.Signature(sigalg) as signer:
+    with oqs.Signature(sigalg) as verifier:
+        print("\nSignature details:")
+        pprint(signer.details)
+
+        # signer generates its keypair
+        signer_public_key = signer.generate_keypair()
+        # optionally, the secret key can be obtained by calling export_secret_key()
+        # and the signer can later be re-instantiated with the key pair:
+        # secret_key = signer.export_secret_key()
+        # store key pair, wait... (session resumption):
+        # signer = oqs.Signature(sigalg, secret_key)
+
+        # signer signs the message
+        signature = signer.sign(message)
+
+        # verifier verifies the signature
+        is_valid = verifier.verify(message, signature, signer_public_key)
+
+        print("\nValid signature?", is_valid)
diff --git a/oqs/__init__.py b/oqs/__init__.py
index c7db430..f82845b 100644
--- a/oqs/__init__.py
+++ b/oqs/__init__.py
@@ -1,5 +1 @@
-from oqs.wrapper import KeyEncapsulation
-from oqs.wrapper import Signature
-from oqs.wrapper import MechanismNotEnabledError, MechanismNotSupportedError
-from oqs.wrapper import get_enabled_KEM_mechanisms, get_supported_KEM_mechanisms
-from oqs.wrapper import get_enabled_sig_mechanisms, get_supported_sig_mechanisms
+from oqs.oqs import *
diff --git a/oqs/wrapper.py b/oqs/oqs.py
similarity index 85%
rename from oqs/wrapper.py
rename to oqs/oqs.py
index c9739ba..9488e06 100644
--- a/oqs/wrapper.py
+++ b/oqs/oqs.py
@@ -15,13 +15,12 @@
 # import platform to learn the OS we're on
 import platform
 
-
-LIBOQS_SHARED_OBJ = 'oqs' if platform.system() == 'Windows' else 'liboqs.so'
-LIBOQS_INSTALL_PATH = 'LIBOQS_INSTALL_PATH'
-
+_LIBOQS_SHARED_OBJ = 'oqs' if platform.system() == 'Windows' else 'liboqs.so'
+_LIBOQS_INSTALL_PATH = 'LIBOQS_INSTALL_PATH'
 
 # expected return value from native OQS functions
-_OQS_SUCCESS = 0
+OQS_SUCCESS = 0
+OQS_ERROR = -1
 
 
 def _load_shared_obj():
@@ -29,11 +28,11 @@
     paths = []
 
     # try custom env var first
-    if LIBOQS_INSTALL_PATH in os.environ:
-        paths.append(os.environ[LIBOQS_INSTALL_PATH])
+    if _LIBOQS_INSTALL_PATH in os.environ:
+        paths.append(os.environ[_LIBOQS_INSTALL_PATH])
 
     # search typical locations too
-    paths += [ctu.find_library('oqs'), os.path.join(os.curdir, LIBOQS_SHARED_OBJ)]
+    paths += [ctu.find_library('oqs'), os.path.join(os.curdir, _LIBOQS_SHARED_OBJ)]
     dll = ct.windll if platform.system() == 'Windows' else ct.cdll
 
     for path in paths:
@@ -59,20 +58,18 @@
 
     def __init__(self, alg_name):
         """
-        :param alg_name: requested algorithm name
+        :param alg_name: requested algorithm name.
         """
         self.alg_name = alg_name
         self.message = alg_name + ' is not supported by OQS'
 
 
 class MechanismNotEnabledError(MechanismNotSupportedError):
-    """
-    Exception raised when an algorithm is not supported but not enabled by OQS.
-    """
+    """Exception raised when an algorithm is not supported but not enabled by OQS."""
 
     def __init__(self, alg_name):
         """
-        :param alg_name: requested algorithm name
+        :param alg_name: requested algorithm name.
         """
         self.alg_name = alg_name
         self.message = alg_name + ' is not supported but not enabled by OQS'
@@ -108,9 +105,11 @@
 
     def __init__(self, alg_name, secret_key=None):
         """
-        Create new KeyEncapsulation with the given algorithm.
-        :param alg_name: KEM mechanism algorithm name
-        :param secret_key: optional if generating by generate_keypair() later
+        Creates new KeyEncapsulation with the given algorithm.
+
+        :param alg_name: KEM mechanism algorithm name. Enabled KEM mechanisms can be obtained with
+        get_enabled_KEM_mechanisms().
+        :param secret_key: optional if generating by generate_keypair() later.
         """
         self.alg_name = alg_name
         if alg_name not in _enabled_KEMs:
@@ -126,7 +125,7 @@
             'name': self._kem.contents.method_name.decode(),
             'version': self._kem.contents.alg_version.decode(),
             'claimed_nist_level': int(self._kem.contents.claimed_nist_level),
-            'is_ind_cca' : bool(self._kem.contents.ind_cca),
+            'is_ind_cca': bool(self._kem.contents.ind_cca),
             'length_public_key': int(self._kem.contents.length_public_key),
             'length_secret_key': int(self._kem.contents.length_secret_key),
             'length_ciphertext': int(self._kem.contents.length_ciphertext),
@@ -150,7 +149,7 @@
         public_key = ct.create_string_buffer(self._kem.contents.length_public_key)
         self.secret_key = ct.create_string_buffer(self._kem.contents.length_secret_key)
         rv = liboqs.OQS_KEM_keypair(self._kem, ct.byref(public_key), ct.byref(self.secret_key))
-        return bytes(public_key) if rv == _OQS_SUCCESS else 0
+        return bytes(public_key) if rv == OQS_SUCCESS else 0
 
     def export_secret_key(self):
         """Exports the secret key."""
@@ -166,7 +165,7 @@
         ciphertext = ct.create_string_buffer(self._kem.contents.length_ciphertext)
         shared_secret = ct.create_string_buffer(self._kem.contents.length_shared_secret)
         rv = liboqs.OQS_KEM_encaps(self._kem, ct.byref(ciphertext), ct.byref(shared_secret), my_public_key)
-        return bytes(ciphertext), bytes(shared_secret) if rv == _OQS_SUCCESS else 0
+        return bytes(ciphertext), bytes(shared_secret) if rv == OQS_SUCCESS else 0
 
     def decap_secret(self, ciphertext):
         """
@@ -177,7 +176,7 @@
         my_ciphertext = ct.create_string_buffer(ciphertext, self._kem.contents.length_ciphertext)
         shared_secret = ct.create_string_buffer(self._kem.contents.length_shared_secret)
         rv = liboqs.OQS_KEM_decaps(self._kem, ct.byref(shared_secret), my_ciphertext, self.secret_key)
-        return bytes(shared_secret) if rv == _OQS_SUCCESS else 0
+        return bytes(shared_secret) if rv == OQS_SUCCESS else 0
 
     def free(self):
         """Releases the native resources."""
@@ -186,7 +185,7 @@
             liboqs.OQS_MEM_cleanse(ct.byref(self.secret_key), self._kem.contents.length_secret_key)
 
     def __repr__(self):
-        return "Key encapsulation mechanism: " + self._kem.contents.method_name.decode()
+        return 'Key encapsulation mechanism: ' + self._kem.contents.method_name.decode()
 
 
 liboqs.OQS_KEM_new.restype = ct.POINTER(KeyEncapsulation)
@@ -194,9 +193,10 @@
 
 
 def is_KEM_enabled(alg_name):
-    """Returns True if the KEM algorithm is enabled.
+    """
+    Returns True if the KEM algorithm is enabled.
 
-    :param alg_name: a KEM mechanism algorithm name
+    :param alg_name: a KEM mechanism algorithm name.
     """
     return liboqs.OQS_KEM_alg_is_enabled(ct.create_string_buffer(alg_name.encode()))
 
@@ -212,7 +212,7 @@
 
 
 def get_supported_KEM_mechanisms():
-    """Returns list of supported KEM mechanisms."""
+    """Returns the list of supported KEM mechanisms."""
     return _supported_KEMs
 
 
@@ -243,12 +243,13 @@
         ("verify_cb", ct.c_void_p)
     ]
 
-    def __init__(self, alg_name, secret_key = None):
+    def __init__(self, alg_name, secret_key=None):
         """
-        Create new Signature with the given algorithm.
-        :param alg_name: a signature mechanism algorithm name. Enabled signature
-        mechanisms can be obtained with get_enabled_KEM_mechanisms().
-        :param secret_key: optional, if generated by generate_keypair()
+        Creates new Signature with the given algorithm.
+
+        :param alg_name: a signature mechanism algorithm name. Enabled signature mechanisms can be obtained with
+        get_enabled_sig_mechanisms().
+        :param secret_key: optional, if generated by generate_keypair().
         """
         if alg_name not in _enabled_sigs:
             # perhaps it's a supported but not enabled alg
@@ -257,7 +258,7 @@
             else:
                 raise MechanismNotSupportedError(alg_name)
 
-        self._sig = liboqs.OQS_SIG_new( ct.create_string_buffer(alg_name.encode()))
+        self._sig = liboqs.OQS_SIG_new(ct.create_string_buffer(alg_name.encode()))
         self.details = {
             'name': self._sig.contents.method_name.decode(),
             'version': self._sig.contents.alg_version.decode(),
@@ -285,7 +286,7 @@
         public_key = ct.create_string_buffer(self._sig.contents.length_public_key)
         self.secret_key = ct.create_string_buffer(self._sig.contents.length_secret_key)
         rv = liboqs.OQS_SIG_keypair(self._sig, ct.byref(public_key), ct.byref(self.secret_key))
-        return bytes(public_key) if rv == _OQS_SUCCESS else 0
+        return bytes(public_key) if rv == OQS_SUCCESS else 0
 
     def export_secret_key(self):
         """Exports the secret key."""
@@ -301,12 +302,12 @@
         my_message = ct.create_string_buffer(message, len(message))
         message_len = ct.c_int(len(my_message))
         signature = ct.create_string_buffer(self._sig.contents.length_signature)
-        sig_len = ct.c_int(self._sig.contents.length_signature) # initialize to maximum signature size
+        sig_len = ct.c_int(self._sig.contents.length_signature)  # initialize to maximum signature size
         rv = liboqs.OQS_SIG_sign(self._sig, ct.byref(signature),
                                  ct.byref(sig_len), my_message,
                                  message_len, self.secret_key)
 
-        return bytes(signature[:sig_len.value]) if rv == _OQS_SUCCESS else 0
+        return bytes(signature[:sig_len.value]) if rv == OQS_SUCCESS else 0
 
     def verify(self, message, signature, public_key):
         """
@@ -326,7 +327,7 @@
         my_public_key = ct.create_string_buffer(public_key, self._sig.contents.length_public_key)
         rv = liboqs.OQS_SIG_verify(self._sig, my_message, message_len,
                                    my_signature, sig_len, my_public_key)
-        return True if rv == _OQS_SUCCESS else False
+        return True if rv == OQS_SUCCESS else False
 
     def free(self):
         """Releases the native resources."""
@@ -335,7 +336,7 @@
             liboqs.OQS_MEM_cleanse(ct.byref(self.secret_key), self._sig.contents.length_secret_key)
 
     def __repr__(self):
-        return "Signature mechanism: " + self._sig.contents.method_name.decode()
+        return 'Signature mechanism: ' + self._sig.contents.method_name.decode()
 
 
 liboqs.OQS_SIG_new.restype = ct.POINTER(Signature)
@@ -343,9 +344,10 @@
 
 
 def is_sig_enabled(alg_name):
-    """Returns True if the signature algorithm is enabled.
+    """
+    Returns True if the signature algorithm is enabled.
 
-    :param alg_name: a signature mechanism algorithm name
+    :param alg_name: a signature mechanism algorithm name.
     """
     return liboqs.OQS_SIG_alg_is_enabled(ct.create_string_buffer(alg_name.encode()))
 
@@ -361,5 +363,5 @@
 
 
 def get_supported_sig_mechanisms():
-    """Returns list of supported signature mechanisms."""
+    """Returns the list of supported signature mechanisms."""
     return _supported_sigs
diff --git a/oqs/rand.py b/oqs/rand.py
new file mode 100644
index 0000000..d6959c4
--- /dev/null
+++ b/oqs/rand.py
@@ -0,0 +1,58 @@
+"""
+Open Quantum Safe (OQS) Python Wrapper for liboqs
+
+The liboqs project provides post-quantum public key cryptography algorithms:
+https://github.com/open-quantum-safe/liboqs
+
+This module provides a Python 3 interface to libOQS <oqs/rand.h> RNGs.
+"""
+
+import oqs
+
+
+def randombytes(bytes_to_read):
+    """
+    Generates random bytes. This implementation uses either the default RNG algorithm ("system"), or whichever
+    algorithm has been selected by random_bytes_switch_algorithm().
+
+    :param bytes_to_read: the number of random bytes to generate.
+    :return: random bytes.
+    """
+    result = oqs.ct.create_string_buffer(bytes_to_read)
+    oqs.liboqs.OQS_randombytes(result, oqs.ct.c_int(bytes_to_read))
+    return bytes(result)
+
+
+def randombytes_switch_algorithm(alg_name):
+    """
+    Switches the core OQS_randombytes to use the specified algorithm. See <oqs/rand.h> liboqs headers for more details.
+
+    :param alg_name: algorithm name, possible values are "system", "NIST-KAT", "OpenSSL".
+    """
+    if oqs.liboqs.OQS_randombytes_switch_algorithm(oqs.ct.create_string_buffer(alg_name.encode())) != oqs.OQS_SUCCESS:
+        raise RuntimeError('Can not switch algorithm')
+
+
+def randombytes_nist_kat_init(entropy_input, personalization_string=None):
+    """
+    Initializes the NIST DRBG with the an entropy seed.
+
+    :param entropy_input: entropy input seed, must be exactly 48 bytes long.
+    :param personalization_string: optional personalization string, which, if present, must be at least 48 bytes long.
+    """
+    if len(entropy_input) != 48:
+        raise ValueError('The entropy source must be exactly 48 bytes long')
+
+    if personalization_string is not None:
+        if len(personalization_string) < 48:
+            raise ValueError('The personalization string must be either empty or at least 48 bytes long')
+        oqs.liboqs.OQS_randombytes_nist_kat_init(oqs.ct.create_string_buffer(entropy_input),
+                                                 oqs.ct.create_string_buffer(personalization_string), 256)
+
+    oqs.liboqs.OQS_randombytes_nist_kat_init(oqs.ct.create_string_buffer(entropy_input), 0, 256)
+
+# def randombytes_in_place(random_array, bytes_to_read):
+#     raise NotImplementedError
+
+# def randombytes_custom_algorithm(fun):
+#     raise NotImplementedError
diff --git a/setup.py b/setup.py
index 67f8b0e..edd43dd 100644
--- a/setup.py
+++ b/setup.py
@@ -4,7 +4,7 @@
 
 setup(
     name='liboqs-python',
-    version='0.2.0',
+    version='0.2.1',
     author='liboqs team',
     author_email='[email protected]',
     packages=find_packages(exclude=('tests', 'docs', 'examples')),
diff --git a/tests/test_kem.py b/tests/test_kem.py
index 4f0d728..c85273a 100644
--- a/tests/test_kem.py
+++ b/tests/test_kem.py
@@ -1,9 +1,11 @@
 import oqs
 import random
 
+
 def test_correctness():
     for alg_name in oqs.get_enabled_KEM_mechanisms():
-        yield (check_correctness, alg_name)
+        yield check_correctness, alg_name
+
 
 def check_correctness(alg_name):
     kem = oqs.KeyEncapsulation(alg_name)
@@ -13,9 +15,11 @@
     assert shared_secret_client == shared_secret_server
     kem.free()
 
+
 def test_wrong_ciphertext():
     for alg_name in oqs.get_enabled_KEM_mechanisms():
-        yield (check_wrong_ciphertext, alg_name)
+        yield check_wrong_ciphertext, alg_name
+
 
 def check_wrong_ciphertext(alg_name):
     kem = oqs.KeyEncapsulation(alg_name)
@@ -26,6 +30,7 @@
     assert shared_secret_client != shared_secret_server
     kem.free()
 
+
 def test_not_supported():
     try:
         kem = oqs.KeyEncapsulation('bogus')
@@ -34,7 +39,7 @@
         pass
     except E:
         raise AssertionError("An unexpected exception was raised. " + E)
-    
+
 
 def test_not_enabled():
     # TODO: test broken as the compiled lib determines which algorithms are
@@ -50,10 +55,13 @@
             except E:
                 raise AssertionError("An unexpected exception was raised. " + E)
 
+
 if __name__ == '__main__':
     try:
         import nose2
+
         nose2.main()
     except ImportError:
         import nose
-        nose.runmodule()
\ No newline at end of file
+
+        nose.runmodule()
diff --git a/tests/test_sig.py b/tests/test_sig.py
index 359b2ad..2cdaf49 100644
--- a/tests/test_sig.py
+++ b/tests/test_sig.py
@@ -1,9 +1,11 @@
 import oqs
 import random
 
+
 def test_correctness():
     for alg_name in oqs.get_enabled_sig_mechanisms():
-        yield (check_correctness, alg_name)
+        yield check_correctness, alg_name
+
 
 def check_correctness(alg_name):
     message = bytes(random.getrandbits(8) for _ in range(100))
@@ -13,9 +15,11 @@
     assert sig.verify(message, signature, public_key)
     sig.free()
 
+
 def test_wrong_message():
     for alg_name in oqs.get_enabled_sig_mechanisms():
-        yield (check_wrong_message, alg_name)
+        yield check_wrong_message, alg_name
+
 
 def check_wrong_message(alg_name):
     message = bytes(random.getrandbits(8) for _ in range(100))
@@ -23,12 +27,14 @@
     public_key = sig.generate_keypair()
     signature = sig.sign(message)
     wrong_message = bytes(random.getrandbits(8) for _ in range(100))
-    assert not(sig.verify(wrong_message, signature, public_key))
+    assert not (sig.verify(wrong_message, signature, public_key))
     sig.free()
 
+
 def test_wrong_signature():
     for alg_name in oqs.get_enabled_sig_mechanisms():
-        yield (check_wrong_signature, alg_name)
+        yield check_wrong_signature, alg_name
+
 
 def check_wrong_signature(alg_name):
     message = bytes(random.getrandbits(8) for _ in range(100))
@@ -36,12 +42,14 @@
     public_key = sig.generate_keypair()
     signature = sig.sign(message)
     wrong_signature = bytes(random.getrandbits(8) for _ in range(sig.details['length_signature']))
-    assert not(sig.verify(message, wrong_signature, public_key))
+    assert not (sig.verify(message, wrong_signature, public_key))
     sig.free()
 
+
 def test_wrong_public_key():
     for alg_name in oqs.get_enabled_sig_mechanisms():
-        yield (check_wrong_public_key, alg_name)
+        yield check_wrong_public_key, alg_name
+
 
 def check_wrong_public_key(alg_name):
     message = bytes(random.getrandbits(8) for _ in range(100))
@@ -49,9 +57,10 @@
     public_key = sig.generate_keypair()
     signature = sig.sign(message)
     wrong_public_key = bytes(random.getrandbits(8) for _ in range(sig.details['length_public_key']))
-    assert not(sig.verify(message, signature, wrong_public_key))
+    assert not (sig.verify(message, signature, wrong_public_key))
     sig.free()
 
+
 def test_not_supported():
     try:
         sig = oqs.Signature('bogus')
@@ -76,10 +85,13 @@
             except E:
                 raise AssertionError("An unexpected exception was raised. " + E)
 
+
 if __name__ == '__main__':
     try:
         import nose2
+
         nose2.main()
     except ImportError:
         import nose
-        nose.runmodule()
\ No newline at end of file
+
+        nose.runmodule()