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:

Moreover, the following OPRF server APIs are used:

Finally, the following shared APIs and parameters:

Simple Routine using OPRF Protocol

  1. The OPRF protocol begins with the client blinding its input, as described by the Blind function below. Note that this function can fail with an InvalidInputError 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
  1. Clients store blind locally and send blindedElement to the server for evaluation. Upon receipt, servers process blindedElement using the BlindEvaluate function described below.
Input:
  Scalar skS
  Element blindedElement

Output:
  Element evaluatedElement

def BlindEvaluate(skS, blindedElement):
  evaluatedElement = skS * blindedElement
  return evaluatedElement
  1. Servers send the output evaluatedElement to clients for processing. Recall that servers may process multiple client inputs by applying the BlindEvaluate function to each blindedElement received and returning an array with the corresponding evaluatedElement values. Upon receipt of evaluatedElement, clients process it to complete the OPRF evaluation with the Finalize 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)
  1. 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)

DH-OPRF

Oblivious Pseudorandom Function (OPRF)_DH_OPRF.png

Reference