| rfc9497v1.txt | rfc9497.txt | |||
|---|---|---|---|---|
| Internet Research Task Force (IRTF) A. Davidson | Internet Research Task Force (IRTF) A. Davidson | |||
| Request for Comments: 9497 Brave Software | Request for Comments: 9497 Brave Software | |||
| Category: Informational A. Faz-Hernandez | Category: Informational A. Faz-Hernandez | |||
| ISSN: 2070-1721 N. Sullivan | ISSN: 2070-1721 N. Sullivan | |||
| C. A. Wood | C. A. Wood | |||
| Cloudflare, Inc. | Cloudflare, Inc. | |||
| October 2023 | November 2023 | |||
| Oblivious Pseudorandom Functions (OPRFs) Using Prime-Order Groups | Oblivious Pseudorandom Functions (OPRFs) Using Prime-Order Groups | |||
| Abstract | Abstract | |||
| An Oblivious Pseudorandom Function (OPRF) is a two-party protocol | An Oblivious Pseudorandom Function (OPRF) is a two-party protocol | |||
| between a client and a server for computing the output of a | between a client and a server for computing the output of a | |||
| Pseudorandom Function (PRF). The server provides the PRF private | Pseudorandom Function (PRF). The server provides the PRF private | |||
| key, and the client provides the PRF input. At the end of the | key, and the client provides the PRF input. At the end of the | |||
| protocol, the client learns the PRF output without learning anything | protocol, the client learns the PRF output without learning anything | |||
| skipping to change at line 218 ¶ | skipping to change at line 218 ¶ | |||
| The following terms are used throughout this document. | The following terms are used throughout this document. | |||
| PRF: Pseudorandom Function | PRF: Pseudorandom Function | |||
| OPRF: Oblivious Pseudorandom Function | OPRF: Oblivious Pseudorandom Function | |||
| VOPRF: Verifiable Oblivious Pseudorandom Function | VOPRF: Verifiable Oblivious Pseudorandom Function | |||
| POPRF: Partially Oblivious Pseudorandom Function | POPRF: Partially Oblivious Pseudorandom Function | |||
| Client: | Client: Protocol initiator. Learns PRF evaluation as the output of | |||
| Protocol initiator. Learns PRF evaluation as the output of the | the protocol. | |||
| protocol. | ||||
| Server: | Server: Computes the PRF using a private key. Learns nothing about | |||
| Computes the PRF using a private key. Learns nothing about the | the client's input or output. | |||
| client's input or output. | ||||
| 2. Preliminaries | 2. Preliminaries | |||
| The protocols in this document have two primary dependencies: | The protocols in this document have two primary dependencies: | |||
| Group: A prime-order group implementing the API described below in | Group: A prime-order group implementing the API described below in | |||
| Section 2.1. See Section 4 for specific instances of groups. | Section 2.1. See Section 4 for specific instances of groups. | |||
| Hash: A cryptographic hash function whose output length is Nh bytes. | Hash: A cryptographic hash function whose output length is Nh bytes. | |||
| Section 4 specifies ciphersuites as combinations of Group and Hash. | Section 4 specifies ciphersuites as combinations of Group and Hash. | |||
| 2.1. Prime-Order Group | 2.1. Prime-Order Group | |||
| In this document, we assume the construction of an additive, prime- | In this document, we assume the construction of an additive, prime- | |||
| order group Group for performing all mathematical operations. In | order group, denoted Group, for performing all mathematical | |||
| prime-order groups, any element (other than the identity) can | operations. In prime-order groups, any element (other than the | |||
| generate the other elements of the group. Usually, one element is | identity) can generate the other elements of the group. Usually, one | |||
| fixed and defined as the group generator. Such groups are uniquely | element is fixed and defined as the group generator. Such groups are | |||
| determined by the choice of the prime p that defines the order of the | uniquely determined by the choice of the prime p that defines the | |||
| group. (However, different representations of the group for a single | order of the group. (However, different representations of the group | |||
| p may exist. Section 4 lists specific groups that indicate both the | for a single p may exist. Section 4 lists specific groups that | |||
| order and representation.) | indicate both the order and representation.) | |||
| The fundamental group operation is addition + with identity element | The fundamental group operation is addition + with identity element | |||
| I. For any elements A and B of the group, A + B = B + A is also a | I. For any elements A and B of the group, A + B = B + A is also a | |||
| member of the group. Also, for any A in the group, there exists an | member of the group. Also, for any A in the group, there exists an | |||
| element -A, such that A + (-A) = (-A) + A = I. Scalar multiplication | element -A, such that A + (-A) = (-A) + A = I. Scalar multiplication | |||
| by r is equivalent to the repeated application of the group operation | by r is equivalent to the repeated application of the group operation | |||
| on an element A with itself r - 1 times; this is denoted as r * A = A | on an element A with itself r - 1 times; this is denoted as r * A = A | |||
| + ... + A. For any element A, p * A = I. The case when the scalar | + ... + A. For any element A, p * A = I. The case when the scalar | |||
| multiplication is performed on the group generator is denoted as | multiplication is performed on the group generator is denoted as | |||
| ScalarMultGen(r). Given two elements A and B, the discrete logarithm | ScalarMultGen(r). Given two elements A and B, the discrete logarithm | |||
| problem is to find an integer k, such that B = k * A. Thus, k is the | problem is to find an integer k, such that B = k * A. Thus, k is the | |||
| discrete logarithm of B with respect to the base A. The set of | discrete logarithm of B with respect to the base A. The set of | |||
| scalars corresponds to GF(p), a prime field of order p, and is | scalars corresponds to GF(p), a prime field of order p, and is | |||
| represented as the set of integers defined by {0, 1, ..., p - 1}. | represented as the set of integers defined by {0, 1, ..., p - 1}. | |||
| This document uses types element and scalar to denote elements of the | This document uses types Element and Scalar to denote elements of the | |||
| group and its set of scalars, respectively. | group and its set of scalars, respectively. | |||
| We now detail a number of member functions that can be invoked on a | We now detail a number of member functions that can be invoked on a | |||
| prime-order group. | prime-order group. | |||
| Order(): Outputs the order of the group (i.e., p). | Order(): Outputs the order of the group (i.e., p). | |||
| Identity(): Outputs the identity element of the group (i.e., I). | Identity(): Outputs the identity element of the group (i.e., I). | |||
| Generator(): Outputs the generator element of the group. | Generator(): Outputs the generator element of the group. | |||
| skipping to change at line 288 ¶ | skipping to change at line 286 ¶ | |||
| a domain separation tag (DST); see Section 4. Security properties | a domain separation tag (DST); see Section 4. Security properties | |||
| of this function are described in [RFC9380]. | of this function are described in [RFC9380]. | |||
| HashToScalar(x): Deterministically maps an array of bytes x to an | HashToScalar(x): Deterministically maps an array of bytes x to an | |||
| element in GF(p). This function is optionally parameterized by a | element in GF(p). This function is optionally parameterized by a | |||
| DST; see Section 4. Security properties of this function are | DST; see Section 4. Security properties of this function are | |||
| described in [RFC9380], Section 10.5. | described in [RFC9380], Section 10.5. | |||
| RandomScalar(): Chooses at random a nonzero element in GF(p). | RandomScalar(): Chooses at random a nonzero element in GF(p). | |||
| ScalarInverse(s): Returns the inverse of input scalar s on GF(p). | ScalarInverse(s): Returns the inverse of input Scalar s on GF(p). | |||
| SerializeElement(A): Maps an element A to a canonical byte array buf | SerializeElement(A): Maps an Element A to a canonical byte array buf | |||
| of fixed-length Ne. | of fixed-length Ne. | |||
| DeserializeElement(buf): Attempts to map a byte array buf to an | DeserializeElement(buf): Attempts to map a byte array buf to an | |||
| element A and fails if the input is not the valid canonical byte | Element A and fails if the input is not the valid canonical byte | |||
| representation of an element of the group. This function can | representation of an element of the group. This function can | |||
| raise a DeserializeError if deserialization fails or A is the | raise a DeserializeError if deserialization fails or A is the | |||
| identity element of the group; see Section 4 for group-specific | identity element of the group; see Section 4 for group-specific | |||
| input validation steps. | input validation steps. | |||
| SerializeScalar(s): Maps scalar s to a canonical byte array buf of | SerializeScalar(s): Maps Scalar s to a canonical byte array buf of | |||
| fixed-length Ns. | fixed-length Ns. | |||
| DeserializeScalar(buf): Attempts to map a byte array buf to scalar | DeserializeScalar(buf): Attempts to map a byte array buf to Scalar | |||
| s. This function can raise a DeserializeError if deserialization | s. This function can raise a DeserializeError if deserialization | |||
| fails; see Section 4 for group-specific input validation steps. | fails; see Section 4 for group-specific input validation steps. | |||
| Section 4 contains details for the implementation of this interface | Section 4 contains details for the implementation of this interface | |||
| for different prime-order groups instantiated over elliptic curves. | for different prime-order groups instantiated over elliptic curves. | |||
| In particular, for some choices of elliptic curves, e.g., those | In particular, for some choices of elliptic curves, e.g., those | |||
| detailed in [RFC7748], which require accounting for cofactors, | detailed in [RFC7748], which require accounting for cofactors, | |||
| Section 4 describes required steps necessary to ensure the resulting | Section 4 describes required steps necessary to ensure the resulting | |||
| group is of prime order. | group is of prime order. | |||
| skipping to change at line 347 ¶ | skipping to change at line 345 ¶ | |||
| proof is derived from a seed-prefixed hash-to-scalar invocation, | proof is derived from a seed-prefixed hash-to-scalar invocation, | |||
| rather than being sampled from a seeded Pseudorandom Number Generator | rather than being sampled from a seeded Pseudorandom Number Generator | |||
| (PRNG). The description is split into two subsections: one for | (PRNG). The description is split into two subsections: one for | |||
| generating the proof, which is done by servers in the verifiable | generating the proof, which is done by servers in the verifiable | |||
| protocols, and another for verifying the proof, which is done by | protocols, and another for verifying the proof, which is done by | |||
| clients in the protocol. | clients in the protocol. | |||
| 2.2.1. Proof Generation | 2.2.1. Proof Generation | |||
| Generating a proof is done with the GenerateProof function, as | Generating a proof is done with the GenerateProof function, as | |||
| defined below. Given elements A and B, two non-empty lists of | defined below. Given Element values A and B, two non-empty lists of | |||
| elements C and D of length m, and a scalar k; this function produces | Element values C and D of length m, and Scalar k, this function | |||
| a proof that k * A == B and k * C[i] == D[i] for each i in [0, ..., m | produces a proof that k * A == B and k * C[i] == D[i] for each i in | |||
| - 1]. The output is a value of type Proof, which is a tuple of two | [0, ..., m - 1]. The output is a value of type Proof, which is a | |||
| scalar values. We use the notation proof[0] and proof[1] to denote | tuple of two Scalar values. We use the notation proof[0] and | |||
| the first and second elements in this tuple, respectively. | proof[1] to denote the first and second elements in this tuple, | |||
| respectively. | ||||
| GenerateProof accepts lists of inputs to amortize the cost of proof | GenerateProof accepts lists of inputs to amortize the cost of proof | |||
| generation. Applications can take advantage of this functionality to | generation. Applications can take advantage of this functionality to | |||
| produce a single, constant-sized proof for m DLEQ inputs, rather than | produce a single, constant-sized proof for m DLEQ inputs, rather than | |||
| m proofs for m DLEQ inputs. | m proofs for m DLEQ inputs. | |||
| Input: | Input: | |||
| Scalar k | Scalar k | |||
| Element A | Element A | |||
| skipping to change at line 375 ¶ | skipping to change at line 374 ¶ | |||
| Element D[m] | Element D[m] | |||
| Output: | Output: | |||
| Proof proof | Proof proof | |||
| Parameters: | Parameters: | |||
| Group G | Group G | |||
| def GenerateProof(k, A, B, C, D) | def GenerateProof(k, A, B, C, D): | |||
| (M, Z) = ComputeCompositesFast(k, B, C, D) | (M, Z) = ComputeCompositesFast(k, B, C, D) | |||
| r = G.RandomScalar() | r = G.RandomScalar() | |||
| t2 = r * A | t2 = r * A | |||
| t3 = r * M | t3 = r * M | |||
| Bm = G.SerializeElement(B) | Bm = G.SerializeElement(B) | |||
| a0 = G.SerializeElement(M) | a0 = G.SerializeElement(M) | |||
| a1 = G.SerializeElement(Z) | a1 = G.SerializeElement(Z) | |||
| a2 = G.SerializeElement(t2) | a2 = G.SerializeElement(t2) | |||
| skipping to change at line 453 ¶ | skipping to change at line 452 ¶ | |||
| Z = k * M | Z = k * M | |||
| return (M, Z) | return (M, Z) | |||
| When used in the protocol described in Section 3, the parameter | When used in the protocol described in Section 3, the parameter | |||
| contextString is as defined in Section 3.2. | contextString is as defined in Section 3.2. | |||
| 2.2.2. Proof Verification | 2.2.2. Proof Verification | |||
| Verifying a proof is done with the VerifyProof function, as defined | Verifying a proof is done with the VerifyProof function, as defined | |||
| below. This function takes elements A and B, two non-empty lists of | below. This function takes Element values A and B, two non-empty | |||
| elements C and D of length m, and a Proof value output from | lists of Element values C and D of length m, and a Proof value output | |||
| GenerateProof. It outputs a single boolean value indicating whether | from GenerateProof. It outputs a single boolean value indicating | |||
| or not the proof is valid for the given DLEQ inputs. Note this | whether or not the proof is valid for the given DLEQ inputs. Note | |||
| function can verify proofs on lists of inputs whenever the proof was | this function can verify proofs on lists of inputs whenever the proof | |||
| generated as a batched DLEQ proof with the same inputs. | was generated as a batched DLEQ proof with the same inputs. | |||
| Input: | Input: | |||
| Element A | Element A | |||
| Element B | Element B | |||
| Element C[m] | Element C[m] | |||
| Element D[m] | Element D[m] | |||
| Proof proof | Proof proof | |||
| Output: | Output: | |||
| skipping to change at line 730 ¶ | skipping to change at line 729 ¶ | |||
| contextString = CreateContextString(modePOPRF, identifier) | contextString = CreateContextString(modePOPRF, identifier) | |||
| return POPRFServerContext(contextString, skS) | return POPRFServerContext(contextString, skS) | |||
| def SetupPOPRFClient(identifier, pkS): | def SetupPOPRFClient(identifier, pkS): | |||
| contextString = CreateContextString(modePOPRF, identifier) | contextString = CreateContextString(modePOPRF, identifier) | |||
| return POPRFClientContext(contextString, pkS) | return POPRFClientContext(contextString, pkS) | |||
| 3.2.1. Deterministic Key Generation | 3.2.1. Deterministic Key Generation | |||
| This section describes a deterministic key generation function, | This section describes a deterministic key generation function, | |||
| DeriveKeyPair. It accepts a seed of Ns bytes generated from a | DeriveKeyPair. It accepts a seed of 32 bytes generated from a | |||
| cryptographically secure random number generator and an optional | cryptographically secure random number generator and an optional | |||
| (possibly empty) info string. The constant Ns corresponds to the | (possibly empty) info string. Note that, by design, knowledge of | |||
| size in bytes of a serialized scalar and is defined in Section 2.1. | seed and info is necessary to compute this function, which means that | |||
| Note that, by design, knowledge of seed and info is necessary to | the secrecy of the output private key (skS) depends on the secrecy of | |||
| compute this function, which means that the secrecy of the output | seed (since the info string is public). | |||
| private key (skS) depends on the secrecy of seed (since the info | ||||
| string is public). | ||||
| Input: | Input: | |||
| opaque seed[Ns] | opaque seed[32] | |||
| PublicInput info | PublicInput info | |||
| Output: | Output: | |||
| Scalar skS | Scalar skS | |||
| Element pkS | Element pkS | |||
| Parameters: | Parameters: | |||
| Group G | Group G | |||
| skipping to change at line 778 ¶ | skipping to change at line 775 ¶ | |||
| 3.3. Online Protocol | 3.3. Online Protocol | |||
| In the online phase, the client and server engage in a two-message | In the online phase, the client and server engage in a two-message | |||
| protocol to compute the protocol output. This section describes the | protocol to compute the protocol output. This section describes the | |||
| protocol details for each protocol variant. Throughout each | protocol details for each protocol variant. Throughout each | |||
| description, the following parameters are assumed to exist: | description, the following parameters are assumed to exist: | |||
| G: a prime-order group implementing the API described in Section 2.1 | G: a prime-order group implementing the API described in Section 2.1 | |||
| contextString: | contextString: a PublicInput domain separation tag constructed | |||
| a PublicInput domain separation tag constructed during context | during context setup, as created in Section 3.1 | |||
| setup, as created in Section 3.1 | ||||
| skS and pkS: | skS and pkS: a Scalar and Element representing the private and | |||
| a scalar and element representing the private and public keys | public keys configured for the client and server in Section 3.2 | |||
| configured for the client and server in Section 3.2 | ||||
| Applications serialize protocol messages between the client and | Applications serialize protocol messages between the client and | |||
| server for transmission. Elements and scalars are serialized to byte | server for transmission. Element values and Scalar values are | |||
| arrays, and values of type Proof are serialized as the concatenation | serialized to byte arrays, and values of type Proof are serialized as | |||
| of two serialized scalars. Deserializing these values can fail; in | the concatenation of two serialized Scalar values. Deserializing | |||
| which case, the application MUST abort the protocol, raising a | these values can fail; in which case, the application MUST abort the | |||
| DeserializeError failure. | protocol, raising a DeserializeError failure. | |||
| Applications MUST check that input element values received over the | Applications MUST check that input Element values received over the | |||
| wire are not the group identity element. This check is handled after | wire are not the group identity element. This check is handled after | |||
| deserializing element values; see Section 4 for more information and | deserializing Element values; see Section 4 for more information and | |||
| requirements on input validation for each ciphersuite. | requirements on input validation for each ciphersuite. | |||
| 3.3.1. OPRF Protocol | 3.3.1. OPRF Protocol | |||
| The OPRF protocol begins with the client blinding its input, as | The OPRF protocol begins with the client blinding its input, as | |||
| described by the Blind function below. Note that this function can | described by the Blind function below. Note that this function can | |||
| fail with an InvalidInputError error for certain inputs that map to | fail with an InvalidInputError error for certain inputs that map to | |||
| the group identity element. Dealing with this failure is an | the group identity element. Dealing with this failure is an | |||
| application-specific decision; see Section 5.3. | application-specific decision; see Section 5.3. | |||
| skipping to change at line 1227 ¶ | skipping to change at line 1222 ¶ | |||
| Identity(): As defined in [RFC9496]. | Identity(): As defined in [RFC9496]. | |||
| Generator(): As defined in [RFC9496]. | Generator(): As defined in [RFC9496]. | |||
| HashToGroup(): Use hash_to_ristretto255 [RFC9380] with DST = | HashToGroup(): Use hash_to_ristretto255 [RFC9380] with DST = | |||
| "HashToGroup-" || contextString and expand_message = | "HashToGroup-" || contextString and expand_message = | |||
| expand_message_xmd using SHA-512. | expand_message_xmd using SHA-512. | |||
| HashToScalar(): Compute uniform_bytes using expand_message = | HashToScalar(): Compute uniform_bytes using expand_message = | |||
| expand_message_xmd, DST = "HashToScalar-" || contextString, and | expand_message_xmd, DST = "HashToScalar-" || contextString, and | |||
| output length 64, interpret uniform_bytes as a 512-bit integer | an output length of 64 bytes, interpret uniform_bytes as a | |||
| in little-endian order, and reduce the integer modulo | 512-bit integer in little-endian order, and reduce the integer | |||
| Group.Order(). | modulo Group.Order(). | |||
| ScalarInverse(s): Returns the multiplicative inverse of input | ScalarInverse(s): Returns the multiplicative inverse of input | |||
| scalar s mod Group.Order(). | Scalar s mod Group.Order(). | |||
| RandomScalar(): | RandomScalar(): Implemented by returning a uniformly random | |||
| Implemented by returning a uniformly random scalar in the range | Scalar in the range [0, G.Order() - 1]. Refer to Section 4.7 | |||
| [0, G.Order() - 1]. Refer to Section 4.7 for implementation | for implementation guidance. | |||
| guidance. | ||||
| SerializeElement(A): Implemented using the Encode function from | SerializeElement(A): Implemented using the Encode function from | |||
| Section 4.3.2 of [RFC9496]; Ne = 32. | Section 4.3.2 of [RFC9496]; Ne = 32. | |||
| DeserializeElement(buf): Implemented using the Decode function | DeserializeElement(buf): Implemented using the Decode function | |||
| from Section 4.3.1 of [RFC9496]. Additionally, this function | from Section 4.3.1 of [RFC9496]. Additionally, this function | |||
| validates that the resulting element is not the group identity | validates that the resulting element is not the group identity | |||
| element. If these checks fail, deserialization returns an | element. If these checks fail, deserialization returns an | |||
| InputValidationError error. | InputValidationError error. | |||
| SerializeScalar(s): | SerializeScalar(s): Implemented by outputting the little-endian, | |||
| Implemented by outputting the little-endian, 32-byte encoding | 32-byte encoding of the Scalar value with the top three bits | |||
| of the scalar value with the top three bits set to zero; Ns = | set to zero; Ns = 32. | |||
| 32. | ||||
| DeserializeScalar(buf): | DeserializeScalar(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a scalar from a | a Scalar from a little-endian, 32-byte string. This function | |||
| little-endian, 32-byte string. This function can fail if the | can fail if the input does not represent a Scalar in the range | |||
| input does not represent a scalar in the range [0, G.Order() - | [0, G.Order() - 1]. Note that this means the top three bits of | |||
| 1]. Note that this means the top three bits of the input MUST | the input MUST be zero. | |||
| be zero. | ||||
| Hash: SHA-512; Nh = 64. | Hash: SHA-512; Nh = 64. | |||
| 4.2. OPRF(decaf448, SHAKE-256) | 4.2. OPRF(decaf448, SHAKE-256) | |||
| This ciphersuite uses decaf448 [RFC9496] for the Group and SHAKE-256 | This ciphersuite uses decaf448 [RFC9496] for the Group and SHAKE-256 | |||
| for the hash function. The value of the ciphersuite identifier is | for the hash function. The value of the ciphersuite identifier is | |||
| "decaf448-SHAKE256". | "decaf448-SHAKE256". | |||
| Group: decaf448 [RFC9496] | Group: decaf448 [RFC9496] | |||
| Order(): Return 2^446 - 13818066809895115352007386748515426880336 | Order(): Return 2^446 - 13818066809895115352007386748515426880336 | |||
| 692474882178609894547503885. | 692474882178609894547503885. | |||
| Identity(): As defined in [RFC9496]. | Identity(): As defined in [RFC9496]. | |||
| Generator(): As defined in [RFC9496]. | Generator(): As defined in [RFC9496]. | |||
| RandomScalar(): | RandomScalar(): Implemented by returning a uniformly random | |||
| Implemented by returning a uniformly random scalar in the range | Scalar in the range [0, G.Order() - 1]. Refer to Section 4.7 | |||
| [0, G.Order() - 1]. Refer to Section 4.7 for implementation | for implementation guidance. | |||
| guidance. | ||||
| HashToGroup(): Use hash_to_decaf448 [RFC9380] with DST = | HashToGroup(): Use hash_to_decaf448 [RFC9380] with DST = | |||
| "HashToGroup-" || contextString and expand_message = | "HashToGroup-" || contextString and expand_message = | |||
| expand_message_xof using SHAKE-256. | expand_message_xof using SHAKE-256. | |||
| HashToScalar(): Compute uniform_bytes using expand_message = | HashToScalar(): Compute uniform_bytes using expand_message = | |||
| expand_message_xof, DST = "HashToScalar-" || contextString, and | expand_message_xof, DST = "HashToScalar-" || contextString, and | |||
| output length 64, interpret uniform_bytes as a 512-bit integer | output length 64, interpret uniform_bytes as a 512-bit integer | |||
| in little-endian order, and reduce the integer modulo | in little-endian order, and reduce the integer modulo | |||
| Group.Order(). | Group.Order(). | |||
| ScalarInverse(s): Returns the multiplicative inverse of input | ScalarInverse(s): Returns the multiplicative inverse of input | |||
| scalar s mod Group.Order(). | Scalar s mod Group.Order(). | |||
| SerializeElement(A): Implemented using the Encode function from | SerializeElement(A): Implemented using the Encode function from | |||
| Section 5.3.2 of [RFC9496]; Ne = 56. | Section 5.3.2 of [RFC9496]; Ne = 56. | |||
| DeserializeElement(buf): Implemented using the Decode function | DeserializeElement(buf): Implemented using the Decode function | |||
| from Section 5.3.1 of [RFC9496]. Additionally, this function | from Section 5.3.1 of [RFC9496]. Additionally, this function | |||
| validates that the resulting element is not the group identity | validates that the resulting element is not the group identity | |||
| element. If these checks fail, deserialization returns an | element. If these checks fail, deserialization returns an | |||
| InputValidationError error. | InputValidationError error. | |||
| SerializeScalar(s): | SerializeScalar(s): Implemented by outputting the little-endian, | |||
| Implemented by outputting the little-endian, 56-byte encoding | 56-byte encoding of the Scalar value; Ns = 56. | |||
| of the scalar value; Ns = 56. | ||||
| DeserializeScalar(buf): | DeserializeScalar(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a scalar from a | a Scalar from a little-endian, 56-byte string. This function | |||
| little-endian, 56-byte string. This function can fail if the | can fail if the input does not represent a Scalar in the range | |||
| input does not represent a scalar in the range [0, G.Order() - | [0, G.Order() - 1]. | |||
| 1]. | ||||
| Hash: SHAKE-256; Nh = 64. | Hash: SHAKE-256; Nh = 64. | |||
| 4.3. OPRF(P-256, SHA-256) | 4.3. OPRF(P-256, SHA-256) | |||
| This ciphersuite uses P-256 [NISTCurves] for the Group and SHA-256 | This ciphersuite uses P-256 [NISTCurves] for the Group and SHA-256 | |||
| for the hash function. The value of the ciphersuite identifier is | for the hash function. The value of the ciphersuite identifier is | |||
| "P256-SHA256". | "P256-SHA256". | |||
| Group: P-256 (secp256r1) [NISTCurves] | Group: P-256 (secp256r1) [NISTCurves] | |||
| Order(): | Order(): Return 0xffffffff00000000ffffffffffffffffbce6faada7179e8 | |||
| Return 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9ca | 4f3b9cac2fc632551. | |||
| c2fc632551. | ||||
| Identity(): As defined in [NISTCurves]. | Identity(): As defined in [NISTCurves]. | |||
| Generator(): As defined in [NISTCurves]. | Generator(): As defined in [NISTCurves]. | |||
| RandomScalar(): | RandomScalar(): Implemented by returning a uniformly random | |||
| Implemented by returning a uniformly random scalar in the range | Scalar in the range [0, G.Order() - 1]. Refer to Section 4.7 | |||
| [0, G.Order() - 1]. Refer to Section 4.7 for implementation | for implementation guidance. | |||
| guidance. | ||||
| HashToGroup(): Use hash_to_curve with suite P256_XMD:SHA- | HashToGroup(): Use hash_to_curve with suite P256_XMD:SHA- | |||
| 256_SSWU_RO_ [RFC9380] and DST = "HashToGroup-" || | 256_SSWU_RO_ [RFC9380] and DST = "HashToGroup-" || | |||
| contextString. | contextString. | |||
| HashToScalar(): Use hash_to_field from [RFC9380] using L = 48, | HashToScalar(): Use hash_to_field from [RFC9380] using L = 48, | |||
| expand_message_xmd with SHA-256, DST = "HashToScalar-" || | expand_message_xmd with SHA-256, DST = "HashToScalar-" || | |||
| contextString, and a prime modulus equal to Group.Order(). | contextString, and a prime modulus equal to Group.Order(). | |||
| ScalarInverse(s): Returns the multiplicative inverse of input | ScalarInverse(s): Returns the multiplicative inverse of input | |||
| scalar s mod Group.Order(). | Scalar s mod Group.Order(). | |||
| SerializeElement(A): | SerializeElement(A): Implemented using the compressed Elliptic- | |||
| Implemented using the compressed Elliptic-Curve-Point-to-Octet- | Curve-Point-to-Octet-String method according to [SEC1]; Ne = | |||
| String method according to [SEC1]; Ne = 33. | 33. | |||
| DeserializeElement(buf): | DeserializeElement(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a 33-byte input string | a 33-byte input string to a public key using the compressed | |||
| to a public key using the compressed Octet-String-to-Elliptic- | Octet-String-to-Elliptic-Curve-Point method according to [SEC1] | |||
| Curve-Point method according to [SEC1] and then performing | and then performing partial public-key validation, as defined | |||
| partial public-key validation, as defined in Section 5.6.2.3.4 | in Section 5.6.2.3.4 of [KEYAGREEMENT]. This includes checking | |||
| of [KEYAGREEMENT]. This includes checking that the coordinates | that the coordinates of the resulting point are in the correct | |||
| of the resulting point are in the correct range, that the point | range, that the point is on the curve, and that the point is | |||
| is on the curve, and that the point is not the group identity | not the group identity element. If these checks fail, | |||
| element. If these checks fail, deserialization returns an | deserialization returns an InputValidationError error. | |||
| InputValidationError error. | ||||
| SerializeScalar(s): | SerializeScalar(s): Implemented using the Field-Element-to-Octet- | |||
| Implemented using the Field-Element-to-Octet-String conversion | String conversion according to [SEC1]; Ns = 32. | |||
| according to [SEC1]; Ns = 32. | ||||
| DeserializeScalar(buf): | DeserializeScalar(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a scalar from a | a Scalar from a 32-byte string using Octet-String-to-Field- | |||
| 32-byte string using Octet-String-to-Field-Element from [SEC1]. | Element from [SEC1]. This function can fail if the input does | |||
| This function can fail if the input does not represent a scalar | not represent a Scalar in the range [0, G.Order() - 1]. | |||
| in the range [0, G.Order() - 1]. | ||||
| Hash: SHA-256; Nh = 32. | Hash: SHA-256; Nh = 32. | |||
| 4.4. OPRF(P-384, SHA-384) | 4.4. OPRF(P-384, SHA-384) | |||
| This ciphersuite uses P-384 [NISTCurves] for the Group and SHA-384 | This ciphersuite uses P-384 [NISTCurves] for the Group and SHA-384 | |||
| for the hash function. The value of the ciphersuite identifier is | for the hash function. The value of the ciphersuite identifier is | |||
| "P384-SHA384". | "P384-SHA384". | |||
| Group: P-384 (secp384r1) [NISTCurves] | Group: P-384 (secp384r1) [NISTCurves] | |||
| Order(): | Order(): Return 0xfffffffffffffffffffffffffffffffffffffffffffffff | |||
| Return 0xffffffffffffffffffffffffffffffffffffffffffffffffc7634d | fc7634d81f4372ddf581a0db248b0a77aecec196accc52973. | |||
| 81f4372ddf581a0db248b0a77aecec196accc52973. | ||||
| Identity(): As defined in [NISTCurves]. | Identity(): As defined in [NISTCurves]. | |||
| Generator(): As defined in [NISTCurves]. | Generator(): As defined in [NISTCurves]. | |||
| RandomScalar(): | RandomScalar(): Implemented by returning a uniformly random | |||
| Implemented by returning a uniformly random scalar in the range | Scalar in the range [0, G.Order() - 1]. Refer to Section 4.7 | |||
| [0, G.Order() - 1]. Refer to Section 4.7 for implementation | for implementation guidance. | |||
| guidance. | ||||
| HashToGroup(): Use hash_to_curve with suite P384_XMD:SHA- | HashToGroup(): Use hash_to_curve with suite P384_XMD:SHA- | |||
| 384_SSWU_RO_ [RFC9380] and DST = "HashToGroup-" || | 384_SSWU_RO_ [RFC9380] and DST = "HashToGroup-" || | |||
| contextString. | contextString. | |||
| HashToScalar(): Use hash_to_field from [RFC9380] using L = 72, | HashToScalar(): Use hash_to_field from [RFC9380] using L = 72, | |||
| expand_message_xmd with SHA-384, DST = "HashToScalar-" || | expand_message_xmd with SHA-384, DST = "HashToScalar-" || | |||
| contextString, and a prime modulus equal to Group.Order(). | contextString, and a prime modulus equal to Group.Order(). | |||
| ScalarInverse(s): Returns the multiplicative inverse of input | ScalarInverse(s): Returns the multiplicative inverse of input | |||
| scalar s mod Group.Order(). | Scalar s mod Group.Order(). | |||
| SerializeElement(A): | SerializeElement(A): Implemented using the compressed Elliptic- | |||
| Implemented using the compressed Elliptic-Curve-Point-to-Octet- | Curve-Point-to-Octet-String method according to [SEC1]; Ne = | |||
| String method according to [SEC1]; Ne = 49. | 49. | |||
| DeserializeElement(buf): | DeserializeElement(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a 49-byte array to a | a 49-byte array to a public key using the compressed Octet- | |||
| public key using the compressed Octet-String-to-Elliptic-Curve- | String-to-Elliptic-Curve-Point method according to [SEC1] and | |||
| Point method according to [SEC1] and then performing partial | then performing partial public-key validation, as defined in | |||
| public-key validation, as defined in Section 5.6.2.3.4 of | Section 5.6.2.3.4 of [KEYAGREEMENT]. This includes checking | |||
| [KEYAGREEMENT]. This includes checking that the coordinates of | that the coordinates of the resulting point are in the correct | |||
| the resulting point are in the correct range, that the point is | range, that the point is on the curve, and that the point is | |||
| on the curve, and that the point is not the point at infinity. | not the point at infinity. Additionally, this function | |||
| Additionally, this function validates that the resulting | validates that the resulting element is not the group identity | |||
| element is not the group identity element. If these checks | element. If these checks fail, deserialization returns an | |||
| fail, deserialization returns an InputValidationError error. | InputValidationError error. | |||
| SerializeScalar(s): | SerializeScalar(s): Implemented using the Field-Element-to-Octet- | |||
| Implemented using the Field-Element-to-Octet-String conversion | String conversion according to [SEC1]; Ns = 48. | |||
| according to [SEC1]; Ns = 48. | ||||
| DeserializeScalar(buf): | DeserializeScalar(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a scalar from a | a Scalar from a 48-byte string using Octet-String-to-Field- | |||
| 48-byte string using Octet-String-to-Field-Element from [SEC1]. | Element from [SEC1]. This function can fail if the input does | |||
| This function can fail if the input does not represent a scalar | not represent a Scalar in the range [0, G.Order() - 1]. | |||
| in the range [0, G.Order() - 1]. | ||||
| Hash: SHA-384; Nh = 48. | Hash: SHA-384; Nh = 48. | |||
| 4.5. OPRF(P-521, SHA-512) | 4.5. OPRF(P-521, SHA-512) | |||
| This ciphersuite uses P-521 [NISTCurves] for the Group and SHA-512 | This ciphersuite uses P-521 [NISTCurves] for the Group and SHA-512 | |||
| for the hash function. The value of the ciphersuite identifier is | for the hash function. The value of the ciphersuite identifier is | |||
| "P521-SHA512". | "P521-SHA512". | |||
| Group: P-521 (secp521r1) [NISTCurves] | Group: P-521 (secp521r1) [NISTCurves] | |||
| Order(): | Order(): Return 0x01fffffffffffffffffffffffffffffffffffffffffffff | |||
| Return 0x01ffffffffffffffffffffffffffffffffffffffffffffffffffff | ffffffffffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b889 | |||
| fffffffffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aeb | 9c47aebb6fb71e91386409. | |||
| b6fb71e91386409. | ||||
| Identity(): As defined in [NISTCurves]. | Identity(): As defined in [NISTCurves]. | |||
| Generator(): As defined in [NISTCurves]. | Generator(): As defined in [NISTCurves]. | |||
| RandomScalar(): | RandomScalar(): Implemented by returning a uniformly random | |||
| Implemented by returning a uniformly random scalar in the range | Scalar in the range [0, G.Order() - 1]. Refer to Section 4.7 | |||
| [0, G.Order() - 1]. Refer to Section 4.7 for implementation | for implementation guidance. | |||
| guidance. | ||||
| HashToGroup(): Use hash_to_curve with suite P521_XMD:SHA- | HashToGroup(): Use hash_to_curve with suite P521_XMD:SHA- | |||
| 512_SSWU_RO_ [RFC9380] and DST = "HashToGroup-" || | 512_SSWU_RO_ [RFC9380] and DST = "HashToGroup-" || | |||
| contextString. | contextString. | |||
| HashToScalar(): Use hash_to_field from [RFC9380] using L = 98, | HashToScalar(): Use hash_to_field from [RFC9380] using L = 98, | |||
| expand_message_xmd with SHA-512, DST = "HashToScalar-" || | expand_message_xmd with SHA-512, DST = "HashToScalar-" || | |||
| contextString, and a prime modulus equal to Group.Order(). | contextString, and a prime modulus equal to Group.Order(). | |||
| ScalarInverse(s): Returns the multiplicative inverse of input | ScalarInverse(s): Returns the multiplicative inverse of input | |||
| scalar s mod Group.Order(). | Scalar s mod Group.Order(). | |||
| SerializeElement(A): | SerializeElement(A): Implemented using the compressed Elliptic- | |||
| Implemented using the compressed Elliptic-Curve-Point-to-Octet- | Curve-Point-to-Octet-String method according to [SEC1]; Ne = | |||
| String method according to [SEC1]; Ne = 67. | 67. | |||
| DeserializeElement(buf): | DeserializeElement(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a 49-byte input string | a 67-byte input string to a public key using the compressed | |||
| to a public key using the compressed Octet-String-to-Elliptic- | Octet-String-to-Elliptic-Curve-Point method according to [SEC1] | |||
| Curve-Point method according to [SEC1] and then performing | and then performing partial public-key validation, as defined | |||
| partial public-key validation, as defined in Section 5.6.2.3.4 | in Section 5.6.2.3.4 of [KEYAGREEMENT]. This includes checking | |||
| of [KEYAGREEMENT]. This includes checking that the coordinates | that the coordinates of the resulting point are in the correct | |||
| of the resulting point are in the correct range, that the point | range, that the point is on the curve, and that the point is | |||
| is on the curve, and that the point is not the point at | not the point at infinity. Additionally, this function | |||
| infinity. Additionally, this function validates that the | validates that the resulting element is not the group identity | |||
| resulting element is not the group identity element. If these | element. If these checks fail, deserialization returns an | |||
| checks fail, deserialization returns an InputValidationError | InputValidationError error. | |||
| error. | ||||
| SerializeScalar(s): | SerializeScalar(s): Implemented using the Field-Element-to-Octet- | |||
| Implemented using the Field-Element-to-Octet-String conversion | String conversion according to [SEC1]; Ns = 66. | |||
| according to [SEC1]; Ns = 66. | ||||
| DeserializeScalar(buf): | DeserializeScalar(buf): Implemented by attempting to deserialize | |||
| Implemented by attempting to deserialize a scalar from a | a Scalar from a 66-byte string using Octet-String-to-Field- | |||
| 66-byte string using Octet-String-to-Field-Element from [SEC1]. | Element from [SEC1]. This function can fail if the input does | |||
| This function can fail if the input does not represent a scalar | not represent a Scalar in the range [0, G.Order() - 1]. | |||
| in the range [0, G.Order() - 1]. | ||||
| Hash: SHA-512; Nh = 64. | Hash: SHA-512; Nh = 64. | |||
| 4.6. Future Ciphersuites | 4.6. Future Ciphersuites | |||
| A critical requirement of implementing the prime-order group using | A critical requirement of implementing the prime-order group using | |||
| elliptic curves is a method to instantiate the function HashToGroup, | elliptic curves is a method to instantiate the function HashToGroup, | |||
| which maps inputs to group elements. In the elliptic curve setting, | which maps inputs to group elements. In the elliptic curve setting, | |||
| this deterministically maps inputs (as byte arrays) to uniformly | this deterministically maps inputs (as byte arrays) to uniformly | |||
| chosen points on the curve. | chosen points on the curve. | |||
| skipping to change at line 1532 ¶ | skipping to change at line 1507 ¶ | |||
| 4.7. Random Scalar Generation | 4.7. Random Scalar Generation | |||
| Two popular algorithms for generating a random integer uniformly | Two popular algorithms for generating a random integer uniformly | |||
| distributed in the range [0, G.Order() - 1] are described in the | distributed in the range [0, G.Order() - 1] are described in the | |||
| following subsections. | following subsections. | |||
| 4.7.1. Rejection Sampling | 4.7.1. Rejection Sampling | |||
| Generate a random byte array with Ns bytes and attempt to map to a | Generate a random byte array with Ns bytes and attempt to map to a | |||
| scalar by calling DeserializeScalar in constant time. If it | Scalar by calling DeserializeScalar in constant time. If it | |||
| succeeds, return the result. If it fails, try again with another | succeeds, return the result. If it fails, try again with another | |||
| random byte array until the procedure succeeds. Failure to implement | random byte array until the procedure succeeds. Failure to implement | |||
| DeserializeScalar in constant time can leak information about the | DeserializeScalar in constant time can leak information about the | |||
| underlying corresponding scalar. | underlying corresponding Scalar. | |||
| As an optimization, if the group order is very close to a power of 2, | As an optimization, if the group order is very close to a power of 2, | |||
| it is acceptable to omit the rejection test completely. In | it is acceptable to omit the rejection test completely. In | |||
| particular, if the group order is p and there is an integer b such | particular, if the group order is p and there is an integer b such | |||
| that |p - 2^b| is less than 2^(b/2), then RandomScalar can simply | that |p - 2^b| is less than 2^(b/2), then RandomScalar can simply | |||
| return a uniformly random integer of at most b bits. | return a uniformly random integer of at most b bits. | |||
| 4.7.2. Random Number Generation Using Extra Random Bits | 4.7.2. Random Number Generation Using Extra Random Bits | |||
| Generate a random byte array with L = ceil(((3 * | Generate a random byte array with L = ceil(((3 * | |||
| skipping to change at line 1572 ¶ | skipping to change at line 1547 ¶ | |||
| these longer inputs to a fixed-length input that fits within the | these longer inputs to a fixed-length input that fits within the | |||
| PublicInput or PrivateInput length bounds. Note that some | PublicInput or PrivateInput length bounds. Note that some | |||
| cryptographic hash functions have input length restrictions | cryptographic hash functions have input length restrictions | |||
| themselves, but these limits are often large enough to not be a | themselves, but these limits are often large enough to not be a | |||
| concern in practice. For example, SHA-256 has an input limit of 2^61 | concern in practice. For example, SHA-256 has an input limit of 2^61 | |||
| bytes. | bytes. | |||
| 5.2. External Interface Recommendations | 5.2. External Interface Recommendations | |||
| In Section 3.3, the interface of the protocol functions allows that | In Section 3.3, the interface of the protocol functions allows that | |||
| some inputs (and outputs) to be group elements and scalars. However, | some inputs (and outputs) to be group Element and Scalar values. | |||
| implementations can instead operate over group elements and scalars | However, implementations can instead operate over Element and Scalar | |||
| internally and only expose interfaces that operate with an | values internally and only expose interfaces that operate with an | |||
| application-specific format of messages. | application-specific format of messages. | |||
| 5.3. Error Considerations | 5.3. Error Considerations | |||
| Some OPRF variants specified in this document have fallible | Some OPRF variants specified in this document have fallible | |||
| operations. For example, Finalize and BlindEvaluate can fail if any | operations. For example, Finalize and BlindEvaluate can fail if any | |||
| element received from the peer fails input validation. The explicit | element received from the peer fails input validation. The explicit | |||
| errors generated throughout this specification, along with the | errors generated throughout this specification, along with the | |||
| conditions that lead to each error, are as follows: | conditions that lead to each error, are as follows: | |||
| VerifyError: Verifiable OPRF proof verification failed (Sections | VerifyError: Verifiable OPRF proof verification failed (Sections | |||
| 3.3.2 and 3.3.3). | 3.3.2 and 3.3.3). | |||
| DeserializeError: Group element or scalar deserialization failure | DeserializeError: Group Element or Scalar deserialization failure | |||
| (Sections 2.1 and 3.3). | (Sections 2.1 and 3.3). | |||
| InputValidationError: Validation of byte array inputs failed | InputValidationError: Validation of byte array inputs failed | |||
| (Section 4). | (Section 4). | |||
| There are other explicit errors generated in this specification; | There are other explicit errors generated in this specification; | |||
| however, they occur with negligible probability in practice. We note | however, they occur with negligible probability in practice. We note | |||
| them here for completeness. | them here for completeness. | |||
| InvalidInputError: OPRF Blind input produces an invalid output | InvalidInputError: OPRF Blind input produces an invalid output | |||
| element (Sections 3.3.1 and 3.3.3). | element (Sections 3.3.1 and 3.3.3). | |||
| InverseError: | InverseError: A tweaked private key is invalid, i.e., has no | |||
| A tweaked private key is invalid, i.e., has no multiplicative | multiplicative inverse (Sections 2.1 and 3.3). | |||
| inverse (Sections 2.1 and 3.3). | ||||
| In general, the errors in this document are meant as a guide to | In general, the errors in this document are meant as a guide to | |||
| implementors. They are not an exhaustive list of all the errors an | implementors. They are not an exhaustive list of all the errors an | |||
| implementation might emit. For example, implementations might run | implementation might emit. For example, implementations might run | |||
| out of memory and return a corresponding error. | out of memory and return a corresponding error. | |||
| 5.4. POPRF Public Input | 5.4. POPRF Public Input | |||
| Functionally, the VOPRF and POPRF variants differ in that the POPRF | Functionally, the VOPRF and POPRF variants differ in that the POPRF | |||
| variant admits public input, whereas the VOPRF variant does not. | variant admits public input, whereas the VOPRF variant does not. | |||
| skipping to change at line 1652 ¶ | skipping to change at line 1626 ¶ | |||
| from the implementation of the protocol variants in this document. | from the implementation of the protocol variants in this document. | |||
| Note that the syntax of the POPRF variant is different from that of | Note that the syntax of the POPRF variant is different from that of | |||
| the OPRF and VOPRF variants since it admits an additional public | the OPRF and VOPRF variants since it admits an additional public | |||
| input, but the same security considerations apply. | input, but the same security considerations apply. | |||
| 7.1. Security Properties | 7.1. Security Properties | |||
| The security properties of an OPRF protocol with functionality y = | The security properties of an OPRF protocol with functionality y = | |||
| F(k, x) include those of a standard PRF. Specifically: | F(k, x) include those of a standard PRF. Specifically: | |||
| Pseudorandomness: | Pseudorandomness: For a random sampling of k, F is pseudorandom if | |||
| For a random sampling of k, F is pseudorandom if the output y = | the output y = F(k, x) on any input x is indistinguishable from | |||
| F(k, x) on any input x is indistinguishable from uniformly | uniformly sampling any element in F's range. | |||
| sampling any element in F's range. | ||||
| In other words, consider an adversary that picks inputs x from the | In other words, consider an adversary that picks inputs x from the | |||
| domain of F and evaluates F on (k, x) (without knowledge of randomly | domain of F and evaluates F on (k, x) (without knowledge of randomly | |||
| sampled k). Then, the output distribution F(k, x) is | sampled k). Then, the output distribution F(k, x) is | |||
| indistinguishable from the output distribution of a randomly chosen | indistinguishable from the output distribution of a randomly chosen | |||
| function with the same domain and range. | function with the same domain and range. | |||
| A consequence of showing that a function is pseudorandom is that it | A consequence of showing that a function is pseudorandom is that it | |||
| is necessarily nonmalleable (i.e., we cannot compute a new evaluation | is necessarily nonmalleable (i.e., we cannot compute a new evaluation | |||
| of F from an existing evaluation). A genuinely random function will | of F from an existing evaluation). A genuinely random function will | |||
| be nonmalleable with high probability, so a pseudorandom function | be nonmalleable with high probability, so a pseudorandom function | |||
| must be nonmalleable to maintain indistinguishability. | must be nonmalleable to maintain indistinguishability. | |||
| Unconditional input secrecy: | Unconditional input secrecy: The server does not learn anything | |||
| The server does not learn anything about the client input x, even | about the client input x, even with unbounded computation. | |||
| with unbounded computation. | ||||
| In other words, an attacker with infinite computing power cannot | In other words, an attacker with infinite computing power cannot | |||
| recover any information about the client's private input x from an | recover any information about the client's private input x from an | |||
| invocation of the protocol. | invocation of the protocol. | |||
| Essentially, input secrecy is the property that, even if the server | Essentially, input secrecy is the property that, even if the server | |||
| learns the client's private input x at some point in the future, the | learns the client's private input x at some point in the future, the | |||
| server cannot link any particular PRF evaluation to x. This property | server cannot link any particular PRF evaluation to x. This property | |||
| is also known as unlinkability [DGSTV18]. | is also known as unlinkability [DGSTV18]. | |||
| Beyond client input secrecy, in the OPRF protocol, the server learns | Beyond client input secrecy, in the OPRF protocol, the server learns | |||
| nothing about the output y of the function, nor does the client learn | nothing about the output y of the function, nor does the client learn | |||
| anything about the server's private key k. | anything about the server's private key k. | |||
| For the VOPRF and POPRF protocol variants, there is an additional | For the VOPRF and POPRF protocol variants, there is an additional | |||
| security property: | security property: | |||
| Verifiable: | Verifiable: The client must only complete execution of the protocol | |||
| The client must only complete execution of the protocol if it can | if it can successfully assert that the output it computes is | |||
| successfully assert that the output it computes is correct. This | correct. This is taken with respect to the private key held by | |||
| is taken with respect to the private key held by the server. | the server. | |||
| Any VOPRF or POPRF that satisfies the 'verifiable' security property | Any VOPRF or POPRF that satisfies the 'verifiable' security property | |||
| is known as 'verifiable'. In practice, the notion of verifiability | is known as 'verifiable'. In practice, the notion of verifiability | |||
| requires that the server commits to the key before the actual | requires that the server commits to the key before the actual | |||
| protocol execution takes place. Then, the client verifies that the | protocol execution takes place. Then, the client verifies that the | |||
| server has used the key in the protocol using this commitment. In | server has used the key in the protocol using this commitment. In | |||
| the following, we may also refer to this commitment as a public key. | the following, we may also refer to this commitment as a public key. | |||
| Finally, the POPRF variant also has the following security property: | Finally, the POPRF variant also has the following security property: | |||
| Partial obliviousness: | Partial obliviousness: The client and server must be able to perform | |||
| The client and server must be able to perform the PRF on the | the PRF on the client's private and public input. Both the client | |||
| client's private and public input. Both the client and server | and server know the public input, but similar to the OPRF and | |||
| know the public input, but similar to the OPRF and VOPRF | VOPRF protocols, the server learns nothing about the client's | |||
| protocols, the server learns nothing about the client's private | private input or the output of the function, and the client learns | |||
| input or the output of the function, and the client learns nothing | nothing about the server's private key. | |||
| about the server's private key. | ||||
| This property becomes useful when dealing with key management | This property becomes useful when dealing with key management | |||
| operations, such as the rotation of the server's keys. Note that | operations, such as the rotation of the server's keys. Note that | |||
| partial obliviousness only applies to the POPRF variant because | partial obliviousness only applies to the POPRF variant because | |||
| neither the OPRF nor VOPRF variants accept public input to the | neither the OPRF nor VOPRF variants accept public input to the | |||
| protocol. | protocol. | |||
| Since the POPRF variant has a different syntax than the OPRF and | Since the POPRF variant has a different syntax than the OPRF and | |||
| VOPRF variants, i.e., y = F(k, x, info), the pseudorandomness | VOPRF variants, i.e., y = F(k, x, info), the pseudorandomness | |||
| property is generalized: | property is generalized: | |||
| Pseudorandomness: | Pseudorandomness: For a random sampling of k, F is pseudorandom if | |||
| For a random sampling of k, F is pseudorandom if the output y = | the output y = F(k, x, info) on any input pairs (x, info) is | |||
| F(k, x, info) on any input pairs (x, info) is indistinguishable | indistinguishable from uniformly sampling any element in F's | |||
| from uniformly sampling any element in F's range. | range. | |||
| 7.2. Security Assumptions | 7.2. Security Assumptions | |||
| Below, we discuss the cryptographic security of each protocol variant | Below, we discuss the cryptographic security of each protocol variant | |||
| from Section 3, relative to the necessary cryptographic assumptions | from Section 3, relative to the necessary cryptographic assumptions | |||
| that need to be made. | that need to be made. | |||
| 7.2.1. OPRF and VOPRF Assumptions | 7.2.1. OPRF and VOPRF Assumptions | |||
| The OPRF and VOPRF protocol variants in this document are based on | The OPRF and VOPRF protocol variants in this document are based on | |||
| skipping to change at line 1902 ¶ | skipping to change at line 1873 ¶ | |||
| [JKKX16] Jarecki, S., Kiayias, A., Krawczyk, H., and J. Xu, | [JKKX16] Jarecki, S., Kiayias, A., Krawczyk, H., and J. Xu, | |||
| "Highly-Efficient and Composable Password-Protected Secret | "Highly-Efficient and Composable Password-Protected Secret | |||
| Sharing (Or: How to Protect Your Bitcoin Wallet Online)", | Sharing (Or: How to Protect Your Bitcoin Wallet Online)", | |||
| 2016 IEEE European Symposium on Security and Privacy | 2016 IEEE European Symposium on Security and Privacy | |||
| (EuroS&P), DOI 10.1109/eurosp.2016.30, March 2016, | (EuroS&P), DOI 10.1109/eurosp.2016.30, March 2016, | |||
| <https://doi.org/10.1109/eurosp.2016.30>. | <https://doi.org/10.1109/eurosp.2016.30>. | |||
| [NISTCurves] | [NISTCurves] | |||
| National Institute of Standards and Technology (NIST), | National Institute of Standards and Technology (NIST), | |||
| "Digital Signature Standard (DSS)", FIPS PUB 186-4, | "Digital Signature Standard (DSS)", FIPS PUB 186-5, | |||
| DOI 10.6028/nist.fips.186-4, July 2013, | DOI 10.6028/NIST.FIPS.186-5, February 2023, | |||
| <https://doi.org/10.6028/nist.fips.186-4>. | <https://doi.org/10.6028/NIST.FIPS.186-5>. | |||
| [OPAQUE] Bourdrez, D., Krawczyk, H., Lewi, K., and C. A. Wood, "The | [OPAQUE] Bourdrez, D., Krawczyk, H., Lewi, K., and C. A. Wood, "The | |||
| OPAQUE Asymmetric PAKE Protocol", Work in Progress, | OPAQUE Asymmetric PAKE Protocol", Work in Progress, | |||
| Internet-Draft, draft-irtf-cfrg-opaque-11, 8 June 2023, | Internet-Draft, draft-irtf-cfrg-opaque-12, 5 October 2023, | |||
| <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg- | <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg- | |||
| opaque-11>. | opaque-12>. | |||
| [PRIVACY-PASS] | [PRIVACY-PASS] | |||
| Celi, S., Davidson, A., Valdez, S., and C. A. Wood, | Celi, S., Davidson, A., Valdez, S., and C. A. Wood, | |||
| "Privacy Pass Issuance Protocol", Work in Progress, | "Privacy Pass Issuance Protocol", Work in Progress, | |||
| Internet-Draft, draft-ietf-privacypass-protocol-16, 3 | Internet-Draft, draft-ietf-privacypass-protocol-16, 3 | |||
| October 2023, <https://datatracker.ietf.org/doc/html/ | October 2023, <https://datatracker.ietf.org/doc/html/ | |||
| draft-ietf-privacypass-protocol-16>. | draft-ietf-privacypass-protocol-16>. | |||
| [PrivacyPass] | [PrivacyPass] | |||
| "Privacy Pass", commit 085380a, March 2018, | "Privacy Pass", commit 085380a, March 2018, | |||
| skipping to change at line 1957 ¶ | skipping to change at line 1928 ¶ | |||
| This section includes test vectors for the protocol variants | This section includes test vectors for the protocol variants | |||
| specified in this document. For each ciphersuite specified in | specified in this document. For each ciphersuite specified in | |||
| Section 4, there is a set of test vectors for the protocol when | Section 4, there is a set of test vectors for the protocol when | |||
| running the OPRF, VOPRF, and POPRF modes. Each test vector lists the | running the OPRF, VOPRF, and POPRF modes. Each test vector lists the | |||
| batch size for the evaluation. Each test vector value is encoded as | batch size for the evaluation. Each test vector value is encoded as | |||
| a hexadecimal byte string. The fields of each test vector are | a hexadecimal byte string. The fields of each test vector are | |||
| described below. | described below. | |||
| "Input": The private client input, an opaque byte string. | "Input": The private client input, an opaque byte string. | |||
| "Info": | "Info": The public info, an opaque byte string. Only present for | |||
| The public info, an opaque byte string. Only present for POPRF | POPRF test vectors. | |||
| test vectors. | ||||
| "Blind": The blind value output by Blind(), a serialized scalar of | "Blind": The blind value output by Blind(), a serialized Scalar of | |||
| Ns bytes long. | Ns bytes long. | |||
| "BlindedElement": The blinded value output by Blind(), a serialized | "BlindedElement": The blinded value output by Blind(), a serialized | |||
| element of Ne bytes long. | Element of Ne bytes long. | |||
| "EvaluatedElement": The evaluated element output by BlindEvaluate(), | "EvaluatedElement": The evaluated element output by BlindEvaluate(), | |||
| a serialized element of Ne bytes long. | a serialized Element of Ne bytes long. | |||
| "Proof": The serialized Proof output from GenerateProof() composed | "Proof": The serialized Proof output from GenerateProof() composed | |||
| of two serialized scalar values, each Ns bytes long. Only present | of two serialized Scalar values, each Ns bytes long. Only present | |||
| for VOPRF and POPRF test vectors. | for VOPRF and POPRF test vectors. | |||
| "ProofRandomScalar": The random scalar r computed in | "ProofRandomScalar": The random Scalar r computed in | |||
| GenerateProof(), a serialized scalar of Ns bytes long. Only | GenerateProof(), a serialized Scalar of Ns bytes long. Only | |||
| present for VOPRF and POPRF test vectors. | present for VOPRF and POPRF test vectors. | |||
| "Output": The protocol output, an opaque byte string of Nh bytes | "Output": The protocol output, an opaque byte string of Nh bytes | |||
| long. | long. | |||
| Test vectors with batch size B > 1 have inputs separated by a comma | Test vectors with batch size B > 1 have inputs separated by a comma | |||
| ",". Applicable test vectors will have B different values for the | ",". Applicable test vectors will have B different values for the | |||
| "Input", "Blind", "BlindedElement", "EvaluationElement", and "Output" | "Input", "Blind", "BlindedElement", "EvaluationElement", and "Output" | |||
| fields. | fields. | |||
| The server key material, pkSm and skSm, are listed under the mode for | The server key material, pkSm and skSm, are listed under the mode for | |||
| each ciphersuite. Both pkSm and skSm are the serialized values of | each ciphersuite. Both pkSm and skSm are the serialized values of | |||
| pkS and skS, respectively, as used in the protocol. Each key pair is | pkS and skS, respectively, as used in the protocol. Each key pair is | |||
| derived from a seed Seed and info string KeyInfo, which are listed as | derived from a seed, denoted Seed, and info string, denoted KeyInfo, | |||
| well, using the DeriveKeyPair function from Section 3.2. | which are listed as well, using the DeriveKeyPair function from | |||
| Section 3.2. | ||||
| A.1. ristretto255-SHA512 | A.1. ristretto255-SHA512 | |||
| A.1.1. OPRF Mode | A.1.1. OPRF Mode | |||
| Seed = a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a | Seed = a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a3a | |||
| 3a3 | 3a3 | |||
| KeyInfo = 74657374206b6579 | KeyInfo = 74657374206b6579 | |||
| skSm = 5ebcea5ee37023ccb9fc2d2019f9d7737be85591ae8652ffa9ef0f4d37063 | skSm = 5ebcea5ee37023ccb9fc2d2019f9d7737be85591ae8652ffa9ef0f4d37063 | |||
| b0e | b0e | |||
| End of changes. 71 change blocks. | ||||
| 224 lines changed or deleted | 195 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. | ||||