0
0
mirror of https://github.com/signalapp/libsignal.git synced 2024-09-20 03:52:17 +02:00

java: Add the zkgroup sources verbatim (does not compile)

This commit is contained in:
Jordan Rose 2021-10-28 17:56:53 -07:00
parent 852069bdc9
commit c2261d1701
45 changed files with 2800 additions and 0 deletions

View File

@ -0,0 +1,20 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup;
public class InvalidInputException extends Exception {
public InvalidInputException() {
}
public InvalidInputException(String message) {
super(message);
}
}

View File

@ -0,0 +1,4 @@
package org.signal.zkgroup;
public class InvalidRedemptionTimeException extends Exception {
}

View File

@ -0,0 +1,26 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup;
import org.signal.zkgroup.internal.ByteArray;
public final class NotarySignature extends ByteArray {
public static final int SIZE = 64;
public NotarySignature(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,48 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ServerPublicParams extends ByteArray {
public static final int SIZE = 225;
public ServerPublicParams(byte[] contents) {
super(contents, SIZE, true);
int ffi_return = Native.serverPublicParamsCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new IllegalArgumentException(new InvalidInputException("FFI_RETURN_INPUT_ERROR"));
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public void verifySignature(byte[] message, NotarySignature notarySignature) throws VerificationFailedException {
int ffi_return = Native.serverPublicParamsVerifySignatureJNI(contents, message, notarySignature.getInternalContentsForJNI());
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,98 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup;
import java.security.SecureRandom;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ServerSecretParams extends ByteArray {
public static final int SIZE = 1121;
public static ServerSecretParams generate() {
return generate(new SecureRandom());
}
public static ServerSecretParams generate(SecureRandom secureRandom) {
byte[] newContents = new byte[ServerSecretParams.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverSecretParamsGenerateDeterministicJNI(random, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ServerSecretParams(newContents);
} catch (IllegalArgumentException e) {
throw new AssertionError(e);
}
}
public ServerSecretParams(byte[] contents) {
super(contents, SIZE, true);
int ffi_return = Native.serverSecretParamsCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new IllegalArgumentException(new InvalidInputException("FFI_RETURN_INPUT_ERROR"));
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public ServerPublicParams getPublicParams() {
byte[] newContents = new byte[ServerPublicParams.SIZE];
int ffi_return = Native.serverSecretParamsGetPublicParamsJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return new ServerPublicParams(newContents);
}
public NotarySignature sign(byte[] message) {
return sign(new SecureRandom(), message);
}
public NotarySignature sign(SecureRandom secureRandom, byte[] message) {
byte[] newContents = new byte[NotarySignature.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverSecretParamsSignDeterministicJNI(contents, random, message, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new NotarySignature(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,11 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup;
public class VerificationFailedException extends Exception {
}

View File

@ -0,0 +1,15 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup;
public final class ZkGroupError extends Error {
public ZkGroupError(String message) {
super(message);
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.auth;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class AuthCredential extends ByteArray {
public static final int SIZE = 181;
public AuthCredential(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.authCredentialCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,70 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.auth;
import java.nio.ByteBuffer;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.groups.UuidCiphertext;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class AuthCredentialPresentation extends ByteArray {
public static final int SIZE = 493;
public AuthCredentialPresentation(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.authCredentialPresentationCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public UuidCiphertext getUuidCiphertext() {
byte[] newContents = new byte[UuidCiphertext.SIZE];
int ffi_return = Native.authCredentialPresentationGetUuidCiphertextJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new UuidCiphertext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public int getRedemptionTime() {
byte[] newContents = new byte[4];
int ffi_return = Native.authCredentialPresentationGetRedemptionTimeJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return ByteBuffer.wrap(newContents).getInt();
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.auth;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class AuthCredentialResponse extends ByteArray {
public static final int SIZE = 361;
public AuthCredentialResponse(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.authCredentialResponseCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,74 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.auth;
import java.security.SecureRandom;
import java.util.UUID;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ServerPublicParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.groups.GroupSecretParams;
import org.signal.zkgroup.internal.Native;
import org.signal.zkgroup.util.UUIDUtil;
public class ClientZkAuthOperations {
private final ServerPublicParams serverPublicParams;
public ClientZkAuthOperations(ServerPublicParams serverPublicParams) {
this.serverPublicParams = serverPublicParams;
}
public AuthCredential receiveAuthCredential(UUID uuid, int redemptionTime, AuthCredentialResponse authCredentialResponse) throws VerificationFailedException {
byte[] newContents = new byte[AuthCredential.SIZE];
int ffi_return = Native.serverPublicParamsReceiveAuthCredentialJNI(serverPublicParams.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), redemptionTime, authCredentialResponse.getInternalContentsForJNI(), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new AuthCredential(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public AuthCredentialPresentation createAuthCredentialPresentation(GroupSecretParams groupSecretParams, AuthCredential authCredential) {
return createAuthCredentialPresentation(new SecureRandom(), groupSecretParams, authCredential);
}
public AuthCredentialPresentation createAuthCredentialPresentation(SecureRandom secureRandom, GroupSecretParams groupSecretParams, AuthCredential authCredential) {
byte[] newContents = new byte[AuthCredentialPresentation.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverPublicParamsCreateAuthCredentialPresentationDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, groupSecretParams.getInternalContentsForJNI(), authCredential.getInternalContentsForJNI(), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new AuthCredentialPresentation(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
}

View File

@ -0,0 +1,78 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.auth;
import java.security.SecureRandom;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ServerSecretParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.InvalidRedemptionTimeException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.groups.GroupPublicParams;
import org.signal.zkgroup.internal.Native;
import org.signal.zkgroup.util.UUIDUtil;
public class ServerZkAuthOperations {
private final ServerSecretParams serverSecretParams;
public ServerZkAuthOperations(ServerSecretParams serverSecretParams) {
this.serverSecretParams = serverSecretParams;
}
public AuthCredentialResponse issueAuthCredential(UUID uuid, int redemptionTime) {
return issueAuthCredential(new SecureRandom(), uuid, redemptionTime);
}
public AuthCredentialResponse issueAuthCredential(SecureRandom secureRandom, UUID uuid, int redemptionTime) {
byte[] newContents = new byte[AuthCredentialResponse.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverSecretParamsIssueAuthCredentialDeterministicJNI(serverSecretParams.getInternalContentsForJNI(), random, UUIDUtil.serialize(uuid), redemptionTime, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new AuthCredentialResponse(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation) throws VerificationFailedException, InvalidRedemptionTimeException {
verifyAuthCredentialPresentation(groupPublicParams, authCredentialPresentation, System.currentTimeMillis());
}
public void verifyAuthCredentialPresentation(GroupPublicParams groupPublicParams, AuthCredentialPresentation authCredentialPresentation, long currentTimeMillis) throws VerificationFailedException, InvalidRedemptionTimeException {
long acceptableStartTime = TimeUnit.MILLISECONDS.convert(authCredentialPresentation.getRedemptionTime()-1, TimeUnit.DAYS);
long acceptableEndTime = TimeUnit.MILLISECONDS.convert(authCredentialPresentation.getRedemptionTime()+2, TimeUnit.DAYS);
if (currentTimeMillis < acceptableStartTime || currentTimeMillis > acceptableEndTime) {
throw new InvalidRedemptionTimeException();
}
int ffi_return = Native.serverSecretParamsVerifyAuthCredentialPresentationJNI(serverSecretParams.getInternalContentsForJNI(), groupPublicParams.getInternalContentsForJNI(), authCredentialPresentation.getInternalContentsForJNI());
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
}

View File

@ -0,0 +1,154 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.groups;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.UUID;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.Native;
import org.signal.zkgroup.profiles.ProfileKey;
import org.signal.zkgroup.util.UUIDUtil;
public class ClientZkGroupCipher {
private final GroupSecretParams groupSecretParams;
public ClientZkGroupCipher(GroupSecretParams groupSecretParams) {
this.groupSecretParams = groupSecretParams;
}
public UuidCiphertext encryptUuid(UUID uuid) {
byte[] newContents = new byte[UuidCiphertext.SIZE];
int ffi_return = Native.groupSecretParamsEncryptUuidJNI(groupSecretParams.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new UuidCiphertext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public UUID decryptUuid(UuidCiphertext uuidCiphertext) throws VerificationFailedException {
byte[] newContents = new byte[UUIDUtil.UUID_LENGTH];
int ffi_return = Native.groupSecretParamsDecryptUuidJNI(groupSecretParams.getInternalContentsForJNI(), uuidCiphertext.getInternalContentsForJNI(), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return UUIDUtil.deserialize(newContents);
}
public ProfileKeyCiphertext encryptProfileKey(ProfileKey profileKey, UUID uuid) {
byte[] newContents = new byte[ProfileKeyCiphertext.SIZE];
int ffi_return = Native.groupSecretParamsEncryptProfileKeyJNI(groupSecretParams.getInternalContentsForJNI(), profileKey.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCiphertext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public ProfileKey decryptProfileKey(ProfileKeyCiphertext profileKeyCiphertext, UUID uuid) throws VerificationFailedException {
byte[] newContents = new byte[ProfileKey.SIZE];
int ffi_return = Native.groupSecretParamsDecryptProfileKeyJNI(groupSecretParams.getInternalContentsForJNI(), profileKeyCiphertext.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKey(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] encryptBlob(byte[] plaintext) throws VerificationFailedException {
return encryptBlob(new SecureRandom(), plaintext);
}
public byte[] encryptBlob(SecureRandom secureRandom, byte[] plaintext) throws VerificationFailedException {
byte[] paddedPlaintext = new byte[plaintext.length + 4];
System.arraycopy(plaintext, 0, paddedPlaintext, 4, plaintext.length);
byte[] newContents = new byte[paddedPlaintext.length + 29];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.groupSecretParamsEncryptBlobDeterministicJNI(groupSecretParams.getInternalContentsForJNI(), random, paddedPlaintext, newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return newContents;
}
public byte[] decryptBlob(byte[] blobCiphertext) throws VerificationFailedException {
byte[] newContents = new byte[blobCiphertext.length + -29];
int ffi_return = Native.groupSecretParamsDecryptBlobJNI(groupSecretParams.getInternalContentsForJNI(), blobCiphertext, newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
if (newContents.length < 4) {
throw new VerificationFailedException();
}
byte[] padLenBytes = new byte[4];
System.arraycopy(newContents, 0, padLenBytes, 0, 4);
int padLen = ByteBuffer.wrap(newContents).getInt();
if (newContents.length < (4 + padLen)) {
throw new VerificationFailedException();
}
byte[] depaddedContents = new byte[newContents.length - (4 + padLen)];
System.arraycopy(newContents, 4, depaddedContents, 0, newContents.length - (4 + padLen));
return depaddedContents;
}
}

View File

@ -0,0 +1,27 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.groups;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.internal.ByteArray;
public final class GroupIdentifier extends ByteArray {
public static final int SIZE = 32;
public GroupIdentifier(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,27 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.groups;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.internal.ByteArray;
public final class GroupMasterKey extends ByteArray {
public static final int SIZE = 32;
public GroupMasterKey(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,56 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.groups;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class GroupPublicParams extends ByteArray {
public static final int SIZE = 97;
public GroupPublicParams(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.groupPublicParamsCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public GroupIdentifier getGroupIdentifier() {
byte[] newContents = new byte[GroupIdentifier.SIZE];
int ffi_return = Native.groupPublicParamsGetGroupIdentifierJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new GroupIdentifier(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,113 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.groups;
import java.security.SecureRandom;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class GroupSecretParams extends ByteArray {
public static final int SIZE = 289;
public static GroupSecretParams generate() {
return generate(new SecureRandom());
}
public static GroupSecretParams generate(SecureRandom secureRandom) {
byte[] newContents = new byte[GroupSecretParams.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.groupSecretParamsGenerateDeterministicJNI(random, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new GroupSecretParams(newContents);
} catch (IllegalArgumentException e) {
throw new AssertionError(e);
}
}
public static GroupSecretParams deriveFromMasterKey(GroupMasterKey groupMasterKey) {
byte[] newContents = new byte[GroupSecretParams.SIZE];
int ffi_return = Native.groupSecretParamsDeriveFromMasterKeyJNI(groupMasterKey.getInternalContentsForJNI(), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new GroupSecretParams(newContents);
} catch (IllegalArgumentException e) {
throw new AssertionError(e);
}
}
public GroupSecretParams(byte[] contents) {
super(contents, SIZE, true);
int ffi_return = Native.groupSecretParamsCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new IllegalArgumentException(new InvalidInputException("FFI_RETURN_INPUT_ERROR"));
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public GroupMasterKey getMasterKey() {
byte[] newContents = new byte[GroupMasterKey.SIZE];
int ffi_return = Native.groupSecretParamsGetMasterKeyJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new GroupMasterKey(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public GroupPublicParams getPublicParams() {
byte[] newContents = new byte[GroupPublicParams.SIZE];
int ffi_return = Native.groupSecretParamsGetPublicParamsJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new GroupPublicParams(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.groups;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ProfileKeyCiphertext extends ByteArray {
public static final int SIZE = 65;
public ProfileKeyCiphertext(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.profileKeyCiphertextCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.groups;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class UuidCiphertext extends ByteArray {
public static final int SIZE = 65;
public UuidCiphertext(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.uuidCiphertextCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,63 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup.internal;
import org.signal.zkgroup.InvalidInputException;
import java.util.Arrays;
import java.util.Locale;
public abstract class ByteArray {
protected final byte[] contents;
protected ByteArray(byte[] contents, int expectedLength) throws InvalidInputException {
this.contents = cloneArrayOfLength(contents, expectedLength);
}
protected ByteArray(byte[] contents, int expectedLength, boolean unrecoverable) {
try {
this.contents = cloneArrayOfLength(contents, expectedLength);
} catch (InvalidInputException e) {
throw new IllegalArgumentException(e);
}
}
private static byte[] cloneArrayOfLength(byte[] bytes, int expectedLength) throws InvalidInputException {
if (bytes.length != expectedLength) {
throw new InvalidInputException(String.format(Locale.US, "Length of array supplied was %d expected %d", bytes.length, expectedLength));
}
return bytes.clone();
}
public byte[] getInternalContentsForJNI() {
return contents;
}
@Override
public int hashCode() {
return getClass().hashCode() * 31 + Arrays.hashCode(contents);
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
ByteArray other = (ByteArray) o;
if (contents == other.contents) return true;
if (contents.length != other.contents.length) return false;
int result = 0;
for (int i = 0; i < contents.length; i++) {
result |= contents[i] ^ other.contents[i];
}
return result == 0;
}
}

View File

@ -0,0 +1,130 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.internal;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
public final class Native {
public static final int FFI_RETURN_OK = 0;
public static final int FFI_RETURN_INTERNAL_ERROR = 1; // ZkGroupError
public static final int FFI_RETURN_INPUT_ERROR = 2;
public static final int RANDOM_LENGTH = 32;
static {
try {
String osName = System.getProperty("os.name").toLowerCase(java.util.Locale.ROOT);
boolean isMacOs = osName.startsWith("mac os x");
String extension = isMacOs ? ".dylib" : ".so";
try (InputStream in = Native.class.getResourceAsStream("/libzkgroup" + extension)) {
if (in != null) {
copyToTempFileAndLoad(in, extension);
} else {
System.loadLibrary("zkgroup");
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Native() {
}
private static void copyToTempFileAndLoad(InputStream in, String extension) throws IOException {
File tempFile = Files.createTempFile("resource", extension).toFile();
tempFile.deleteOnExit();
try (OutputStream out = new FileOutputStream(tempFile)) {
copy(in, out);
}
System.load(tempFile.getAbsolutePath());
}
public static native int profileKeyGetCommitmentJNI(byte[] self, byte[] uuid, byte[] output);
public static native int profileKeyGetProfileKeyVersionJNI(byte[] self, byte[] uuid, byte[] output);
public static native int profileKeyCommitmentCheckValidContentsJNI(byte[] self);
public static native int groupSecretParamsGenerateDeterministicJNI(byte[] randomness, byte[] output);
public static native int groupSecretParamsDeriveFromMasterKeyJNI(byte[] groupMasterKey, byte[] output);
public static native int groupSecretParamsGetMasterKeyJNI(byte[] self, byte[] output);
public static native int groupSecretParamsGetPublicParamsJNI(byte[] self, byte[] output);
public static native int groupSecretParamsCheckValidContentsJNI(byte[] self);
public static native int groupSecretParamsEncryptUuidJNI(byte[] self, byte[] uuid, byte[] output);
public static native int groupSecretParamsDecryptUuidJNI(byte[] self, byte[] uuidCiphertext, byte[] output);
public static native int groupSecretParamsEncryptProfileKeyJNI(byte[] self, byte[] profileKey, byte[] uuid, byte[] output);
public static native int groupSecretParamsDecryptProfileKeyJNI(byte[] self, byte[] profileKeyCiphertext, byte[] uuid, byte[] output);
public static native int groupSecretParamsEncryptBlobDeterministicJNI(byte[] self, byte[] randomness, byte[] plaintext, byte[] output);
public static native int groupSecretParamsDecryptBlobJNI(byte[] self, byte[] blobCiphertext, byte[] output);
public static native int serverSecretParamsGenerateDeterministicJNI(byte[] randomness, byte[] output);
public static native int serverSecretParamsGetPublicParamsJNI(byte[] self, byte[] output);
public static native int serverSecretParamsSignDeterministicJNI(byte[] self, byte[] randomness, byte[] message, byte[] output);
public static native int serverSecretParamsCheckValidContentsJNI(byte[] self);
public static native int serverPublicParamsReceiveAuthCredentialJNI(byte[] self, byte[] uuid, int redemptionTime, byte[] authCredentialResponse, byte[] output);
public static native int serverPublicParamsCreateAuthCredentialPresentationDeterministicJNI(byte[] self, byte[] randomness, byte[] groupSecretParams, byte[] authCredential, byte[] output);
public static native int serverPublicParamsCreateProfileKeyCredentialRequestContextDeterministicJNI(byte[] self, byte[] randomness, byte[] uuid, byte[] profileKey, byte[] output);
public static native int serverPublicParamsReceiveProfileKeyCredentialJNI(byte[] self, byte[] profileKeyCredentialRequestContext, byte[] profileKeyCredentialResponse, byte[] output);
public static native int serverPublicParamsCreateProfileKeyCredentialPresentationDeterministicJNI(byte[] self, byte[] randomness, byte[] groupSecretParams, byte[] profileKeyCredential, byte[] output);
public static native int serverPublicParamsCreateReceiptCredentialRequestContextDeterministicJNI(byte[] self, byte[] randomness, byte[] receiptSerial, byte[] output);
public static native int serverPublicParamsReceiveReceiptCredentialJNI(byte[] self, byte[] receiptCredentialRequestContext, byte[] receiptCredentialResponse, byte[] output);
public static native int serverPublicParamsCreateReceiptCredentialPresentationDeterministicJNI(byte[] self, byte[] randomness, byte[] receiptCredential, byte[] output);
public static native int serverSecretParamsIssueAuthCredentialDeterministicJNI(byte[] self, byte[] randomness, byte[] uuid, int redemptionTime, byte[] output);
public static native int serverSecretParamsVerifyAuthCredentialPresentationJNI(byte[] self, byte[] groupPublicParams, byte[] authCredentialPresentation);
public static native int serverSecretParamsIssueProfileKeyCredentialDeterministicJNI(byte[] self, byte[] randomness, byte[] profileKeyCredentialRequest, byte[] uuid, byte[] profileKeyCommitment, byte[] output);
public static native int serverSecretParamsVerifyProfileKeyCredentialPresentationJNI(byte[] self, byte[] groupPublicParams, byte[] profileKeyCredentialPresentation);
public static native int serverSecretParamsIssueReceiptCredentialDeterministicJNI(byte[] self, byte[] randomness, byte[] receiptCredentialRequest, long receiptExpirationTime, long receiptLevel, byte[] output);
public static native int serverSecretParamsVerifyReceiptCredentialPresentationJNI(byte[] self, byte[] receiptCredentialPresentation);
public static native int groupPublicParamsGetGroupIdentifierJNI(byte[] self, byte[] output);
public static native int groupPublicParamsCheckValidContentsJNI(byte[] self);
public static native int serverPublicParamsVerifySignatureJNI(byte[] self, byte[] message, byte[] notarySignature);
public static native int serverPublicParamsCheckValidContentsJNI(byte[] self);
public static native int authCredentialResponseCheckValidContentsJNI(byte[] self);
public static native int authCredentialCheckValidContentsJNI(byte[] self);
public static native int authCredentialPresentationGetUuidCiphertextJNI(byte[] self, byte[] output);
public static native int authCredentialPresentationGetRedemptionTimeJNI(byte[] self, byte[] output);
public static native int authCredentialPresentationCheckValidContentsJNI(byte[] self);
public static native int profileKeyCredentialRequestContextGetRequestJNI(byte[] self, byte[] output);
public static native int profileKeyCredentialRequestContextCheckValidContentsJNI(byte[] self);
public static native int profileKeyCredentialRequestCheckValidContentsJNI(byte[] self);
public static native int profileKeyCredentialResponseCheckValidContentsJNI(byte[] self);
public static native int profileKeyCredentialCheckValidContentsJNI(byte[] self);
public static native int profileKeyCredentialPresentationGetUuidCiphertextJNI(byte[] self, byte[] output);
public static native int profileKeyCredentialPresentationGetProfileKeyCiphertextJNI(byte[] self, byte[] output);
public static native int profileKeyCredentialPresentationCheckValidContentsJNI(byte[] self);
public static native int receiptCredentialRequestContextGetRequestJNI(byte[] self, byte[] output);
public static native int receiptCredentialRequestContextCheckValidContentsJNI(byte[] self);
public static native int receiptCredentialRequestCheckValidContentsJNI(byte[] self);
public static native int receiptCredentialResponseCheckValidContentsJNI(byte[] self);
public static native int receiptCredentialGetReceiptExpirationTimeJNI(byte[] self, byte[] output);
public static native int receiptCredentialGetReceiptLevelJNI(byte[] self, byte[] output);
public static native int receiptCredentialCheckValidContentsJNI(byte[] self);
public static native int receiptCredentialPresentationGetReceiptExpirationTimeJNI(byte[] self, byte[] output);
public static native int receiptCredentialPresentationGetReceiptLevelJNI(byte[] self, byte[] output);
public static native int receiptCredentialPresentationGetReceiptSerialJNI(byte[] self, byte[] output);
public static native int receiptCredentialPresentationCheckValidContentsJNI(byte[] self);
public static native int uuidCiphertextCheckValidContentsJNI(byte[] self);
public static native int profileKeyCiphertextCheckValidContentsJNI(byte[] self);
private static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
}

View File

@ -0,0 +1,102 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import java.security.SecureRandom;
import java.util.UUID;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ServerPublicParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.groups.GroupSecretParams;
import org.signal.zkgroup.internal.Native;
import org.signal.zkgroup.util.UUIDUtil;
public class ClientZkProfileOperations {
private final ServerPublicParams serverPublicParams;
public ClientZkProfileOperations(ServerPublicParams serverPublicParams) {
this.serverPublicParams = serverPublicParams;
}
public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(UUID uuid, ProfileKey profileKey) {
return createProfileKeyCredentialRequestContext(new SecureRandom(), uuid, profileKey);
}
public ProfileKeyCredentialRequestContext createProfileKeyCredentialRequestContext(SecureRandom secureRandom, UUID uuid, ProfileKey profileKey) {
byte[] newContents = new byte[ProfileKeyCredentialRequestContext.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverPublicParamsCreateProfileKeyCredentialRequestContextDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, UUIDUtil.serialize(uuid), profileKey.getInternalContentsForJNI(), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCredentialRequestContext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public ProfileKeyCredential receiveProfileKeyCredential(ProfileKeyCredentialRequestContext profileKeyCredentialRequestContext, ProfileKeyCredentialResponse profileKeyCredentialResponse) throws VerificationFailedException {
if (profileKeyCredentialResponse == null) {
throw new VerificationFailedException();
}
byte[] newContents = new byte[ProfileKeyCredential.SIZE];
int ffi_return = Native.serverPublicParamsReceiveProfileKeyCredentialJNI(serverPublicParams.getInternalContentsForJNI(), profileKeyCredentialRequestContext.getInternalContentsForJNI(), profileKeyCredentialResponse.getInternalContentsForJNI(), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCredential(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(GroupSecretParams groupSecretParams, ProfileKeyCredential profileKeyCredential) {
return createProfileKeyCredentialPresentation(new SecureRandom(), groupSecretParams, profileKeyCredential);
}
public ProfileKeyCredentialPresentation createProfileKeyCredentialPresentation(SecureRandom secureRandom, GroupSecretParams groupSecretParams, ProfileKeyCredential profileKeyCredential) {
byte[] newContents = new byte[ProfileKeyCredentialPresentation.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverPublicParamsCreateProfileKeyCredentialPresentationDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, groupSecretParams.getInternalContentsForJNI(), profileKeyCredential.getInternalContentsForJNI(), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCredentialPresentation(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
}

View File

@ -0,0 +1,64 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import java.util.UUID;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
import org.signal.zkgroup.util.UUIDUtil;
public final class ProfileKey extends ByteArray {
public static final int SIZE = 32;
public ProfileKey(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
public ProfileKeyCommitment getCommitment(UUID uuid) {
byte[] newContents = new byte[ProfileKeyCommitment.SIZE];
int ffi_return = Native.profileKeyGetCommitmentJNI(contents, UUIDUtil.serialize(uuid), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCommitment(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public ProfileKeyVersion getProfileKeyVersion(UUID uuid) {
byte[] newContents = new byte[ProfileKeyVersion.SIZE];
int ffi_return = Native.profileKeyGetProfileKeyVersionJNI(contents, UUIDUtil.serialize(uuid), newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyVersion(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ProfileKeyCommitment extends ByteArray {
public static final int SIZE = 97;
public ProfileKeyCommitment(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.profileKeyCommitmentCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ProfileKeyCredential extends ByteArray {
public static final int SIZE = 145;
public ProfileKeyCredential(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.profileKeyCredentialCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,75 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.groups.ProfileKeyCiphertext;
import org.signal.zkgroup.groups.UuidCiphertext;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ProfileKeyCredentialPresentation extends ByteArray {
public static final int SIZE = 713;
public ProfileKeyCredentialPresentation(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.profileKeyCredentialPresentationCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public UuidCiphertext getUuidCiphertext() {
byte[] newContents = new byte[UuidCiphertext.SIZE];
int ffi_return = Native.profileKeyCredentialPresentationGetUuidCiphertextJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new UuidCiphertext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public ProfileKeyCiphertext getProfileKeyCiphertext() {
byte[] newContents = new byte[ProfileKeyCiphertext.SIZE];
int ffi_return = Native.profileKeyCredentialPresentationGetProfileKeyCiphertextJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCiphertext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ProfileKeyCredentialRequest extends ByteArray {
public static final int SIZE = 329;
public ProfileKeyCredentialRequest(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.profileKeyCredentialRequestCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,56 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ProfileKeyCredentialRequestContext extends ByteArray {
public static final int SIZE = 473;
public ProfileKeyCredentialRequestContext(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.profileKeyCredentialRequestContextCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public ProfileKeyCredentialRequest getRequest() {
byte[] newContents = new byte[ProfileKeyCredentialRequest.SIZE];
int ffi_return = Native.profileKeyCredentialRequestContextGetRequestJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCredentialRequest(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ProfileKeyCredentialResponse extends ByteArray {
public static final int SIZE = 457;
public ProfileKeyCredentialResponse(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.profileKeyCredentialResponseCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,36 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.internal.ByteArray;
import java.io.UnsupportedEncodingException;
public final class ProfileKeyVersion extends ByteArray {
public static final int SIZE = 64;
public ProfileKeyVersion(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
public ProfileKeyVersion(String contents) throws InvalidInputException, UnsupportedEncodingException {
super(contents.getBytes("UTF-8"), SIZE);
}
public String serialize() {
try {
return new String(contents, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new AssertionError();
}
}
}

View File

@ -0,0 +1,68 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.profiles;
import java.security.SecureRandom;
import java.util.UUID;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ServerSecretParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.groups.GroupPublicParams;
import org.signal.zkgroup.internal.Native;
import org.signal.zkgroup.util.UUIDUtil;
public class ServerZkProfileOperations {
private final ServerSecretParams serverSecretParams;
public ServerZkProfileOperations(ServerSecretParams serverSecretParams) {
this.serverSecretParams = serverSecretParams;
}
public ProfileKeyCredentialResponse issueProfileKeyCredential(ProfileKeyCredentialRequest profileKeyCredentialRequest, UUID uuid, ProfileKeyCommitment profileKeyCommitment) throws VerificationFailedException {
return issueProfileKeyCredential(new SecureRandom(), profileKeyCredentialRequest, uuid, profileKeyCommitment);
}
public ProfileKeyCredentialResponse issueProfileKeyCredential(SecureRandom secureRandom, ProfileKeyCredentialRequest profileKeyCredentialRequest, UUID uuid, ProfileKeyCommitment profileKeyCommitment) throws VerificationFailedException {
byte[] newContents = new byte[ProfileKeyCredentialResponse.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverSecretParamsIssueProfileKeyCredentialDeterministicJNI(serverSecretParams.getInternalContentsForJNI(), random, profileKeyCredentialRequest.getInternalContentsForJNI(), UUIDUtil.serialize(uuid), profileKeyCommitment.getInternalContentsForJNI(), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ProfileKeyCredentialResponse(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public void verifyProfileKeyCredentialPresentation(GroupPublicParams groupPublicParams, ProfileKeyCredentialPresentation profileKeyCredentialPresentation) throws VerificationFailedException {
int ffi_return = Native.serverSecretParamsVerifyProfileKeyCredentialPresentationJNI(serverSecretParams.getInternalContentsForJNI(), groupPublicParams.getInternalContentsForJNI(), profileKeyCredentialPresentation.getInternalContentsForJNI());
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
}

View File

@ -0,0 +1,101 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import java.security.SecureRandom;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ServerPublicParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.Native;
public class ClientZkReceiptOperations {
private final ServerPublicParams serverPublicParams;
public ClientZkReceiptOperations(ServerPublicParams serverPublicParams) {
this.serverPublicParams = serverPublicParams;
}
public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(ReceiptSerial receiptSerial) throws VerificationFailedException {
return createReceiptCredentialRequestContext(new SecureRandom(), receiptSerial);
}
public ReceiptCredentialRequestContext createReceiptCredentialRequestContext(SecureRandom secureRandom, ReceiptSerial receiptSerial) throws VerificationFailedException {
byte[] newContents = new byte[ReceiptCredentialRequestContext.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverPublicParamsCreateReceiptCredentialRequestContextDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, receiptSerial.getInternalContentsForJNI(), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ReceiptCredentialRequestContext(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public ReceiptCredential receiveReceiptCredential(ReceiptCredentialRequestContext receiptCredentialRequestContext, ReceiptCredentialResponse receiptCredentialResponse) throws VerificationFailedException {
byte[] newContents = new byte[ReceiptCredential.SIZE];
int ffi_return = Native.serverPublicParamsReceiveReceiptCredentialJNI(serverPublicParams.getInternalContentsForJNI(), receiptCredentialRequestContext.getInternalContentsForJNI(), receiptCredentialResponse.getInternalContentsForJNI(), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ReceiptCredential(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public ReceiptCredentialPresentation createReceiptCredentialPresentation(ReceiptCredential receiptCredential) throws VerificationFailedException {
return createReceiptCredentialPresentation(new SecureRandom(), receiptCredential);
}
public ReceiptCredentialPresentation createReceiptCredentialPresentation(SecureRandom secureRandom, ReceiptCredential receiptCredential) throws VerificationFailedException {
byte[] newContents = new byte[ReceiptCredentialPresentation.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverPublicParamsCreateReceiptCredentialPresentationDeterministicJNI(serverPublicParams.getInternalContentsForJNI(), random, receiptCredential.getInternalContentsForJNI(), newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ReceiptCredentialPresentation(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
}

View File

@ -0,0 +1,64 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import java.nio.ByteBuffer;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ReceiptCredential extends ByteArray {
public static final int SIZE = 129;
public ReceiptCredential(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.receiptCredentialCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public long getReceiptExpirationTime() {
byte[] newContents = new byte[8];
int ffi_return = Native.receiptCredentialGetReceiptExpirationTimeJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return ByteBuffer.wrap(newContents).getLong();
}
public long getReceiptLevel() {
byte[] newContents = new byte[8];
int ffi_return = Native.receiptCredentialGetReceiptLevelJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return ByteBuffer.wrap(newContents).getLong();
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,81 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import java.nio.ByteBuffer;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ReceiptCredentialPresentation extends ByteArray {
public static final int SIZE = 329;
public ReceiptCredentialPresentation(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.receiptCredentialPresentationCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public long getReceiptExpirationTime() {
byte[] newContents = new byte[8];
int ffi_return = Native.receiptCredentialPresentationGetReceiptExpirationTimeJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return ByteBuffer.wrap(newContents).getLong();
}
public long getReceiptLevel() {
byte[] newContents = new byte[8];
int ffi_return = Native.receiptCredentialPresentationGetReceiptLevelJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
return ByteBuffer.wrap(newContents).getLong();
}
public ReceiptSerial getReceiptSerial() {
byte[] newContents = new byte[ReceiptSerial.SIZE];
int ffi_return = Native.receiptCredentialPresentationGetReceiptSerialJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ReceiptSerial(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ReceiptCredentialRequest extends ByteArray {
public static final int SIZE = 97;
public ReceiptCredentialRequest(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.receiptCredentialRequestCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,56 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ReceiptCredentialRequestContext extends ByteArray {
public static final int SIZE = 177;
public ReceiptCredentialRequestContext(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.receiptCredentialRequestContextCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public ReceiptCredentialRequest getRequest() {
byte[] newContents = new byte[ReceiptCredentialRequest.SIZE];
int ffi_return = Native.receiptCredentialRequestContextGetRequestJNI(contents, newContents);
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ReceiptCredentialRequest(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,39 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.ByteArray;
import org.signal.zkgroup.internal.Native;
public final class ReceiptCredentialResponse extends ByteArray {
public static final int SIZE = 409;
public ReceiptCredentialResponse(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
int ffi_return = Native.receiptCredentialResponseCheckValidContentsJNI(contents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new InvalidInputException("FFI_RETURN_INPUT_ERROR");
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,27 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.internal.ByteArray;
public final class ReceiptSerial extends ByteArray {
public static final int SIZE = 16;
public ReceiptSerial(byte[] contents) throws InvalidInputException {
super(contents, SIZE);
}
public byte[] serialize() {
return contents.clone();
}
}

View File

@ -0,0 +1,65 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
// Generated by zkgroup/codegen/codegen.py - do not edit
package org.signal.zkgroup.receipts;
import java.security.SecureRandom;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.ServerSecretParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.ZkGroupError;
import org.signal.zkgroup.internal.Native;
public class ServerZkReceiptOperations {
private final ServerSecretParams serverSecretParams;
public ServerZkReceiptOperations(ServerSecretParams serverSecretParams) {
this.serverSecretParams = serverSecretParams;
}
public ReceiptCredentialResponse issueReceiptCredential(ReceiptCredentialRequest receiptCredentialRequest, long receiptExpirationTime, long receiptLevel) throws VerificationFailedException {
return issueReceiptCredential(new SecureRandom(), receiptCredentialRequest, receiptExpirationTime, receiptLevel);
}
public ReceiptCredentialResponse issueReceiptCredential(SecureRandom secureRandom, ReceiptCredentialRequest receiptCredentialRequest, long receiptExpirationTime, long receiptLevel) throws VerificationFailedException {
byte[] newContents = new byte[ReceiptCredentialResponse.SIZE];
byte[] random = new byte[Native.RANDOM_LENGTH];
secureRandom.nextBytes(random);
int ffi_return = Native.serverSecretParamsIssueReceiptCredentialDeterministicJNI(serverSecretParams.getInternalContentsForJNI(), random, receiptCredentialRequest.getInternalContentsForJNI(), receiptExpirationTime, receiptLevel, newContents);
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
try {
return new ReceiptCredentialResponse(newContents);
} catch (InvalidInputException e) {
throw new AssertionError(e);
}
}
public void verifyReceiptCredentialPresentation(ReceiptCredentialPresentation receiptCredentialPresentation) throws VerificationFailedException {
int ffi_return = Native.serverSecretParamsVerifyReceiptCredentialPresentationJNI(serverSecretParams.getInternalContentsForJNI(), receiptCredentialPresentation.getInternalContentsForJNI());
if (ffi_return == Native.FFI_RETURN_INPUT_ERROR) {
throw new VerificationFailedException();
}
if (ffi_return != Native.FFI_RETURN_OK) {
throw new ZkGroupError("FFI_RETURN!=OK");
}
}
}

View File

@ -0,0 +1,50 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup.util;
import java.util.UUID;
public final class UUIDUtil {
public static final int UUID_LENGTH = 16;
private UUIDUtil() {
}
public static UUID deserialize(byte[] bytes) {
long mostSignificantBits = bytesToLong(bytes, 0);
long leastSignificantBits = bytesToLong(bytes, 8);
return new UUID(mostSignificantBits, leastSignificantBits);
}
public static byte[] serialize(UUID uuid) {
byte[] bytes = new byte[UUID_LENGTH];
longToBytes(uuid.getMostSignificantBits(), bytes, 0);
longToBytes(uuid.getLeastSignificantBits(), bytes, 8);
return bytes;
}
private static void longToBytes(long l, byte[] result, int offset) {
for (int i = 7; i >= 0; i--) {
result[i + offset] = (byte) (l & 0xFF);
l >>= 8;
}
}
private static long bytesToLong(byte[] b, int offset) {
long result = 0;
for (int i = 0; i < 8; i++) {
result <<= 8;
result |= (b[i + offset] & 0xFF);
}
return result;
}
}

View File

@ -0,0 +1,65 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup;
import java.io.IOException;
/**
* Utility for bytes to hex and hex to bytes.
*/
public final class Hex {
private final static char[] HEX_DIGITS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
private Hex() {
}
public static String toStringCondensed(byte[] bytes) {
StringBuilder builder = new StringBuilder(bytes.length * 2);
for (byte aByte : bytes) {
appendHexChar(builder, aByte);
}
return builder.toString();
}
public static byte[] fromStringCondensedAssert(String encoded) {
try {
return fromStringCondensed(encoded);
} catch (IOException e) {
throw new AssertionError(e);
}
}
public static byte[] fromStringCondensed(String encoded) throws IOException {
final char[] data = encoded.toCharArray();
final int len = data.length;
if ((len & 0x01) != 0) {
throw new IOException("Odd number of characters.");
}
final byte[] out = new byte[len >> 1];
for (int i = 0, j = 0; j < len; i++) {
int f = Character.digit(data[j], 16) << 4;
j++;
f = f | Character.digit(data[j], 16);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
private static void appendHexChar(StringBuilder buf, int b) {
buf.append(HEX_DIGITS[(b >> 4) & 0xf]);
buf.append(HEX_DIGITS[b & 0xf]);
}
}

View File

@ -0,0 +1,40 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup;
import org.junit.Test;
import java.security.SecureRandom;
import static org.junit.Assert.assertArrayEquals;
import org.signal.zkgroup.internal.*;
import java.io.IOException;
public final class RandomnessTest extends SecureRandomTest {
@Test
public void generate_usesSecureRandom() throws IOException {
byte[] array = Hex.fromStringCondensed("e18de7dfe7195f0b9320e309cd3ed3765dcf54a09be57813ee69f5ea35867689");
SecureRandom secureRandom = createSecureRandom(array);
byte[] random = new byte[array.length];
secureRandom.nextBytes(random);
assertArrayEquals(array, random);
}
@Test
public void generate_usesSecureRandom_alternativeValues() throws IOException {
byte[] array = Hex.fromStringCondensed("ba8a89a05eaf51cac3ce35256199b38a18e0e1fa16f1443db8e34b0489739b80");
SecureRandom secureRandom = createSecureRandom(array);
byte[] random = new byte[array.length];
secureRandom.nextBytes(random);
assertArrayEquals(array, random);
}
}

View File

@ -0,0 +1,43 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.security.SecureRandom;
import java.util.Arrays;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doAnswer;
public abstract class SecureRandomTest {
public static SecureRandom createSecureRandom(final byte[] nextRandom) {
SecureRandom mockRandom = Mockito.mock(SecureRandom.class);
doAnswer(new Answer() {
byte[] bytes = Arrays.copyOf(nextRandom, nextRandom.length);
@Override
public Object answer(InvocationOnMock invocation) {
assertNotNull("Bytes have been used", bytes);
byte[] input = (byte[]) invocation.getArguments()[0];
assertEquals("setSecureRandomNextBytes was setup with wrong number of bytes", nextRandom.length, input.length);
System.arraycopy(bytes, 0, input, 0, bytes.length);
bytes = null;
return null; // Void method
}
}).when(mockRandom).nextBytes(any(byte[].class));
return mockRandom;
}
}

View File

@ -0,0 +1,57 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup;
import org.junit.Test;
import org.signal.zkgroup.util.UUIDUtil;
import java.util.UUID;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import org.signal.zkgroup.internal.*;
import java.io.IOException;
public final class UUIDUtilTest {
@Test
public void serialize() throws IOException {
UUID uuid = UUID.fromString("67dfd496-ea02-4720-b13d-83a462168b1d");
byte[] serialized = UUIDUtil.serialize(uuid);
assertArrayEquals(Hex.fromStringCondensed("67dfd496ea024720b13d83a462168b1d"), serialized);
}
@Test
public void serialize_alternativeValues() throws IOException {
UUID uuid = UUID.fromString("b70df6ac-3b21-4b39-a514-613561f51e2a");
byte[] serialized = UUIDUtil.serialize(uuid);
assertArrayEquals(Hex.fromStringCondensed("b70df6ac3b214b39a514613561f51e2a"), serialized);
}
@Test
public void deserialize() throws IOException {
byte[] bytes = Hex.fromStringCondensed("3dc48790568b49c19bd6ab6604a5bc32");
UUID uuid = UUIDUtil.deserialize(bytes);
assertEquals("3dc48790-568b-49c1-9bd6-ab6604a5bc32", uuid.toString());
}
@Test
public void deserialize_alternativeValues() throws IOException {
byte[] bytes = Hex.fromStringCondensed("b83dfb0b67f141aa992e030c167cd011");
UUID uuid = UUIDUtil.deserialize(bytes);
assertEquals("b83dfb0b-67f1-41aa-992e-030c167cd011", uuid.toString());
}
}

View File

@ -0,0 +1,346 @@
//
// Copyright (C) 2020 Signal Messenger, LLC.
// All rights reserved.
//
// SPDX-License-Identifier: GPL-3.0-only
//
package org.signal.zkgroup.integrationtests;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import org.signal.zkgroup.Hex;
import org.signal.zkgroup.InvalidInputException;
import org.signal.zkgroup.NotarySignature;
import org.signal.zkgroup.SecureRandomTest;
import org.signal.zkgroup.ServerPublicParams;
import org.signal.zkgroup.ServerSecretParams;
import org.signal.zkgroup.VerificationFailedException;
import org.signal.zkgroup.InvalidRedemptionTimeException;
import org.signal.zkgroup.auth.AuthCredential;
import org.signal.zkgroup.auth.AuthCredentialPresentation;
import org.signal.zkgroup.auth.AuthCredentialResponse;
import org.signal.zkgroup.auth.ClientZkAuthOperations;
import org.signal.zkgroup.auth.ServerZkAuthOperations;
import org.signal.zkgroup.groups.ClientZkGroupCipher;
import org.signal.zkgroup.groups.GroupMasterKey;
import org.signal.zkgroup.groups.GroupPublicParams;
import org.signal.zkgroup.groups.GroupSecretParams;
import org.signal.zkgroup.groups.ProfileKeyCiphertext;
import org.signal.zkgroup.groups.UuidCiphertext;
import org.signal.zkgroup.profiles.ClientZkProfileOperations;
import org.signal.zkgroup.profiles.ProfileKey;
import org.signal.zkgroup.profiles.ProfileKeyCommitment;
import org.signal.zkgroup.profiles.ProfileKeyCredential;
import org.signal.zkgroup.profiles.ProfileKeyCredentialPresentation;
import org.signal.zkgroup.profiles.ProfileKeyCredentialRequest;
import org.signal.zkgroup.profiles.ProfileKeyCredentialRequestContext;
import org.signal.zkgroup.profiles.ProfileKeyCredentialResponse;
import org.signal.zkgroup.profiles.ProfileKeyVersion;
import org.signal.zkgroup.profiles.ServerZkProfileOperations;
import org.signal.zkgroup.util.UUIDUtil;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.UUID;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public final class ZkGroupTest extends SecureRandomTest {
private static final byte[] TEST_ARRAY_16 = Hex.fromStringCondensedAssert("000102030405060708090a0b0c0d0e0f");
private static final byte[] TEST_ARRAY_32 = Hex.fromStringCondensedAssert("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
private static final byte[] TEST_ARRAY_32_1 = Hex.fromStringCondensedAssert("6465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f80818283");
private static final byte[] TEST_ARRAY_32_2 = Hex.fromStringCondensedAssert("c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7");
private static final byte[] TEST_ARRAY_32_3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32 };
private static final byte[] TEST_ARRAY_32_4 = {
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
28, 29, 30, 31, 32, 33};
private static final byte[] TEST_ARRAY_32_5 = Hex.fromStringCondensedAssert("030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122");
private static final byte[] authPresentationResult = Hex.fromStringCondensedAssert(
"000cde979737ed30bbeb16362e4e076945ce02069f727b0ed4c3c33c011e82546e1cdf081fbdf37c03a851ad060bdcbf6378cb4cb16dc3154d08de5439b5323203729d1841b517033af2fd177d30491c138ae723655734f6e5cc01c00696f4e92096d8c33df26ba2a820d42e9735d30f8eeef96d399079073c099f7035523bfe716638659319d3c36ad34c00ef8850f663c4d93030235074312a8878b6a5c5df4fbc7d32935278bfa5996b44ab75d6f06f4c30b98640ad5de74742656c8977567de000000000000000fde69f82ad2dcb4909650ac6b2573841af568fef822b32b45f625a764691a704d11b6f385261468117ead57fa623338e21c66ed846ab65809fcac158066d8e0e444077b99540d886e7dc09555dd6faea2cd3697f1e089f82d54e5d0fe4a185008b5cbc3979391ad71686bc03be7b00ea7e42c08d9f1d75c3a56c27ae2467b80636c0b5343eda7cd578ba88ddb7a0766568477fed63cf531862122c6c15b4a707973d41782cfc0ef4fe6c3115988a2e339015938d2df0a5d30237a2592cc10c05a9e4ef6b695bca99736b1a49ea39606a381ecfb05efe60d28b54823ec5a3680c765de9df4cfa5487f360e29e99343e91811baec331c4680985e608ca5d408e21725c6aa1b61d5a8b48d75f4aaa9a3cbe88d3e0f1a54319081f77c72c8f52547440e20100");
private static final byte[] profileKeyPresentationResult = Hex.fromStringCondensedAssert(
"00c4d19bca1ae844585168869da4133e0e0bb59f2ce17b7ac65bff5da9610eca103429d8022a94bae2b5b1057b5595b8ad70bfc2d0e1ad662cb75e6bae0782be6f00e3db793bc28561f0196c2e74da6f303fa8bcb70c94096671b73f7b3a95fb002200d5b9180fa0ef7d3014d01344145b4d38480d72ff25c24294e305e5705072e0d32cc4e84f5caf31486089a4b934c80c92eba43472ff23a5af93c397535d33801f0e6fc6eb2ee0d117f03bb4fd38a8b9c88d94708131f38742ca804a3cfc4f9476bc2d03f53d17001c36478afbe9cc535a224b2df6b2b08bef06cbc7d4dc42ccfc3459f7ac5c4419ae9f3c8a161d554d047778943216240858da3b1101984c40010000000000007a01eea6b2adad14d71ab8b8e411bef3c596e954b70e4031570cb1abd7e932083241f1caca3116708fa4319fbbdfe351376c23644ae09a42f0155db4996c9d0c7ffc8521c1914c0e1a20ae51e65df64dd5e6e5985b3d9d31732046d2d77f9c08aaccf056b84026073976eec6164cbdaee5d9e76e497f0c290af681cabd5c5101282abb26c3680d6087ce053310fe8a94f59d8ae23caac5fc0ed0c379888abf028a6f29f89d4fe2acc1706341b2245ba1885bca57e1e27ccf7ed79371500965009f960c2ba00fad3e93383b87ce119cac0b3360eb99284ce78e2cbed680f7960373e0ab75c190254160c2353614109489e653c9b2e1c93f92c7c5ad583d987a04bd3541b24485c33ea49bac43c87c4ab3efde2e2d7ec10a40be544199f925b20b2c55542bc56410571e41cd8e0286f609a66768b5061ccb4777af32309928dd09765de9df4cfa5487f360e29e99343e91811baec331c4680985e608ca5d408e21725c6aa1b61d5a8b48d75f4aaa9a3cbe88d3e0f1a54319081f77c72c8f52547448c03ab4afbf6b8fb0e126c037a0ad4094600dd0e0634d76f88c21087f3cfb485a89bc1e3abc4c95041d1d170eccf02933ec5393d4be1dc573f83c33d3b9a746");
@Test
public void testAuthIntegration() throws VerificationFailedException, InvalidInputException, InvalidRedemptionTimeException {
UUID uuid = UUIDUtil.deserialize(TEST_ARRAY_16);
int redemptionTime = 123456;
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
// CLIENT
GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
GroupPublicParams groupPublicParams = groupSecretParams.getPublicParams();
// SERVER
// Issue credential
AuthCredentialResponse authCredentialResponse = serverZkAuth.issueAuthCredential(createSecureRandom(TEST_ARRAY_32_2), uuid, redemptionTime);
// CLIENT
// Receive credential
ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher (groupSecretParams );
AuthCredential authCredential = clientZkAuthCipher.receiveAuthCredential(uuid, redemptionTime, authCredentialResponse);
// Create and decrypt user entry
UuidCiphertext uuidCiphertext = clientZkGroupCipher.encryptUuid(uuid);
UUID plaintext = clientZkGroupCipher.decryptUuid(uuidCiphertext);
assertEquals(uuid, plaintext);
// Create presentation
AuthCredentialPresentation presentation = clientZkAuthCipher.createAuthCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
// Verify presentation, using times at the edge of the acceptable window
UuidCiphertext uuidCiphertextRecv = presentation.getUuidCiphertext();
assertArrayEquals(uuidCiphertext.serialize(), uuidCiphertextRecv.serialize());
assertEquals(presentation.getRedemptionTime(), redemptionTime);
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(123455L, TimeUnit.DAYS));
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(123458L, TimeUnit.DAYS));
try {
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(123455L, TimeUnit.DAYS) - 1L);
throw new AssertionError("verifyAuthCredentialPresentation should fail #1!");
} catch(InvalidRedemptionTimeException e) {
// good
}
try {
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(123458L, TimeUnit.DAYS) + 1L);
throw new AssertionError("verifyAuthCredentialPresentation should fail #2!");
} catch(InvalidRedemptionTimeException e) {
// good
}
assertArrayEquals(presentation.serialize(), authPresentationResult);
}
@Test
public void testAuthIntegrationCurrentTime() throws VerificationFailedException, InvalidInputException, InvalidRedemptionTimeException {
// This test is mostly the same as testAuthIntegration() except instead of using a hardcoded
// redemption date to compare against test vectors, it uses the current time
UUID uuid = UUIDUtil.deserialize(TEST_ARRAY_16);
int redemptionTime = (int)TimeUnit.DAYS.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
ServerZkAuthOperations serverZkAuth = new ServerZkAuthOperations(serverSecretParams);
// CLIENT
GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
GroupPublicParams groupPublicParams = groupSecretParams.getPublicParams();
// SERVER
// Issue credential
AuthCredentialResponse authCredentialResponse = serverZkAuth.issueAuthCredential(createSecureRandom(TEST_ARRAY_32_2), uuid, redemptionTime);
// CLIENT
// Receive credential
ClientZkAuthOperations clientZkAuthCipher = new ClientZkAuthOperations(serverPublicParams);
ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher (groupSecretParams );
AuthCredential authCredential = clientZkAuthCipher.receiveAuthCredential(uuid, redemptionTime, authCredentialResponse);
// Create and decrypt user entry
UuidCiphertext uuidCiphertext = clientZkGroupCipher.encryptUuid(uuid);
UUID plaintext = clientZkGroupCipher.decryptUuid(uuidCiphertext);
assertEquals(uuid, plaintext);
// Create presentation
AuthCredentialPresentation presentation = clientZkAuthCipher.createAuthCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, authCredential);
// Verify presentation, using times at the edge of the acceptable window
UuidCiphertext uuidCiphertextRecv = presentation.getUuidCiphertext();
assertArrayEquals(uuidCiphertext.serialize(), uuidCiphertextRecv.serialize());
assertEquals(presentation.getRedemptionTime(), redemptionTime);
// By default the library uses the current time
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation);
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(redemptionTime - 1L, TimeUnit.DAYS));
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(redemptionTime + 2L, TimeUnit.DAYS));
try {
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(redemptionTime - 1L, TimeUnit.DAYS) - 1L);
throw new AssertionError("verifyAuthCredentialPresentation (current time) should fail #1!");
} catch(InvalidRedemptionTimeException e) {
// good
}
try {
serverZkAuth.verifyAuthCredentialPresentation(groupPublicParams, presentation, TimeUnit.MILLISECONDS.convert(redemptionTime + 2L, TimeUnit.DAYS) + 1L);
throw new AssertionError("verifyAuthCredentialPresentation (current time) should fail #2!");
} catch(InvalidRedemptionTimeException e) {
// good
}
}
@Test
public void testProfileKeyIntegration() throws VerificationFailedException, InvalidInputException, UnsupportedEncodingException {
UUID uuid = UUIDUtil.deserialize(TEST_ARRAY_16);
int redemptionTime = 1234567;
// Generate keys (client's are per-group, server's are not)
// ---
// SERVER
ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
ServerZkProfileOperations serverZkProfile = new ServerZkProfileOperations(serverSecretParams);
// CLIENT
GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
assertArrayEquals(groupSecretParams.getMasterKey().serialize(), masterKey.serialize());
GroupPublicParams groupPublicParams = groupSecretParams.getPublicParams();
ClientZkProfileOperations clientZkProfileCipher = new ClientZkProfileOperations(serverPublicParams);
ProfileKey profileKey = new ProfileKey(TEST_ARRAY_32_1);
ProfileKeyCommitment profileKeyCommitment = profileKey.getCommitment(uuid);
// Create context and request
ProfileKeyCredentialRequestContext context = clientZkProfileCipher.createProfileKeyCredentialRequestContext(createSecureRandom(TEST_ARRAY_32_3), uuid, profileKey);
ProfileKeyCredentialRequest request = context.getRequest();
// SERVER
ProfileKeyCredentialResponse response = serverZkProfile.issueProfileKeyCredential(createSecureRandom(TEST_ARRAY_32_4), request, uuid, profileKeyCommitment);
// CLIENT
// Gets stored profile credential
ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
ProfileKeyCredential profileKeyCredential = clientZkProfileCipher.receiveProfileKeyCredential(context, response);
// Create encrypted UID and profile key
UuidCiphertext uuidCiphertext = clientZkGroupCipher.encryptUuid(uuid);
UUID plaintext = clientZkGroupCipher.decryptUuid(uuidCiphertext);
assertEquals(plaintext, uuid);
ProfileKeyCiphertext profileKeyCiphertext = clientZkGroupCipher.encryptProfileKey(profileKey, uuid);
ProfileKey decryptedProfileKey = clientZkGroupCipher.decryptProfileKey(profileKeyCiphertext, uuid);
assertArrayEquals(profileKey.serialize(), decryptedProfileKey.serialize());
ProfileKeyCredentialPresentation presentation = clientZkProfileCipher.createProfileKeyCredentialPresentation(createSecureRandom(TEST_ARRAY_32_5), groupSecretParams, profileKeyCredential);
assertArrayEquals(presentation.serialize(), profileKeyPresentationResult);
// Verify presentation
serverZkProfile.verifyProfileKeyCredentialPresentation(groupPublicParams, presentation);
UuidCiphertext uuidCiphertextRecv = presentation.getUuidCiphertext();
assertArrayEquals(uuidCiphertext.serialize(), uuidCiphertextRecv.serialize());
ProfileKeyVersion pkvB = profileKey.getProfileKeyVersion(uuid);
ProfileKeyVersion pkvC = new ProfileKeyVersion(pkvB.serialize());
if (!pkvB.serialize().equals(pkvC.serialize()))
throw new AssertionError();
}
@Test
public void testServerSignatures() throws VerificationFailedException {
ServerSecretParams serverSecretParams = ServerSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
ServerPublicParams serverPublicParams = serverSecretParams.getPublicParams();
byte[] message = TEST_ARRAY_32_1;
NotarySignature signature = serverSecretParams.sign(createSecureRandom(TEST_ARRAY_32_2), message);
serverPublicParams.verifySignature(message, signature);
assertByteArray(
"87d354564d35ef91edba851e0815612e864c227a0471d50c270698604406d003a55473f576cf241fc6b41c6b16e5e63b333c02fe4a33858022fdd7a4ab367b06", signature.serialize());
byte[] alteredMessage = message.clone();
alteredMessage[0] ^= 1;
try {
serverPublicParams.verifySignature(alteredMessage, signature);
throw new AssertionError("signature validation should have failed!");
} catch (VerificationFailedException e) {
// good
}
}
@Test
public void testGroupIdentifier() throws VerificationFailedException {
GroupSecretParams groupSecretParams = GroupSecretParams.generate(createSecureRandom(TEST_ARRAY_32));
GroupPublicParams groupPublicParams = groupSecretParams.getPublicParams();
//assertByteArray("31f2c60f86f4c5996e9e2568355591d9", groupPublicParams.getGroupIdentifier().serialize());
}
@Test(expected = IllegalArgumentException.class)
public void testErrors() throws RuntimeException {
byte[] ckp = new byte[GroupSecretParams.SIZE];
Arrays.fill(ckp, (byte) -127);
GroupSecretParams groupSecretParams = new GroupSecretParams(ckp);
}
@Test
public void testBlobEncryption() throws InvalidInputException, VerificationFailedException {
GroupMasterKey masterKey = new GroupMasterKey(TEST_ARRAY_32_1);
GroupSecretParams groupSecretParams = GroupSecretParams.deriveFromMasterKey(masterKey);
ClientZkGroupCipher clientZkGroupCipher = new ClientZkGroupCipher(groupSecretParams);
byte[] plaintext = Hex.fromStringCondensedAssert("0102030405060708111213141516171819");
byte[] ciphertext = Hex.fromStringCondensedAssert("dd4d032ca9bb75a4a78541b90cb4e95743f3b0dabfc7e11101b098e34f6cf6513940a04c1f20a302692afdc7087f10196000");
byte[] ciphertextPaddedWith257 = Hex.fromStringCondensedAssert("5cb5b7bff06e85d929f3511fd194e638cf32a47663868bc8e64d98fb1bbe435ebd21c763ce2d42e85a1b2c169f12f9818ddadcf4b491398b7c5d46a224e1582749f5e2a4a2294caaaaab843a1b7cf6426fd543d09ff32a4ba5f319ca4442b4da34b3e2b5b4f8a52fdc4b484ea86b33db3ebb758dbd9614178f0e4e1f9b2b914f1e786936b62ed2b58b7ae3cb3e7ae0835b9516959837406662b85eac740cef83b60b5aaeaaab95643c2bef8ce87358fabff9d690052beb9e52d0c947e7c986b2f3ce3b7161cec72c08e2c4ade3debe3792d736c0457bc352afb8b6caa48a5b92c1ec05ba808ba8f94c6572ebbf29818912344987573de419dbcc7f1ea0e4b2dd4077b76b381819747ac332e46fa23abfc3338e2f4b081a8a53cba0988eef116764d944f1ce3f20a302692afdc7087f10196000");
byte[] ciphertext2 = clientZkGroupCipher.encryptBlob(createSecureRandom(TEST_ARRAY_32_2), plaintext);
byte[] plaintext2 = clientZkGroupCipher.decryptBlob(ciphertext2);
assertArrayEquals(plaintext, plaintext2);
assertArrayEquals(ciphertext, ciphertext2);
byte[] plaintext257 = clientZkGroupCipher.decryptBlob(ciphertextPaddedWith257);
assertArrayEquals(plaintext, plaintext257);
}
private void assertByteArray(String expectedAsHex, byte[] actual) {
byte[] expectedBytes = Hex.fromStringCondensedAssert(expectedAsHex);
assertArrayEquals(expectedBytes, actual);
}
}