blob: 34a4f25b34b1e4167d60420c3da05d2bbb9e596c [file] [log] [blame]
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
option optimize_for = LITE_RUNTIME;
package private_membership.rlwe;
option go_package = "github.com/google/private-membership";
import "private_membership.proto";
import "serialization.proto";
// Request and Response protos
//
// The protocol consists of two roundtrips:
// First Round: OprfRequest and OprfResponse
// Second Round: QueryRequest and QueryResponse
// First request sent by the client for checking membership.
message PrivateMembershipRlweOprfRequest {
// The identifier encrypted using the elliptic curve commutative
// cipher under an ephemeral key generated by the client. Before encryption,
// the identifier is hashed using either SHA256 or a more computationally
// expensive hash such as Argon2.
repeated bytes encrypted_ids = 1;
// The name of the use case of this query.
RlweUseCase use_case = 2;
}
// First response sent by the server for checking membership.
message PrivateMembershipRlweOprfResponse {
// The requested encrypted_id entries that are re-encrypted using the elliptic
// curve commutative cipher using the server’s key.
//
// The client will decrypt to simply get the identifier encrypted under the
// server’s key. The client will use this to match with the associated
// EncryptedBucket to see if there is a match or not. Additionally, the client
// will use it to decrypt the AES encrypted value.
repeated DoublyEncryptedId doubly_encrypted_ids = 1;
// Unset if the server doesn't support non-sensitive identifier bucketing for
// the requested use case.
HashedBucketsParameters hashed_buckets_parameters = 2;
// Parameters for the encrypted buckets (second level).
EncryptedBucketsParameters encrypted_buckets_parameters = 3;
// Parameters describing the Ring LWE group as well as the security parameter.
RlweParameters rlwe_parameters = 4;
// Version of key that encrypted the identifier-value pair.
//
// The client should provide this value in the second round of the protocol
// to ensure consistency.
int64 key_version = 5;
}
// Second request sent by the client for checking membership.
message PrivateMembershipRlweQueryRequest {
// Upload a retrieval request consisting of RLWE ciphertexts.
repeated PrivateMembershipRlweQuery queries = 1;
// The name of the use case of this query.
RlweUseCase use_case = 2;
// Version of key that encrypted the identifier-value pair.
int64 key_version = 3;
}
// Second response sent by the server for checking membership.
message PrivateMembershipRlweQueryResponse {
repeated PrivateMembershipRlwePirResponse pir_responses = 1;
}
// Proto containing plaintext IDs supplied to the client library.
message RlwePlaintextId {
// Non-sensitive portion of the identifier.
string non_sensitive_id = 1;
// Sensitive portion of the identifier.
string sensitive_id = 2;
}
// Different use cases of the RLWE-based PSM protocol.
//
// NEXT ID: 18
enum RlweUseCase {
RLWE_USE_CASE_UNDEFINED = 0;
TEST_USE_CASE = 1;
TEST_USE_CASE2 = 2;
TEST_USE_CASE3 = 3;
// The device state of Chrome OS device, used for Zero Touch, License
// Packaging.
CROS_DEVICE_STATE = 5;
// The device state of Chrome OS device, used for Forced Re-enrollment.
CROS_DEVICE_SECONDARY_STATE = 12;
// Use-cases for ChromeOS Device Active Reporting to Fresnel.
CROS_FRESNEL_DAILY = 13;
CROS_FRESNEL_MONTHLY = 14;
CROS_FRESNEL_FIRST_ACTIVE = 15;
CROS_FRESNEL_7DAY_ACTIVE = 16;
CROS_FRESNEL_28DAY_ACTIVE = 17;
reserved 4, 6, 7, 8, 9, 10, 11;
}
// Parameters for the hashed buckets (first level).
//
// Hashed bucket id is derived by taking the prefix of the hash of the non-
// sensitive identifier.
message HashedBucketsParameters {
// The bit length of the hashed bucket id.
int32 hashed_bucket_id_length = 1;
// The type of hash function to be used for the non-sensitive identifier
// part.
private_membership.HashType non_sensitive_id_hash_type = 2;
}
// Parameters for the encrypted buckets (second level).
message EncryptedBucketsParameters {
// The bit length of the encrypted bucket ids.
//
// The total number of encrypted buckets can be derived from this field,
// i.e. 2^encrypted_bucket_id_length.
int32 encrypted_bucket_id_length = 1;
// The type of hash function to be used to generate the encrypted bucket ID.
private_membership.EncryptedBucketHashType sensitive_id_hash_type = 2;
}
// Public Ring-LWE encryption scheme parameters.
message RlweParameters {
// Sequence of one modulus or two decreasing moduli.
repeated Uint128 modulus = 1;
// Log (base 2) of the polynomial degree N (dimension of the vectorspace).
int32 log_degree = 2;
// Plaintext modulus in bits log t.
int32 log_t = 3;
// Variance of Gaussian error in bits.
int32 variance = 4;
// Levels of recursion.
int32 levels_of_recursion = 5;
}
// Represents a unsigned 128-bit integer.
message Uint128 {
// The lower 64 bits of the modulus.
uint64 lo = 1;
// The higher 64 bits of the modulus.
uint64 hi = 2;
}
// Single unit of RLWE query.
message PrivateMembershipRlweQuery {
// Corresponds to the doubly_encrypted_id.queried_encrypted_id in the
// PrivateMembershipRlweOprfResponse.
//
// Should be set by the client.
bytes queried_encrypted_id = 1;
// Upload a retrieval request consisting of RLWE ciphertexts.
PirRequest pir_request = 2;
// Hashed bucket id at bit level granularity.
message HashedBucketId {
// Hashed bucket id, in bytes.
//
// All bits after bit_length's bit should be set to 0.
bytes hashed_bucket_id = 1;
// Bit length of the hashed bucket id.
//
// This value should be in
// ((hashed_bucket_id.size() - 1) * 8, hashed_bucket_id.size() * 8] range.
int32 bit_length = 2;
}
// Hashed bucket id.
//
// The hashed bucket id is computed by taking the prefix of the hashed
// non-sensitive id at the bit level.
// e.g. if the hashed non-sensitive id is 11010111 and the bucket id length is
// 6, this will be populated as 11010100.
//
// Should be unset if the server doesn't support non-sensitive identifier
// bucketing for the requested use case.
HashedBucketId hashed_bucket_id = 3;
}
// Response consisting of a unique query id and the associated PIR response.
message PrivateMembershipRlwePirResponse {
// This corresponds to the queried_encrypted_id set by the client in the query
// request.
bytes queried_encrypted_id = 1;
// PIR response corresponding to the PIR request.
PirResponse pir_response = 2;
}
// Request for private bucket retrieval.
message PirRequest {
// The request is an encoding of a flattened table of encrypted {1} and {0}
// messages as necessary for PIR. If the database has D items and we are using
// L levels of recursion, this table will contain L*(D^(1/L)) messages,
// representing a table with L rows and D^(1/L) items per row. Each row should
// contain exactly one {1} ciphertext, with the rest of the items containing
// {0} messages.
//
// The flattened table is laid out in the following order:
//
// level | ciphertexts
// -----------------------------
// 1 | {0} ... {1} ... {0}
// 2 | {0} ... {1} ... {0}
// ... | ...
//
// The ciphertexts are uploaded in a compressed format as NTT Polynomials
// using a PRNG seed to expand them into ciphertexts.
repeated .rlwe.SerializedNttPolynomial request = 1;
// The PRNG seed used to expand the compressed RLWE ciphertexts.
bytes prng_seed = 2;
}
// Response for private bucket retrieval.
message PirResponse {
// Sequence of ciphertexts consisting of encrypted buckets.
repeated .rlwe.SerializedSymmetricRlweCiphertext response = 1;
// Size of the plaintext entry in bytes.
int32 plaintext_entry_size = 2;
}
// Bucket consisting of encrypted id and values.
message EncryptedBucket {
// All encrypted pairs in the bucket.
repeated EncryptedIdValuePair encrypted_id_value_pairs = 1;
// Proto storing encrypted id-value pairs.
message EncryptedIdValuePair {
// Identifier that is encrypted using the Elliptic curve commutative cipher.
// Furthermore, the serialization of the encryption is hashed and only a
// prefix is used.
bytes encrypted_id = 1;
// Value that is encrypted using AES where the key is a serialization
// of the identifier encrypted using the Elliptic curve commutative cipher.
bytes encrypted_value = 2;
// Proto containing the sensitive and non-sensitive portion of the
// identifier in plaintext.
RlwePlaintextId id = 3;
}
}
// A collection of plaintext ids and associated membership responses.
message RlweMembershipResponses {
// A pair of queried plaintext id and its associated membership response.
message MembershipResponseEntry {
// Plaintext id that was queried.
RlwePlaintextId plaintext_id = 1;
// Membership response of the queried plaintext id.
MembershipResponse membership_response = 2;
}
repeated MembershipResponseEntry membership_responses = 1;
}