Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 58 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,63 @@
# liboprf

This library implements the basic OPRF(ristretto255, SHA-512) variant
from the IRTF CFRG Draft: https://github.com/cfrg/draft-irtf-cfrg-voprf/

Additionally it implements a threshold OPRF variant based on
https://eprint.iacr.org/2017/363 by Krawczyk et al. which is
compatible with the CFRG OPRF(ristretto255, SHA-512) variant.

Furthermore it also implements the 3hashTDH from
https://eprint.iacr.org/2024/1455 "Threshold PAKE with Security
against Compromise of all Servers" by Gu, Jarecki, Kedzior, Nazarian,
Xu. This too is compatible with the CFRG OPRF(ristretto255, SHA-512)
variant.

For the threshold OPRF this library also provides distributed
key-generation (DKG) implementation that is based on a trusted
party handling the broadcasts necessary for the DKG, this is
based on the JF-DKG (fig 1.) a variant on Pedersens DKG from
the paper "Secure Distributed Key Generation for Discrete-Log
Based Cryptosystems" by R. Gennaro, S. Jarecki, H. Krawczyk,
and T. Rabin.

The semi-trusted version of the DKG implements FT-Joint-DL-VSS from fig. 7 in
R. Gennaro, M. O. Rabin, and T. Rabin. "Simplified VSS and fact-track
multiparty computations with applications to threshold cryptography" In B. A.
Coan and Y. Afek, editors, 17th ACM PODC, pages 101–111. ACM, June / July 1998


In order to update a threshold OPRF instantiation this library contains the
multi-party multiplication is based on Fig. 2 from R. Gennaro, M. O. Rabin, and
T. Rabin. "Simplified VSS and fact-track multiparty computations with
applications to threshold cryptography" In B. A. Coan and Y. Afek, editors,
17th ACM PODC, pages 101–111. ACM, June / July 1998.

Additionally a python wrapper is provided, which can be installed
using `pip install pyoprf`

This library depends on libsodium.
## Overview

liboprf is a library for Oblivious Pseudorandom Functions (OPRFs), including support for Threshold OPRFs. It is designed to make advanced cryptographic protocols easy to integrate across applications.

## What is an OPRF?

An Oblivious Pseudorandom Function (OPRF) is a two-party cryptographic primitive involving a sender and receiver who jointly compute a function, `F`, in such a way that:
- The sender holds a secret key `k`
- The receiver provides an input `x`
- The receiver learns `F(k, x)` but nothing about `k`
- The sender learns nothing about `x` or `F(k, x)`

OPRFs are the foundation for many privacy-preserving protocols including:
- Password-based authentication without exposing passwords
- Private set intersection, which allows two parties to find the intersection of their private sets without revealing the full sets
- Privacy-preserving information retrieval, allowing users to get specific information from a database without revealing what information is being retrieved

## Features

### Basic OPRF
liboprf implements the basic OPRF(ristretto255, SHA-512) variant from the [IRTF CFRG Draft](https://github.com/cfrg/draft-irtf-cfrg-voprf/), "Oblivious Pseudorandom Functions (OPRFs) using Prime-Order Groups".

### Threshold OPRF
liboprf implements a threshold OPRF variant based on [Krawczyk et al. (2017)](https://eprint.iacr.org/2017/363) which is compatible with the [CFRG OPRF(ristretto255, SHA-512) variant](#basic-oprf). A threshold implementation distributes trust among multiple servers, requiring a minimum number (threshold) to cooperate for operation. It uses Distributed Key Generation (DKG) protocols, as described below, to distribute secret key shares among multiple servers.

### 3hashTDH
This library also implements the 3hashTDH from [Gu, Jarecki, Kedzior, Nazarian, Xu (2024)](https://eprint.iacr.org/2024/1455) "Threshold PAKE with Security against Compromise of all Servers". This implementation is compatible with the aforementioned [IRTF CFRG OPRF(ristretto255, SHA-512)](#basic-oprf) variant.

### Distributed Key Generation (DKG)
For the [threshold OPRF](#threshold-oprf), liboprf provides:

- **Trusted Party DKG**: An implementation based on Joint Feldman DKG (JF-DKG) from the paper "[Secure Distributed Key Generation for Discrete-Log Based Cryptosystems](https://link.springer.com/article/10.1007/s00145-006-0347-3)" by R. Gennaro, S. Jarecki, Hugo Krawczyk & T. Rabin.

- **Semi-trusted DKG**: Implements Fast-Track Joint Verifiable Secret Sharing (FT-Joint-DL-VSS) described in R. Gennaro, M. O. Rabin, and T. Rabin, "[Simplified VSS and fast-track multiparty computations with applications to threshold cryptography](https://dl.acm.org/doi/10.1145/277697.277716)" In B. A. Coan and Y. Afek, editors, 17th ACM PODC, pages 101–111. ACM, June/July 1998.

### Threshold OPRF Updates
To update a threshold OPRF instantiation, liboprf contains multi-party multiplication described in R. Gennaro, M. O. Rabin, and T. Rabin, "[Simplified VSS and fast-track multiparty computations with applications to threshold cryptography](https://dl.acm.org/doi/10.1145/277697.277716)" In B. A. Coan and Y. Afek, editors, 17th ACM PODC, pages 101–111. ACM, June/July 1998.

## Installation

### Dependencies
- **libsodium**: You must install [libsodium](https://github.com/jedisct1/libsodium) first. libsodium is a cryptographic library that provides a range of cryptographic operations including encryption, decryption, digital signatures, and secure password hashing.
- **pkgconf**: Needed for building the library.

### Building from source

```bash
git clone https://github.com/stef/liboprf.git
cd liboprf/src
make
sudo make install
```
Comment thread
enjeck marked this conversation as resolved.

### Python Wrapper
A Python wrapper, `pyoprf`, is provided. Look at [its README](/python/README.md) for installation and usage instructions.


## Funding

This project is funded through [NGI0 Entrust](https://nlnet.nl/entrust), a fund
established by [NLnet](https://nlnet.nl) with financial support from the
Expand Down
153 changes: 146 additions & 7 deletions python/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,155 @@
# pyoprf

This is the python bindings for liboprf.
pyoprf offers Python bindings for the liboprf library, allowing integration of Oblivious Pseudorandom Functions (OPRFs) into Python applications. It provides access to the [features](../README.md#features) of the [liboprf](https://github.com/stef/liboprf) library.

## installation
## Installation

you'll need https://github.com/stef/liboprf/
which depends on libsodium.
a simple `pip install pyoprf` should suffice to install the bindings.
### Prerequisites

## usage
- [liboprf](https://github.com/stef/liboprf): The core library
- [libsodium](https://github.com/jedisct1/libsodium): Required dependency for liboprf
- OpenSSL: For cryptographic functions

see the file `test.py`
### Installing from PyPI

```bash
pip install pyoprf
```

### Installing from source

```bash
git clone https://github.com/stef/liboprf.git
cd liboprf/python
pip install .
```

## Usage

For detailed usage examples, refer to the [`test.py`](./tests/test.py) file and the [`examples`](/examples) folder.

### Basic Example
Imagine a scenario where a client wants to retrieve data from a server using a password, but doesn't want to reveal the actual password to the server:

```python
import pyoprf

# Basic OPRF evaluation process
# Step 1: Client blinds the input value
input_value = b"password123"
blind_factor, blinded_input = pyoprf.blind(input_value)

# Step 2: Server generates a key and evaluates the blinded input
server_key = pyoprf.keygen()
server_evaluation = pyoprf.evaluate(server_key, blinded_input)

# Step 3: Client unblinds the server's response
unblinded_result = pyoprf.unblind(blind_factor, server_evaluation)

# Step 4: Client finalizes the OPRF computation
final_result = pyoprf.finalize(input_value, unblinded_result)

print(f"OPRF result: {final_result.hex()}")

# Verify that repeated evaluations with the same key and input produce the same result
blind_factor2, blinded_input2 = pyoprf.blind(input_value)
server_evaluation2 = pyoprf.evaluate(server_key, blinded_input2)
unblinded_result2 = pyoprf.unblind(blind_factor2, server_evaluation2)
final_result2 = pyoprf.finalize(input_value, unblinded_result2)

print(f"Verification result: {final_result2.hex()}")
assert final_result == final_result2, "OPRF evaluations should be deterministic for the same input and key"

# The `final_result` can be used as a key for encryption, authentication token, and more.
# Both client and server can derive the same value without the server learning the password
```

### Threshold Example
Suppose you want to build a password authentication system that distributes trust across multiple servers, so no single server can learn a user's password. The library also supports threshold OPRFs, where multiple servers hold shares of a key:

```python
import pyoprf

# Setting up a threshold OPRF with 3 servers, threshold of 2
# Server setup, which would happen on each server
n = 3 # Total number of servers
t = 2 # The minimum servers needed, also called the threshold

# Generate a key
key = pyoprf.keygen()

# Create shares of the key for distributed evaluation
shares = pyoprf.create_shares(key, n, t)

# On client
input_value = b"password123"
blind_factor, blinded_input = pyoprf.blind(input_value)

# Each server evaluates the input with its share
evaluations = []
for i in range(n):
# This evaluation happens on server i
server_evaluation = pyoprf.evaluate(shares[i][1:], blinded_input)
evaluations.append(shares[i][:1] + server_evaluation)

# Client combines evaluations (need at least t of them)
collected_evaluations = evaluations[:t] # Just use the first t evaluations
combined = pyoprf.thresholdmult(collected_evaluations)

# Client unblinds the combined result
unblinded = pyoprf.unblind(blind_factor, combined)

# Finalize to get the OPRF output
final_result = pyoprf.finalize(input_value, unblinded)
print(f"Threshold OPRF result: {final_result.hex()}")

# Verify that it matches a direct evaluation with the key
server_evaluation = pyoprf.evaluate(key, blinded_input)
unblinded_direct = pyoprf.unblind(blind_factor, server_evaluation)
direct_result = pyoprf.finalize(input_value, unblinded_direct)
print(f"Direct OPRF result: {direct_result.hex()}")
assert final_result == direct_result, "Threshold evaluation should match direct evaluation"
```

## Troubleshooting

If you encounter issues, first ensure that libsodium, liboprf and OpenSSL are properly installed.

### OpenSSL Header Issues

If after installing OpenSSL, you get the error `'openssl/crypto.h' file not found`, you might need to provide OpenSSL headers to the compiler. For example, if OpenSSL was installed on Mac using Homebrew:
```
export CFLAGS="-I/opt/homebrew/opt/openssl@3/include"
export LDFLAGS="-L/opt/homebrew/opt/openssl@3/lib"
```
Comment thread
enjeck marked this conversation as resolved.

### Library Loading Issues

When running Python code, you might encounter errors like:

```
OSError: liboprf.so.0: cannot open shared object file: No such file or directory
OSError: liboprf-noiseXK.so.0: cannot open shared object file: No such file or directory
```

To fix this, first create symbolic links:

```bash
cd /path/to/liboprf/src
ln -s liboprf.so liboprf.so.0
cd noise_xk
ln -s liboprf-noiseXK.so liboprf-noiseXK.so.0
```

Then when running your Python code, use the LD_LIBRARY_PATH environment variable:

```bash
LD_LIBRARY_PATH=/path/to/liboprf/src:/path/to/liboprf/src/noise_xk python your_script.py
```
Comment on lines +129 to +148
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This happened to me on Ubuntu. Maybe there's an easier fix?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i suppose:

cd /path/to/liboprf/src
sudo PREFIX=/usr make install
ldconfig

or on debian(-derivates) apt install liboprf0t64

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These don't work for me


## Documentation

For more information on the underlying liboprf functionality, visit the [liboprf documentation](../README.md).

## License

Expand Down