npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@privacyresearch/oprf-ts

v0.0.7

Published

EC-OPRF Protocols in low-dependency TypeScript

Downloads

7

Readme

VOPRF - Verifiable Oblivious Pseudorandom Functions

This package implements v07 of the Internet-Draft OPRF protocol. It provides both Base and Verifiable modes of operation.

Implementation Status

This protocol implementation is generic, allowing users to create server and client contexts using their own implementations of ciphersuites. So if a user implements, for example, a Decaf448-SHAKE256 ciphersuite then this library can use it to execute the VOPRF protocol. This provides flexibility to users as well as a degree of future-proofing - as better ciphersuite implementations arise they will be usable (almost) out of the box with this library.

With that said, standard ciphersuite implementations are still needed. The table below shows the current state of support.

| Ciphersuite | Supported | Curve Implementation | Notes | | -------------------------- | ----------- | --------------------------------------------------------------------------------- | -------------------------------------------- | | OPRF(Ristretto255, SHA512) | ✔️ | @privacyresearch/ed25519-ts | Configurable BigInt and Hash implementations | | OPRF(Decaf448, SHAKE-256) | ❌ | | | | OPRF(P-256, SHA-256) | ❌ | | | | OPRF(P-384, SHA-384) | ❌ | | | | OPRF(P-521, SHA-512) | ❌ | | |

Installation

Install with yarn:

yarn add @privacyresearch/oprf-ts

Usage

In the examples below we work with the Ristretto255-SHA512 ciphersuite. This ciphersuite uses the @privacyresearch/ed25519-ts implementation of the Ristretto group, which allows programmers to choose their own implementation of arbitrary precision integers - something that is particularly useful when working on platforms that do not have native bigint support (such as React Native).

To emphasize flexibility, these examples will use the JSBI arbitrary precision arithmetic library.

Creating the ciphersuite

Every program with this library will start by creating a ciphersuite. Here we create a Ristretto255-SHA512 ciphersuite using the JSBI library for arithmetic.

import { makeED } from '@privacyresearch/ed25519-ts'
import JSBI from 'jsbi'
const ed = makeED(JSBI)
const ciphersuite = ristretto255SHA512Ciphersuite<JSBI>(ed, OPRFMode.Base)

Creating or Importing a Keypair

Given seed, an array of random bytes with sufficient entropy, derive a keypair with secret key skS and public key pkS as follows:

// skS is a Scalar, pkS is a group element
const { skS, pkS } = ciphersuite.GG.deriveKeyPair(seed)

With a ciphersuite and keypair in hand, we can begin the protocol.

Base Mode

Client Protocol in Base Mode

In base mode we do not perform verification, so the server public key, pkS, is not needed. Below we see a full client run of the OPRF protocol. It consists of four steps:

  1. Create a ClientContext.
  2. Blind input
  3. Send the blinded element to the server along with public info.
  4. Unblind and finalize the server response.
import { ClientContextImpl } from '@privacyresearch/oprf-ts'
const clientContext = new ClientContextImpl(ciphersuite)

let input: PrivateInput // Uint8Array
let info: PublicInput // Uint8Array

const { blind, blindedElement } = clientContext.blind(input)

// This is pseudocode - you'll know how to call your server!
const evaluatedElement = await callServer(blindedElement, info)

const output = clientContext.finalize(input, blind, evaluatedElement, info)

Server Protocol in Base Mode

The server will need to be initialized with its secret key, skS. Here is how the server will handle the client's call

import { ServerContextImpl } from '@privacyresearch/oprf-ts'

const serverContext = new ServerContextImpl(ciphersuite, skS)

const { evaluatedElement } = serverContext.evaluate(blindedElement, info)

// Now return `evaluatedElement` to the client

Verifiable Mode

Verifiable mode is almost identical to the base mode for the programmer. Since all verification is performed by this library, the only differences will be small differences in function and class names, and the need for the server to return a verification proof with its response.

Client Protocol in Verifiable Mode

In verifiable mode, the client needs to be initialized with the server's public key, pkS, in order to perform verification.

import { VerifiableClientContextImpl } from '@privacyresearch/oprf-ts'
const clientContext = new VerifiableClientContextImpl(ciphersuite, pkS)

let input: PrivateInput // Uint8Array
let info: PublicInput // Uint8Array

const { blind, blindedElement } = clientContext.blind(input)

// This is pseudocode - you'll know how to call your server!
const { evaluatedElement, proof } = await callServer(blindedElement, info)

// This will throw an `Error` if verification fails
const output = clientContext.verifiableFinalize(input, blind, evaluatedElement, info)

Server Protocol in Verifiable Mode

The server will need to be initialized with its secret key, skS. Here is how the server will handle the client's call

import { VerifiableServerContextImpl } from '@privacyresearch/oprf-ts'

const serverContext = new VerifiableServerContextImpl(ciphersuite, skS)

const { evaluatedElement, proof } = serverContext.verifiableEvaluate(blindedElement, info)

// Now return `{evaluatedElement, proof}` to the client

Batch Processing

Multiple inputs that use the same public info can be evaluated in a single batch call that returns a constant-sized proof. To do this, use the methods verifiableEvaluateBatch on the server and verifiableFinalizeBatch on the client:

import { VerifiableClientContextImpl, VerifiableServerContextImpl } from '@privacyresearch/oprf-ts'
const clientContext = new VerifiableClientContextImpl(ciphersuite, pkS)
const serverContext = new VerifiableServerContextImpl(ciphersuite, skS)

let inputs: PrivateInput[] // Uint8Array[]
let info: PublicInput // Uint8Array

const blindResults = inputs.map((input) => clientContext.blind(input))
const blinds = blindResults.map((br) => br.blind)
const blindedElements = blindResults.map((blindedElement) => br.blindedElement)

// Just for domonstration - the server will really be somewhere else
const { evaluatedElements, proof } = serverContext.verifiableEvaluateBatch(blindedElements, info)

// This will throw an `Error` if verification fails
const output = clientContext.verifiableFinalizeBatch(inputs, blinds, evaluatedElements, blindedElements, proof, info)

Implementing New Ciphersuites

A good place to get started when developing a new ciphersuite for use with this library is the Privacy Research ciphersuites repository. There you will find

  • Type definitions for groups, scalars, and ciphersuites

  • Implementations of standard functions such as I2OSP, OS2IP, CT_EQUAL, and expand_message_xmd

  • Ciphersuite implementations, including @privacyresearch/noble-restretto255-sha256, an implementation of the OPRF(Ristretto255, SHA256) ciphersuite based on noble-ed25519. To see this ciphersuite in use, look at this unit test.

    This implementation uses the native bigint and is much faster than the JSBI implementation described above. If bigints are available and acceptable for your application, nobe-ed25519 is preferred.

License

(c) 2021 Privacy Research, LLC (https://privacyresearch.io), see LICENSE file.