In order to ensure that the FLE system works transparently for equality predicates against encrypted fields, we must implement the following constraints:
- Any field encrypted with the deterministic algorithm must specify exactly one BSON type. This was implemented under
SERVER-40627. - Queries can only contain equality predicates against encrypted an encrypted field if the field is encrypted with the deterministic algorithm. This was implemented under
SERVER-40378. - The BSON type of the constant for an equality predicate must match the BSON type specified in the JSON Schema. Implementing this final constraint is the work tracked by this ticket.
Taken together, these restrictions prevent a situation where users can issue a query against an encrypted field such as {ssn: {$eq: NumberInt(12345678)}} and expect matches where ssn can be any of the types {int, long, double, decimal}. One cannot build an application using FLE which queries mixed-type encrypted fields. Instead, when using deterministic encryption to ensure queryability, users must define a schema which names exactly one type for the encrypted field. Furthermore, they must write the query so that any constant in an equality predicate against the encrypted field has matching type. For instance, if a user creates a schema specifying that ssn is deterministically encrypted int, they may not run an equality query such as {ssn: {$eq: NumberLong(12345678)}}, since "long" is not the type specified in the schema.
Original description
BSONElement equality semantics involve a logical comparison function rather than byte-wise equality. Therefore, two equal BSONElements may result in unequal ciphertext after encryption, even with the "Deterministic" encryption algorithm. If we want FLE equality to work transparently, the client should encrypt a KeyString encoding. Decryption would similarly be a two-step process in which we decrypt and then decode the KeyString.
The simplest example of this is integers of different types. The integer 42 can be BSON-encoded as either a NumberDouble, NumberInt, or NumberLong. The actual bytes inside the BSONElement are different for all three cases, yet all three are considered equal.