Oblivious Pseudorandom Function (OPRF)
#Cryptography #OPRF #PRF
An Oblivious Pseudorandom Function (OPRF) is a two-party protocol between client and server for computing a PRF, where the PRF key is held by the server and the input to the function is provided by the client. The client does not learn anything about the PRF other than the obtained output and the server learns nothing about the client's input or the function output.
The following OPRF client APIs are used:
Blind(element)
: Create and output (blind
,blinded_element
), consisting of a blinded representation of inputelement
, denotedblinded_element
, along with a value to revert the blinding process, denotedblind
.Finalize(element, blind, evaluated_element)
: Finalize the OPRF evaluation using inputelement
, random inverterblind
, and evaluation outputevaluated_element
, yielding outputoprf_output
.
Moreover, the following OPRF server APIs are used:
BlindEvaluate(k, blinded_element)
: Evaluate blinded input elementblinded_element
using input keyk
, yielding output elementevaluated_element
.DeriveKeyPair(seed, info)
: Create and output (sk
,pk
), consisting of a private and public key derived deterministically from aseed
andinfo
parameter.
Finally, the following shared APIs and parameters:
SerializeElement(element)
: Map inputelement
to a fixed-length byte array.DeserializeElement(buf)
: Attempt to map input byte arraybuf
to an OPRF group element. This function can raise a DeserializeError upon failure.- Noe: The size of a serialized OPRF group element output from SerializeElement.
- Nok: The size of an OPRF private key as output from DeriveKeyPair.
Simple Routine using OPRF Protocol
- G: a prime-order group implementing the API described Section 2.1
- contextString: a
PublicInput
domain separation tag constructed during context setup - skS and pkS: a Scalar and Element representing the private and public keys configured for the client and server
- The OPRF protocol begins with the client blinding its input, as described by the
Blind
function below. Note that this function can fail with anInvalidInputError
error for certain inputs that map to the group identity element. Dealing with this failure is an application-specific decision.
Input:
PrivateInput input
Output:
Scalar blind
Element blindedElement
Parameters:
Group G
Errors: InvalidInputError
def Blind(input):
blind = G.RandomScalar()
inputElement = G.HashToGroup(input)
if inputElement == G.Identity():
raise InvalidInputError
blindedElement = blind * inputElement
return blind, blindedElement
- Clients store
blind
locally and sendblindedElement
to the server for evaluation. Upon receipt, servers processblindedElement
using theBlindEvaluate
function described below.
Input:
Scalar skS
Element blindedElement
Output:
Element evaluatedElement
def BlindEvaluate(skS, blindedElement):
evaluatedElement = skS * blindedElement
return evaluatedElement
- Servers send the output
evaluatedElement
to clients for processing. Recall that servers may process multiple client inputs by applying theBlindEvaluate
function to eachblindedElement
received and returning an array with the correspondingevaluatedElement
values. Upon receipt ofevaluatedElement
, clients process it to complete the OPRF evaluation with theFinalize
function described below.
Input:
PrivateInput input
Scalar blind
Element evaluatedElement
Output:
opaque output[Nh]
Parameters:
Group G
def Finalize(input, blind, evaluatedElement):
N = G.ScalarInverse(blind) * evaluatedElement
unblindedElement = G.SerializeElement(N)
hashInput = I2OSP(len(input), 2) || input ||
I2OSP(len(unblindedElement), 2) || unblindedElement ||
"Finalize"
return Hash(hashInput)
- An entity that knows both the private key and the input can compute the PRF result using the following
Evaluate
function.
Input:
Scalar skS
PrivateInput input
Output:
opaque output[Nh]
Parameters:
Group G
Errors: InvalidInputError
def Evaluate(skS, input):
inputElement = G.HashToGroup(input)
if inputElement == G.Identity():
raise InvalidInputError
evaluatedElement = skS * inputElement
issuedElement = G.SerializeElement(evaluatedElement)
hashInput = I2OSP(len(input), 2) || input ||
I2OSP(len(issuedElement), 2) || issuedElement ||
"Finalize"
return Hash(hashInput)