Skip to content

Commit

Permalink
cleanup and message passing example.
Browse files Browse the repository at this point in the history
  • Loading branch information
ladnir committed Dec 6, 2022
1 parent 86dcb8b commit 4852cae
Show file tree
Hide file tree
Showing 6 changed files with 318 additions and 125 deletions.
75 changes: 61 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ This library currently implements:
* The malicious secure 1-out-of-2 Delta-OT [[KOS15]](https://eprint.iacr.org/2015/546),[[BLNNOOSS15]](https://eprint.iacr.org/2015/472.pdf).
* The malicious 1-out-of-2 OT [[Roy22]](https://eprint.iacr.org/2022/192).
* The malicious secure 1-out-of-N OT [[OOS16]](http://eprint.iacr.org/2016/933).
* The malicious secure approximate K-out-of-N OT [[RR16]](https://eprint.iacr.org/2016/746).
* The malicious secure 1-out-of-2 base OT [NP01].
* The malicious secure 1-out-of-2 base OT [[CO15]](https://eprint.iacr.org/2015/267.pdf) (Faster Linux ASM version disabled by default).
* The malicious secure 1-out-of-2 base OT [[MR19]](https://eprint.iacr.org/2019/706.pdf)
Expand All @@ -30,14 +29,13 @@ This library currently implements:
This library provides several different classes of OT protocols. First is the
base OT protocol of [CO15, MR19, MRR21]. These protocol bootstraps all the other
OT extension protocols. Within the OT extension protocols, we have 1-out-of-2,
1-out-of-N and K-out-of-N, both in the semi-honest and malicious settings. See The `frontend` or `libOTe_Tests` folder for examples.
1-out-of-N, and VOLE both in the semi-honest and malicious settings. See The `frontend` or `libOTe_Tests` folder for examples.

All implementations are highly optimized using fast SSE instructions and vectorization
to obtain optimal performance both in the single and multi-threaded setting. See
the **Performance** section for a comparison between protocols and to other libraries.
to obtain optimal performance both in the single and multi-threaded setting.

Networking can be performed using both the sockets provided by the library and
external socket classes. See the coproto tutorial for an example.
external socket classes. The simplest integration can be achieved via the [message passing interface](https://github.com/osu-crypto/libOTe/blob/master/frontend/ExampleMessagePassing.h) where the user is given the protocol messages that need to be sent/received. Users can also integrate their own socket type for maximum performance. See the [coproto](https://github.com/Visa-Research/coproto/blob/main/frontend/SocketTutorial.cpp) tutorial for examples.


## Build
Expand All @@ -47,14 +45,14 @@ There is one mandatory dependency on [coproto](https://github.com/Visa-Research/
and three **optional dependencies** on [libsodium](https://doc.libsodium.org/),
[Relic](https://github.com/relic-toolkit/relic), or
[SimplestOT](https://github.com/osu-crypto/libOTe/tree/master/SimplestOT) (Unix only)
for Base OTs.
for Base OTs. [Boost Asio](https://www.boost.org/doc/libs/1_77_0/doc/html/boost_asio.html) tcp networking and [OpenSSL](https://www.openssl.org/) support can optionally be enabled.
CMake 3.15+ is required and the build script assumes python 3.

The library can be built as
The library can be built with libsodium, all OT protocols enabled and boost asio TCP networking as
```
git clone https://github.com/osu-crypto/libOTe.git
cd libOTe
python build.py --sodium --boost
python build.py --all --boost --sodium
```
The main executable with examples is `frontend` and is located in the build directory, eg `out/build/linux/frontend/frontend.exe, out/build/x64-Release/frontend/Release/frontend.exe` depending on the OS.

Expand Down Expand Up @@ -96,16 +94,33 @@ Dependencies can be managed by cmake/build.py or installed via an external tool.
```
python build.py --relic
```
Relic can be disabled by removing `--relic` from the setup and setting `-D ENABLE_RELIC=OFF`. Relic can always be fetched and locally built using `-D FETCH_RELIC=true`.
Relic can be disabled by removing `--relic` from the setup and setting `-D ENABLE_RELIC=false`. This will always download and build relic. To only enable but not download relic, use `python build.py -D ENABLE_RELIC=true`.

**Enabling/Disabling [libsodium](https://github.com/osu-crypto/libsodium) (for base OTs):**
The library can be built with libsodium as
```
python build.py --sodium
```
libsodium can be disabled by removing `--sodium` from the setup and setting `-D ENABLE_SODIUM=OFF`. Sodium can always be fetched and locally built using `-D FETCH_SODIUM=true`.
libsodium can be disabled by removing `--sodium` from the setup and setting `-D ENABLE_SODIUM=false`. This will always download and build sodium. To only enable but not download relic, use `python build.py -D ENABLE_SODIUM=true`.

The McQuoid Rosulek Roy 2021 Base OTs uses a twisted curve which additionally require the `noclamp` option for Montgomery curves and is currently only in a [fork](https://github.com/osu-crypto/libsodium) of libsodium. If you prefer the stable libsodium, then install it and add `-D SODIUM_MONTGOMERY=OFF` as a cmake argument to libOTe.
The McQuoid Rosulek Roy 2021 Base OTs uses a twisted curve which additionally require the `noclamp` option for Montgomery curves and is currently only in a [fork](https://github.com/osu-crypto/libsodium) of libsodium. If you prefer the stable libsodium, then install it and add `-D SODIUM_MONTGOMERY=false` as a cmake argument to libOTe.


**Enabling/Disabling [boost asio](https://www.boost.org/doc/libs/1_77_0/doc/html/boost_asio.html) (for TCP networking):**
The library can be built with boost as
```
python build.py --boost
```
boost can be disabled by removing `--boost` from the setup and setting `-D ENABLE_BOOST=false`. This will always download and build boost. To only enable but not download relic, use `python build.py -D ENABLE_BOOST=true`.



**Enabling/Disabling [OpenSSL](https://www.boost.org/doc/libs/1_77_0/doc/html/boost_asio.html) (for TLS networking):**
The library can be built with boost as
```
python build.py --openssl
```
OpenSSL can be disabled by removing `--openssl` from the setup and setting `-D ENABLE_OPENSSL=false`. OpenSSL is never downloaded for you and is always found using your system installs.

## Install

Expand All @@ -114,8 +129,7 @@ libOTe can be installed and linked the same way as other cmake projects. To inst
python build.py --install
```


By default, sudo is not used. If installation requires sudo access, then add `--sudo` to the `build.py` script arguments. See `python build.py --help` for full details.
Sudo is not used. If installation requires sudo access, then install as root. See `python build.py --help` for full details.


## Linking
Expand All @@ -128,7 +142,40 @@ Other exposed targets are `oc::cryptoTools, oc::tests_cryptoTools, oc::libOTe_Te

To ensure that cmake can find libOTe, you can either install libOTe or build it locally and set `-D CMAKE_PREFIX_PATH=path/to/libOTe` or provide its location as a cmake `HINTS`, i.e. `find_package(libOTe HINTS path/to/libOTe)`.


libOTe can be found with the following components:
```
find_package(libOTe REQUIRED
COMPONENTS
boost
relic
sodium
bitpolymul
openssl
circuits
sse
avx
asan
pic
no_sse
no_avx
no_asan
no_pic
simplestot
simplestot_asm
mrr
mrr_twist
mr
mr_kyber
kos
iknp
silentot
softspoken_ot
delta_kos
silent_vole
oos
kkrt
)
```

## Help

Expand Down
4 changes: 1 addition & 3 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,5 @@ def replace(argv, find, rep):

argv = sys.argv
replace(argv, "--bitpolymul", "-DENABLE_SILENTOT=ON -DENABLE_BITPOLYMUL=ON")
replace(argv, "--all", "-DENABLE_BITPOLYMUL=ON -DENABLE_SODIUM=ON -DENABLE_ALL_OT=ON")
replace(argv, "--boost", "-DCOPROTO_ENABLE_BOOST=ON")
replace(argv, "--openssl", "-DCOPROTO_ENABLE_OPENSSL=ON")
replace(argv, "--all", "-DENABLE_ALL_OT=ON")
cryptoTools.build.main("libOTe", argv[1:])
2 changes: 1 addition & 1 deletion cryptoTools
208 changes: 208 additions & 0 deletions frontend/ExampleMessagePassing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#include "cryptoTools/Common/CLP.h"
#include "coproto/Socket/BufferingSocket.h"
#include <fstream>
#include "libOTe/TwoChooseOne/Silent/SilentOtExtReceiver.h"
#include "libOTe/TwoChooseOne/Silent/SilentOtExtSender.h"

// This example demonstates how one can get and manually send the protocol messages
// that are generated. This communicate method is one possible way of doing this.
// It takes a protocol that has been started and coproto buffering socket as input.
// It alternates between "sending" and "receiving" protocol messages. Instead of
// sending the messages on a socket, this program writes them to a file and the other
// party reads that file to get the message. In a real program the communication could
// handled in any way the user decides.
auto communicate(
macoro::eager_task<>& protocol,
bool sender,
coproto::BufferingSocket& sock,
bool verbose)
{

int s = 0, r = 0;
std::string me = sender ? "sender" : "recver";
std::string them = !sender ? "sender" : "recver";

// write any outgoing data to a file me_i.bin where i in the message index.
auto write = [&]()
{
// the the outbound messages that the protocol has generated.
// This will consist of all the outbound messages that can be
// generated without receiving the next inbound message.
auto b = sock.getOutbound();

// If we do have outbound messages, then lets write them to a file.
if (b && b->size())
{
std::ofstream message;
auto temp = me + ".tmp";
auto file = me + "_" + std::to_string(s) + ".bin";
message.open(temp, std::ios::binary | std::ios::trunc);
message.write((char*)b->data(), b->size());
message.close();

if (verbose)
{
// optional for debug purposes.
oc::RandomOracle hash(16);
hash.Update(b->data(), b->size());
oc::block h; hash.Final(h);

std::cout << me << " write " << std::to_string(s) << " " << h << "\n";
}

if (rename(temp.c_str(), file.c_str()) != 0)
std::cout << me << " file renamed failed\n";
else if (verbose)
std::cout << me << " file renamed successfully\n";

++s;
}

};

// write incoming data from a file them_i.bin where i in the message index.
auto read = [&]() {

std::ifstream message;
auto file = them + "_" + std::to_string(r) + ".bin";
while (message.is_open() == false)
{
message.open(file, std::ios::binary);
if ((message.is_open() == false))
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

auto fsize = message.tellg();
message.seekg(0, std::ios::end);
fsize = message.tellg() - fsize;
message.seekg(0, std::ios::beg);
std::vector<oc::u8> buff(fsize);
message.read((char*)buff.data(), fsize);
message.close();
std::remove(file.c_str());

if (verbose)
{
oc::RandomOracle hash(16);
hash.Update(buff.data(), buff.size());
oc::block h; hash.Final(h);

std::cout << me << " read " << std::to_string(r) << " " << h << "\n";
}
++r;

// This gives this socket the message which forwards it to the protocol and
// run the protocol forward, possibly generating more outbound protocol
// messages.
sock.processInbound(buff);
};

// The sender we generate the first message.
if (!sender)
write();

// While the protocol is not done we alternate between reading and writing messages.
while (protocol.is_ready() == false)
{
read();
write();
}
}

void messagePassingExampleRun(oc::CLP& cmd)
{
#ifdef ENABLE_SILENTOT
auto isReceiver = cmd.get<int>("r");

// The number of OTs.
auto n = cmd.getOr("n", 100);

auto verbose = cmd.isSet("v");

// A buffering socket. This socket type internally buffers the
// protocol messages. It is then up to the user to manually send
// and receive messages via the getOutbond(...) and processInbount(...)
// methods.
coproto::BufferingSocket sock;

// randomness source
PRNG prng(oc::sysRandomSeed());

// Sets are always represented as 16 byte values. To support longer elements one can hash them.
if (!isReceiver)
{
oc::SilentOtExtSender sender;

std::vector<std::array<block, 2>> senderOutput(n);


if (verbose)
std::cout << "sender start\n";

// Eagerly start the protocol. This will run the protocol up to the point
// that it need to receive a message from the other party.
auto protocol =
sender.silentSend(senderOutput, prng, sock)
| macoro::make_eager();

// Perform the communication and complete the protocol.
communicate(protocol, true, sock, verbose);

std::cout << "sender done\n";

for (u64 i = 0; i < std::min<u64>(10, n); ++i)
std::cout << "sender.msg[" << i << "] = { " << senderOutput[i][0] << ", " << senderOutput[i][1] << "}" << std::endl;
if (n > 10)
std::cout << "..." << std::endl;
}
else
{
std::vector<block> receiverOutputMsg(n);
oc::BitVector receiverOutputBits(n);

oc::SilentOtExtReceiver receiver;

if (verbose)
std::cout << "recver start\n";

// Eagerly start the protocol. This will run the protocol up to the point
// that it need to receive a message from the other party.
auto protocol =
receiver.silentReceive(receiverOutputBits, receiverOutputMsg, prng, sock)
| macoro::make_eager();

// Perform the communication and complete the protocol.
communicate(protocol, false, sock, verbose);

std::cout << "recver done\n";

for (u64 i = 0; i < std::min<u64>(10, n); ++i)
std::cout << "receiver.msg[" << i << "] = " << receiverOutputMsg[i] << " = sender.msg["<<i <<"][" << receiverOutputBits[i] << "]" << std::endl;
if (n > 10)
std::cout << "..." << std::endl;
}
#else
std::cout << "ENABLE_SILENTOT is not defined. Rebuilt with -DENABLE_SILENTOT=true" << std::endl;
#endif
}


void messagePassingExample(oc::CLP& cmd)
{
// If the user specified -r, then run that party.
// Otherwise run both parties.
if (cmd.hasValue("r"))
{
messagePassingExampleRun(cmd);
}
else
{
auto s = cmd;
s.setDefault("r", 0);
cmd.setDefault("r", 1);
auto a = std::async([&]() {messagePassingExampleRun(s); });
messagePassingExampleRun(cmd);
a.get();
}
}

Loading

0 comments on commit 4852cae

Please sign in to comment.