Skip to content

Commit

Permalink
882 add documentation for external PRNG (#889)
Browse files Browse the repository at this point in the history
* Added documentation for external PRNGs, simplified a Blake2Engine constructor

* Altered the documentation

* Documentation changes

* Documentation changes

* Documentation formatting

* Update prng.rst

* Addressed review comments and added a condition for '#include <dlfcn.h>'

---------

Co-authored-by: Dmitriy Suponitskiy <dsuponitskiy@dualitytech.com>
Co-authored-by: pascoec <123595534+pascoec@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 25, 2024
1 parent 8f72e90 commit f2012fe
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 9 deletions.
90 changes: 84 additions & 6 deletions docs/sphinx_rsts/modules/core/utils/prng.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
Pseudorandom Number Generator (PRNG)
=====================================

Documentation for `core/include/utils/prng <https://github.com/openfheorg/openfhe-development/tree/main/src/core/include/utils/prng>`_. Additionally, we refer users to :ref:`our sampling documentation<sampling>`
.. note:: By default, OpenFHE uses a `built-in blake2-based PRNG <https://github.com/openfheorg/openfhe-development/tree/main/src/core/include/utils/prng>`_, but provides the ability to integrate a cutom PRNG engine as a shared library. See below for instructions on how to implement and use a custom PRNG shared library.

.. contents:: Page Contents
:local:
Expand All @@ -10,9 +9,88 @@ Documentation for `core/include/utils/prng <https://github.com/openfheorg/openfh
Implemented PRNG hash function
-------------------------------

- Our cryptographic hash function is based off of `Blake2b <https://blake2.net>`_, which allows fast hashing.
- The default cryptographic hash function in OpenFHE is based off of `Blake2b <https://blake2.net>`_, which allows fast hashing.

.. _for_existing_example:

Building and testing an external PRNG engine (existing example)
-------------------------------------------------------------

.. note:: Integration of an external PRNG engine is an experimental feature currently available only on Linux using the g++ compiler. We provide `an external blake2 PRNG example <https://github.com/openfheorg/openfhe-prng-blake2>`_ as a refernece. See below for instructions on how to build your own custom PRNG engine.

1. Build **OpenFHE 1.2.2+** by following `these instructions <https://openfhe-development.readthedocs.io/en/latest/sphinx_rsts/intro/installation/linux.html>`_ and set **g++** as the default compiler.

2. Clone `the external PRNG repo <https://github.com/openfheorg/openfhe-prng-blake2>`_.

3. Create a directory where the binaries will be built. The typical choice is a subfolder "build". In this case, the commands are:
::
mkdir build
cd build
cmake ..
make

4. Optionally install the shared object **libPRNGengine.so** you have just built.

* for the default install location, run:
::
sudo make install

* for a custom install location you should run a different ``cmake`` command:
::
cmake .. -DCMAKE_INSTALL_PREFIX=/custom/install/location

and after that you run the remaining commands:
::
make
make install
5. Run `the example <https://github.com/openfheorg/openfhe-development/tree/main/src/core/examples/external-prng.cpp>`_ to test the engine. It calls PseudoRandomNumberGenerator::InitPRNGEngine() which initializes PRNG either with the built-in engine or a custom one.

* If executed without arguments, the example calls InitPRNGEngine() which initializes PRNG with the built-in engine:
::
./build/bin/examples/core/external-prng
and the output should be:
::
==== Using internal PRNG

* If your provide the absolute path to the external PRNG as an argument to the example, then InitPRNGEngine() will use that path to initialize PRNG with the custom engine.

For example: if you install **libPRNGengine.so** to the default location (/usr/local), then you will run:
::
./build/bin/examples/core/external-prng /usr/local/lib/libPRNGengine.so

which should produce:
::
==== Using external PRNG
InitPRNGEngine: using external PRNG

.. note:: If PseudoRandomNumberGenerator::InitPRNGEngine() initializes PRNG with a custom engine, it always notifies the user by producing a trace **"InitPRNGEngine: using external PRNG"**. There is no trace for the built-in PRNG engine. InitPRNGEngine() always throws an exception if it fails.


Creating custom external PRNG engine using the existing example
----------------------------------------------------------------

You can create your own PRNG engine and use it with OpenFHE by following the steps below:

1. Create a separate repo for your own engine and copy everything from `the example of external PRNG <https://github.com/openfheorg/openfhe-prng-blake2>`_ to the new repo.

2. Change CMakeLists.txt: replace **"PRNGengine"** (LIBRARY_NAME) with the name of your choice.

3. Delete all source files from src/include and src/lib except:
::
src/prng.h
src/include/blake2engine.h
src/lib/blake2engine.cpp

4. Create a new class similar to Blake2Engine (use the code in blake2engine.h/blake2engine.cpp as an example), following the requirements below:

* the class PRNG defined in prng.h must be used as the base class for the new class. The file prng.h is not allowed to be changed.

* rename blake2engine.h and blake2engine.cpp with the name of your engine.

Using your own PRNG engine
-----------------------------------
* **only two public member functions** should be in the new class: a trivial **constructor with 2 input parameters** (seed array and counter) and **operator()** providing similar functionality as Blake2Engine does, which is generating numbers.

* create extern "C" function **createEngineInstance()** returning a dynamically allocated object of the new class. OpenFHE finds this function by name using dlsym(), so you may not change the name.

To define new ``PRNG`` engines, refer to `blake2engine.h <https://github.com/openfheorg/openfhe-development/blob/main/src/core/include/utils/prng/blake2.h>`_.
5. Follow `the instructions above <#for_existing_example>`_ to build and test your new PRNG.
3 changes: 1 addition & 2 deletions src/core/include/utils/prng/blake2engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ class Blake2Engine : public PRNG {
* @brief Main constructor taking a vector of MAX_SEED_GENS integers as a seed and a counter.
* If there is no value for the counter, then pass zero as the counter value
*/
explicit Blake2Engine(const PRNG::seed_array_t& seed, uint64_t counter)
: PRNG(seed, counter), m_buffer({}), m_bufferIndex(0) {}
explicit Blake2Engine(const PRNG::seed_array_t& seed, uint64_t counter) : PRNG(seed, counter) {}

/**
* @brief main call to the PRNG
Expand Down
4 changes: 3 additions & 1 deletion src/core/lib/math/distributiongenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@

#include <chrono>
#include <cstdint>
#include <dlfcn.h>
#include <random>
#include <thread>
#include <iostream>
#if (defined(__linux__) || defined(__unix__)) && !defined(__APPLE__) && defined(__GNUC__) && !defined(__clang__)
#include <dlfcn.h>
#endif

namespace lbcrypto {

Expand Down

0 comments on commit f2012fe

Please sign in to comment.