zkgroup: Add CallLinkAuthCredential

This is very similar to the AuthCredential used by the group server,
but using CallLinkParams to encrypt the user ID rather than
GroupParams (and using GenericServerParams to issue the credential
rather than the group server's ServerParams).
This commit is contained in:
Jordan Rose
2023-04-25 17:18:05 -07:00
committed by GitHub
parent 1b5449e777
commit e588fa5450
24 changed files with 1004 additions and 4 deletions

View File

@@ -115,9 +115,21 @@ public final class Native {
public static native void AuthCredential_CheckValidContents(byte[] buffer);
public static native void CallLinkAuthCredentialPresentation_CheckValidContents(byte[] presentationBytes);
public static native byte[] CallLinkAuthCredentialPresentation_GetUserId(byte[] presentationBytes);
public static native void CallLinkAuthCredentialPresentation_Verify(byte[] presentationBytes, long now, byte[] serverParamsBytes, byte[] callLinkParamsBytes);
public static native void CallLinkAuthCredentialResponse_CheckValidContents(byte[] responseBytes);
public static native byte[] CallLinkAuthCredentialResponse_IssueDeterministic(UUID userId, long redemptionTime, byte[] paramsBytes, byte[] randomness);
public static native byte[] CallLinkAuthCredentialResponse_Receive(byte[] responseBytes, UUID userId, long redemptionTime, byte[] paramsBytes);
public static native void CallLinkAuthCredential_CheckValidContents(byte[] credentialBytes);
public static native byte[] CallLinkAuthCredential_PresentDeterministic(byte[] credentialBytes, UUID userId, long redemptionTime, byte[] serverParamsBytes, byte[] callLinkParamsBytes, byte[] randomness);
public static native void CallLinkPublicParams_CheckValidContents(byte[] paramsBytes);
public static native void CallLinkSecretParams_CheckValidContents(byte[] paramsBytes);
public static native UUID CallLinkSecretParams_DecryptUserId(byte[] paramsBytes, byte[] userId);
public static native byte[] CallLinkSecretParams_DeriveFromRootKey(byte[] rootKey);
public static native byte[] CallLinkSecretParams_GetPublicParams(byte[] paramsBytes);

View File

@@ -0,0 +1,43 @@
//
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
package org.signal.libsignal.zkgroup.calllinks;
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.UUID;
import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class CallLinkAuthCredential extends ByteArray {
public CallLinkAuthCredential(byte[] contents) throws InvalidInputException {
super(contents);
Native.CallLinkAuthCredential_CheckValidContents(contents);
}
public CallLinkAuthCredentialPresentation present(UUID userId, Instant redemptionTime, GenericServerPublicParams serverParams, CallLinkSecretParams callLinkParams) {
return present(userId, redemptionTime, serverParams, callLinkParams, new SecureRandom());
}
public CallLinkAuthCredentialPresentation present(UUID userId, Instant redemptionTime, GenericServerPublicParams serverParams, CallLinkSecretParams callLinkParams, SecureRandom secureRandom) {
byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
byte[] newContents = Native.CallLinkAuthCredential_PresentDeterministic(getInternalContentsForJNI(), userId, redemptionTime.getEpochSecond(), serverParams.getInternalContentsForJNI(), callLinkParams.getInternalContentsForJNI(), random);
try {
return new CallLinkAuthCredentialPresentation(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
}

View File

@@ -0,0 +1,42 @@
//
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
package org.signal.libsignal.zkgroup.calllinks;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
import java.time.Instant;
public final class CallLinkAuthCredentialPresentation extends ByteArray {
public CallLinkAuthCredentialPresentation(byte[] contents) throws InvalidInputException {
super(contents);
Native.CallLinkAuthCredentialPresentation_CheckValidContents(contents);
}
public void verify(GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams) throws VerificationFailedException {
verify(Instant.now(), serverParams, callLinkParams);
}
public void verify(Instant currentTime, GenericServerSecretParams serverParams, CallLinkPublicParams callLinkParams) throws VerificationFailedException {
Native.CallLinkAuthCredentialPresentation_Verify(getInternalContentsForJNI(), currentTime.getEpochSecond(), serverParams.getInternalContentsForJNI(), callLinkParams.getInternalContentsForJNI());
}
public UuidCiphertext getUserId() {
byte[] newContents = Native.CallLinkAuthCredentialPresentation_GetUserId(contents);
try {
return new UuidCiphertext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
}

View File

@@ -0,0 +1,53 @@
//
// Copyright 2023 Signal Messenger, LLC.
// SPDX-License-Identifier: AGPL-3.0-only
//
package org.signal.libsignal.zkgroup.calllinks;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.GenericServerPublicParams;
import org.signal.libsignal.zkgroup.GenericServerSecretParams;
import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.UUID;
import static org.signal.libsignal.zkgroup.internal.Constants.RANDOM_LENGTH;
public final class CallLinkAuthCredentialResponse extends ByteArray {
public CallLinkAuthCredentialResponse(byte[] contents) throws InvalidInputException {
super(contents);
Native.CallLinkAuthCredentialResponse_CheckValidContents(contents);
}
public static CallLinkAuthCredentialResponse issueCredential(UUID userId, Instant redemptionTime, GenericServerSecretParams params) {
return issueCredential(userId, redemptionTime, params, new SecureRandom());
}
public static CallLinkAuthCredentialResponse issueCredential(UUID userId, Instant redemptionTime, GenericServerSecretParams params, SecureRandom secureRandom) {
byte[] random = new byte[RANDOM_LENGTH];
secureRandom.nextBytes(random);
byte[] newContents = Native.CallLinkAuthCredentialResponse_IssueDeterministic(userId, redemptionTime.getEpochSecond(), params.getInternalContentsForJNI(), random);
try {
return new CallLinkAuthCredentialResponse(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public CallLinkAuthCredential receive(UUID userId, Instant redemptionTime, GenericServerPublicParams params) throws VerificationFailedException {
byte[] newContents = Native.CallLinkAuthCredentialResponse_Receive(getInternalContentsForJNI(), userId, redemptionTime.getEpochSecond(), params.getInternalContentsForJNI());
try {
return new CallLinkAuthCredential(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
}

View File

@@ -6,6 +6,7 @@
package org.signal.libsignal.zkgroup.calllinks;
import org.signal.libsignal.zkgroup.InvalidInputException;
import org.signal.libsignal.zkgroup.VerificationFailedException;
import org.signal.libsignal.zkgroup.groups.UuidCiphertext;
import org.signal.libsignal.zkgroup.internal.ByteArray;
import org.signal.libsignal.internal.Native;
@@ -39,4 +40,8 @@ public final class CallLinkSecretParams extends ByteArray {
}
}
public UUID decryptUserId(UuidCiphertext ciphertext) throws VerificationFailedException {
return Native.CallLinkSecretParams_DecryptUserId(getInternalContentsForJNI(), ciphertext.getInternalContentsForJNI());
}
}