Check presentation before verifying the signature

This commit is contained in:
Ravi Khadiwala
2024-04-02 14:39:51 -05:00
committed by ravi-signal
parent 268c8382ee
commit 1ebc17352f
3 changed files with 80 additions and 28 deletions

View File

@@ -37,9 +37,16 @@ public class BackupAuthTestUtil {
public BackupAuthCredentialPresentation getPresentation(
final BackupTier backupTier, final byte[] backupKey, final UUID aci)
throws VerificationFailedException {
return getPresentation(params, backupTier, backupKey, aci);
}
public BackupAuthCredentialPresentation getPresentation(
GenericServerSecretParams params, final BackupTier backupTier, final byte[] backupKey, final UUID aci)
throws VerificationFailedException {
final BackupAuthCredentialRequestContext ctx = BackupAuthCredentialRequestContext.create(backupKey, aci);
return ctx.receiveResponse(
ctx.getRequest().issueCredential(clock.instant().truncatedTo(ChronoUnit.DAYS), backupTier.getReceiptLevel(), params),
ctx.getRequest()
.issueCredential(clock.instant().truncatedTo(ChronoUnit.DAYS), backupTier.getReceiptLevel(), params),
params.getPublicParams(),
backupTier.getReceiptLevel())
.present(params.getPublicParams());

View File

@@ -57,6 +57,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import org.signal.libsignal.protocol.InvalidKeyException;
import org.signal.libsignal.protocol.ecc.Curve;
import org.signal.libsignal.protocol.ecc.ECKeyPair;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.backups.BackupAuthCredentialPresentation;
import org.whispersystems.textsecuregcm.auth.AuthenticatedBackupUser;
@@ -170,6 +171,48 @@ public class BackupManagerTest {
backupUser);
}
@Test
public void invalidPresentationNoPublicKey() throws VerificationFailedException {
final BackupAuthCredentialPresentation invalidPresentation = backupAuthTestUtil.getPresentation(
GenericServerSecretParams.generate(),
BackupTier.MESSAGES, backupKey, aci);
final ECKeyPair keyPair = Curve.generateKeyPair();
// haven't set a public key yet, but should fail before hitting the database anyway
assertThatExceptionOfType(StatusRuntimeException.class)
.isThrownBy(() -> backupManager.authenticateBackupUser(
invalidPresentation,
keyPair.getPrivateKey().calculateSignature(invalidPresentation.serialize())))
.extracting(StatusRuntimeException::getStatus)
.extracting(Status::getCode)
.isEqualTo(Status.UNAUTHENTICATED.getCode());
}
@Test
public void invalidPresentationCorrectSignature() throws VerificationFailedException {
final BackupAuthCredentialPresentation presentation = backupAuthTestUtil.getPresentation(
BackupTier.MESSAGES, backupKey, aci);
final BackupAuthCredentialPresentation invalidPresentation = backupAuthTestUtil.getPresentation(
GenericServerSecretParams.generate(),
BackupTier.MESSAGES, backupKey, aci);
final ECKeyPair keyPair = Curve.generateKeyPair();
backupManager.setPublicKey(
presentation,
keyPair.getPrivateKey().calculateSignature(presentation.serialize()),
keyPair.getPublicKey()).join();
assertThatExceptionOfType(StatusRuntimeException.class)
.isThrownBy(() -> backupManager.authenticateBackupUser(
invalidPresentation,
keyPair.getPrivateKey().calculateSignature(invalidPresentation.serialize())))
.extracting(StatusRuntimeException::getStatus)
.extracting(Status::getCode)
.isEqualTo(Status.UNAUTHENTICATED.getCode());
}
@Test
public void unknownPublicKey() throws VerificationFailedException {
final BackupAuthCredentialPresentation presentation = backupAuthTestUtil.getPresentation(