Support searching for identifiers in the key transparency log by version

This commit is contained in:
Katherine
2025-10-29 16:22:55 -04:00
committed by GitHub
parent d7a9e3c9f3
commit 3116913378
5 changed files with 121 additions and 66 deletions

View File

@@ -76,8 +76,10 @@ public class KeyTransparencyController {
)
@ApiResponse(responseCode = "200", description = "The ACI was found and its mapped value matched the provided ACI identity key", useReturnTypeSchema = true)
@ApiResponse(responseCode = "400", description = "Invalid request. See response for any available details.")
@ApiResponse(responseCode = "403", description = "The ACI was found but its mapped value did not match the provided ACI identity key")
@ApiResponse(responseCode = "404", description = "The ACI was not found in the log")
@ApiResponse(responseCode = "403", description = """
The ACI was found but its mapped value did not match the provided ACI identity key
or the ACI was not found in the log.
""")
@ApiResponse(responseCode = "422", description = "Invalid request format")
@ApiResponse(responseCode = "429", description = "Rate-limited")
@POST
@@ -108,7 +110,10 @@ public class KeyTransparencyController {
request.usernameHash().map(ByteString::copyFrom),
maybeE164SearchRequest,
request.lastTreeHeadSize(),
request.distinguishedTreeHeadSize())
request.distinguishedTreeHeadSize(),
request.aciVersion(),
request.e164Version(),
request.usernameHashVersion())
.toByteArray());
} catch (final StatusRuntimeException exception) {
handleKeyTransparencyServiceError(exception);

View File

@@ -9,6 +9,8 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.AssertTrue;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import java.util.Optional;
@@ -51,8 +53,20 @@ public record KeyTransparencySearchRequest(
Optional<@Positive Long> lastTreeHeadSize,
@Schema(description = "The distinguished tree head size to prove consistency against.")
@Positive long distinguishedTreeHeadSize
@Positive long distinguishedTreeHeadSize,
@Schema(description = "The version of the ACI to look up.")
Optional<@Max(MAX_UINT32) @Min(0) Long> aciVersion,
@Schema(description = "The version of the E164 to look up.")
Optional<@Max(MAX_UINT32) @Min(0) Long> e164Version,
@Schema(description = "The version of the username hash to look up.")
Optional<@Max(MAX_UINT32) @Min(0) Long> usernameHashVersion
) {
// This is the max value for a protobuf uint32 field
private static final long MAX_UINT32 = 0xFFFFFFFFL;
@AssertTrue
@Schema(hidden = true)
public boolean isUnidentifiedAccessKeyProvidedWithE164() {

View File

@@ -116,7 +116,10 @@ public class KeyTransparencyServiceClient implements Managed {
final Optional<ByteString> usernameHash,
final Optional<E164SearchRequest> e164SearchRequest,
final Optional<Long> lastTreeHeadSize,
final long distinguishedTreeHeadSize) {
final long distinguishedTreeHeadSize,
final Optional<Long> aciVersion,
final Optional<Long> e164Version,
final Optional<Long> usernameHashVersion) {
final SearchRequest.Builder searchRequestBuilder = SearchRequest.newBuilder()
.setAci(aci)
.setAciIdentityKey(aciIdentityKey);
@@ -124,6 +127,10 @@ public class KeyTransparencyServiceClient implements Managed {
usernameHash.ifPresent(searchRequestBuilder::setUsernameHash);
e164SearchRequest.ifPresent(searchRequestBuilder::setE164SearchRequest);
aciVersion.ifPresent(version -> searchRequestBuilder.setAciVersion(version.intValue()));
e164Version.ifPresent(version -> searchRequestBuilder.setE164Version(version.intValue()));
usernameHashVersion.ifPresent(version -> searchRequestBuilder.setUsernameHashVersion(version.intValue()));
final ConsistencyParameters.Builder consistency = ConsistencyParameters.newBuilder()
.setDistinguished(distinguishedTreeHeadSize);
lastTreeHeadSize.ifPresent(consistency::setLast);