mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-26 11:51:10 +01:00
Remove unused code.
This commit is contained in:
committed by
Cody Henthorne
parent
15aa941436
commit
ea0b8fc594
@@ -1,28 +0,0 @@
|
||||
package org.whispersystems.signalservice.api;
|
||||
|
||||
import org.whispersystems.signalservice.api.kbs.MasterKey;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse;
|
||||
|
||||
public final class SvrPinData {
|
||||
|
||||
private final MasterKey masterKey;
|
||||
private final TokenResponse tokenResponse;
|
||||
|
||||
// Visible for testing
|
||||
public SvrPinData(MasterKey masterKey, TokenResponse tokenResponse) {
|
||||
this.masterKey = masterKey;
|
||||
this.tokenResponse = tokenResponse;
|
||||
}
|
||||
|
||||
public MasterKey getMasterKey() {
|
||||
return masterKey;
|
||||
}
|
||||
|
||||
public TokenResponse getTokenResponse() {
|
||||
return tokenResponse;
|
||||
}
|
||||
|
||||
public int getRemainingTries() {
|
||||
return tokenResponse.getTries();
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package org.whispersystems.signalservice.api;
|
||||
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse;
|
||||
|
||||
class TokenException extends Exception {
|
||||
|
||||
private final TokenResponse nextToken;
|
||||
private final boolean canAutomaticallyRetry;
|
||||
|
||||
TokenException(TokenResponse nextToken, boolean canAutomaticallyRetry) {
|
||||
this.nextToken = nextToken;
|
||||
this.canAutomaticallyRetry = canAutomaticallyRetry;
|
||||
}
|
||||
|
||||
public TokenResponse getToken() {
|
||||
return nextToken;
|
||||
}
|
||||
|
||||
public boolean isCanAutomaticallyRetry() {
|
||||
return canAutomaticallyRetry;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.whispersystems.signalservice.api.groupsv2;
|
||||
|
||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class UuidProfileKey {
|
||||
|
||||
private final UUID uuid;
|
||||
private final ProfileKey profileKey;
|
||||
|
||||
public UuidProfileKey(UUID uuid, ProfileKey profileKey) {
|
||||
this.uuid = uuid;
|
||||
this.profileKey = profileKey;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public ProfileKey getProfileKey() {
|
||||
return profileKey;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.messages;
|
||||
|
||||
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Group information to include in SignalServiceMessages destined to groups.
|
||||
*
|
||||
* This class represents a "context" that is included with Signal Service messages
|
||||
* to make them group messages. There are three types of context:
|
||||
*
|
||||
* 1) Update -- Sent when either creating a group, or updating the properties
|
||||
* of a group (such as the avatar icon, membership list, or title).
|
||||
* 2) Deliver -- Sent when a message is to be delivered to an existing group.
|
||||
* 3) Quit -- Sent when the sender wishes to leave an existing group.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class SignalServiceGroup {
|
||||
|
||||
public enum Type {
|
||||
UNKNOWN,
|
||||
UPDATE,
|
||||
DELIVER,
|
||||
QUIT,
|
||||
REQUEST_INFO
|
||||
}
|
||||
|
||||
private final byte[] groupId;
|
||||
private final Type type;
|
||||
private final Optional<String> name;
|
||||
private final Optional<List<SignalServiceAddress>> members;
|
||||
private final Optional<SignalServiceAttachment> avatar;
|
||||
|
||||
|
||||
/**
|
||||
* Construct a DELIVER group context.
|
||||
* @param groupId
|
||||
*/
|
||||
public SignalServiceGroup(byte[] groupId) {
|
||||
this(Type.DELIVER, groupId, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a group context.
|
||||
* @param type The group message type (update, deliver, quit).
|
||||
* @param groupId The group ID.
|
||||
* @param name The group title.
|
||||
* @param members The group membership list.
|
||||
* @param avatar The group avatar icon.
|
||||
*/
|
||||
public SignalServiceGroup(Type type, byte[] groupId, String name,
|
||||
List<SignalServiceAddress> members,
|
||||
SignalServiceAttachment avatar)
|
||||
{
|
||||
this.type = type;
|
||||
this.groupId = groupId;
|
||||
this.name = Optional.ofNullable(name);
|
||||
this.members = Optional.ofNullable(members);
|
||||
this.avatar = Optional.ofNullable(avatar);
|
||||
}
|
||||
|
||||
public byte[] getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Optional<String> getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Optional<List<SignalServiceAddress>> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
public Optional<SignalServiceAttachment> getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public static Builder newUpdateBuilder() {
|
||||
return new Builder(Type.UPDATE);
|
||||
}
|
||||
|
||||
public static Builder newBuilder(Type type) {
|
||||
return new Builder(type);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private Type type;
|
||||
private byte[] id;
|
||||
private String name;
|
||||
private List<SignalServiceAddress> members;
|
||||
private SignalServiceAttachment avatar;
|
||||
|
||||
private Builder(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Builder withId(byte[] id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withMembers(List<SignalServiceAddress> members) {
|
||||
this.members = members;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder withAvatar(SignalServiceAttachment avatar) {
|
||||
this.avatar = avatar;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SignalServiceGroup build() {
|
||||
if (id == null) throw new IllegalArgumentException("No group ID specified!");
|
||||
|
||||
if (type == Type.UPDATE && name == null && members == null && avatar == null) {
|
||||
throw new IllegalArgumentException("Group update with no updates!");
|
||||
}
|
||||
|
||||
return new SignalServiceGroup(type, id, name, members, avatar);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package org.whispersystems.signalservice.api.messages;
|
||||
|
||||
|
||||
import org.whispersystems.signalservice.api.push.ServiceId.PNI;
|
||||
|
||||
/**
|
||||
* When someone sends a message to your PNI, you need to attach one of these PNI signature messages,
|
||||
* proving that you own the PNI identity.
|
||||
*
|
||||
* The signature is generated by signing your ACI public key with your PNI identity.
|
||||
*/
|
||||
public class SignalServicePniSignatureMessage {
|
||||
|
||||
private final PNI pni;
|
||||
private final byte[] signature;
|
||||
|
||||
public SignalServicePniSignatureMessage(PNI pni, byte[] signature) {
|
||||
this.pni = pni;
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public PNI getPni() {
|
||||
return pni;
|
||||
}
|
||||
|
||||
public byte[] getSignature() {
|
||||
return signature;
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.messages.multidevice;
|
||||
|
||||
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class DeviceGroup {
|
||||
|
||||
private final byte[] id;
|
||||
private final Optional<String> name;
|
||||
private final List<SignalServiceAddress> members;
|
||||
private final Optional<SignalServiceAttachmentStream> avatar;
|
||||
private final boolean active;
|
||||
private final Optional<Integer> expirationTimer;
|
||||
private final Optional<String> color;
|
||||
private final boolean blocked;
|
||||
private final Optional<Integer> inboxPosition;
|
||||
private final boolean archived;
|
||||
|
||||
public DeviceGroup(byte[] id,
|
||||
Optional<String> name,
|
||||
List<SignalServiceAddress> members,
|
||||
Optional<SignalServiceAttachmentStream> avatar,
|
||||
boolean active,
|
||||
Optional<Integer> expirationTimer,
|
||||
Optional<String> color,
|
||||
boolean blocked,
|
||||
Optional<Integer> inboxPosition,
|
||||
boolean archived)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.members = members;
|
||||
this.avatar = avatar;
|
||||
this.active = active;
|
||||
this.expirationTimer = expirationTimer;
|
||||
this.color = color;
|
||||
this.blocked = blocked;
|
||||
this.inboxPosition = inboxPosition;
|
||||
this.archived = archived;
|
||||
}
|
||||
|
||||
public Optional<SignalServiceAttachmentStream> getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public Optional<String> getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public byte[] getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public List<SignalServiceAddress> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public Optional<Integer> getExpirationTimer() {
|
||||
return expirationTimer;
|
||||
}
|
||||
|
||||
public Optional<String> getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public boolean isBlocked() {
|
||||
return blocked;
|
||||
}
|
||||
|
||||
public Optional<Integer> getInboxPosition() {
|
||||
return inboxPosition;
|
||||
}
|
||||
|
||||
public boolean isArchived() {
|
||||
return archived;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.api.svr
|
||||
|
||||
import org.signal.libsignal.svr2.PinHash
|
||||
import org.whispersystems.signalservice.internal.push.AuthCredentials
|
||||
|
||||
/**
|
||||
* Encapsulates the various dependencies needed to create a [PinHash] in SVR2 without having to expose them.
|
||||
*/
|
||||
internal class Svr2PinHasher(
|
||||
private val authCredentials: AuthCredentials,
|
||||
private val mrEnclave: ByteArray
|
||||
) {
|
||||
fun hash(normalizedPin: ByteArray): PinHash {
|
||||
return PinHash.svr2(normalizedPin, authCredentials.username(), mrEnclave)
|
||||
}
|
||||
}
|
||||
@@ -193,11 +193,6 @@ internal class Svr2Socket(
|
||||
FAILED
|
||||
}
|
||||
|
||||
data class Response(
|
||||
val response: Svr2Response,
|
||||
val pinHasher: Svr2PinHasher
|
||||
)
|
||||
|
||||
companion object {
|
||||
private val TAG = Svr2Socket::class.java.simpleName
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
import org.signal.libsignal.protocol.util.ByteUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
final class AESCipher {
|
||||
|
||||
private static final int TAG_LENGTH_BYTES = 16;
|
||||
private static final int TAG_LENGTH_BITS = TAG_LENGTH_BYTES * 8;
|
||||
|
||||
static byte[] decrypt(byte[] key, byte[] iv, byte[] ciphertext, byte[] tag) throws InvalidCiphertextException {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(TAG_LENGTH_BITS, iv));
|
||||
|
||||
return cipher.doFinal(ByteUtil.combine(ciphertext, tag));
|
||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException e) {
|
||||
throw new AssertionError(e);
|
||||
} catch (InvalidKeyException | BadPaddingException e) {
|
||||
throw new InvalidCiphertextException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static AESEncryptedResult encrypt(byte[] key, byte[] aad, byte[] requestData) {
|
||||
try {
|
||||
byte[] iv = Util.getSecretBytes(12);
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new GCMParameterSpec(TAG_LENGTH_BITS, iv));
|
||||
if (aad != null) {
|
||||
cipher.updateAAD(aad);
|
||||
}
|
||||
|
||||
byte[] cipherText = cipher.doFinal(requestData);
|
||||
byte[][] parts = ByteUtil.split(cipherText, cipherText.length - TAG_LENGTH_BYTES, TAG_LENGTH_BYTES);
|
||||
|
||||
byte[] mac = parts[1];
|
||||
byte[] data = parts[0];
|
||||
|
||||
return new AESEncryptedResult(iv, data, mac, aad);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
static class AESEncryptedResult {
|
||||
final byte[] iv;
|
||||
final byte[] data;
|
||||
final byte[] mac;
|
||||
final byte[] aad;
|
||||
|
||||
private AESEncryptedResult(byte[] iv, byte[] data, byte[] mac, byte[] aad) {
|
||||
this.iv = iv;
|
||||
this.data = data;
|
||||
this.mac = mac;
|
||||
this.aad = aad;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
import org.signal.libsignal.protocol.util.ByteUtil;
|
||||
import org.signal.core.util.CryptoUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||
import org.whispersystems.signalservice.internal.contacts.crypto.AESCipher.AESEncryptedResult;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.DiscoveryRequest;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.DiscoveryResponse;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.QueryEnvelope;
|
||||
import org.whispersystems.signalservice.internal.util.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ContactDiscoveryCipher {
|
||||
|
||||
private ContactDiscoveryCipher() {
|
||||
}
|
||||
|
||||
public static DiscoveryRequest createDiscoveryRequest(List<String> addressBook, Map<String, RemoteAttestation> remoteAttestations) {
|
||||
byte[] queryDataKey = Util.getSecretBytes(32);
|
||||
byte[] queryData = buildQueryData(addressBook);
|
||||
AESEncryptedResult encryptedQueryData = AESCipher.encrypt(queryDataKey, null, queryData);
|
||||
byte[] commitment = CryptoUtil.sha256(queryData);
|
||||
Map<String, QueryEnvelope> envelopes = new HashMap<>(remoteAttestations.size());
|
||||
|
||||
for (Map.Entry<String, RemoteAttestation> entry : remoteAttestations.entrySet()) {
|
||||
envelopes.put(entry.getKey(),
|
||||
buildQueryEnvelope(entry.getValue().getRequestId(),
|
||||
entry.getValue().getKeys().getClientKey(),
|
||||
queryDataKey));
|
||||
}
|
||||
|
||||
return new DiscoveryRequest(addressBook.size(),
|
||||
commitment,
|
||||
encryptedQueryData.iv,
|
||||
encryptedQueryData.data,
|
||||
encryptedQueryData.mac,
|
||||
envelopes);
|
||||
}
|
||||
|
||||
public static byte[] getDiscoveryResponseData(DiscoveryResponse response, Collection<RemoteAttestation> attestations) throws InvalidCiphertextException, IOException {
|
||||
for (RemoteAttestation attestation : attestations) {
|
||||
if (Arrays.equals(response.getRequestId(), attestation.getRequestId())) {
|
||||
return AESCipher.decrypt(attestation.getKeys().getServerKey(), response.getIv(), response.getData(), response.getMac());
|
||||
}
|
||||
}
|
||||
throw new NoMatchingRequestIdException();
|
||||
}
|
||||
|
||||
private static byte[] buildQueryData(List<String> addresses) {
|
||||
try {
|
||||
byte[] nonce = Util.getSecretBytes(32);
|
||||
ByteArrayOutputStream requestDataStream = new ByteArrayOutputStream();
|
||||
|
||||
requestDataStream.write(nonce);
|
||||
|
||||
for (String address : addresses) {
|
||||
requestDataStream.write(ByteUtil.longToByteArray(Long.parseLong(address)));
|
||||
}
|
||||
|
||||
return requestDataStream.toByteArray();
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static QueryEnvelope buildQueryEnvelope(byte[] requestId, byte[] clientKey, byte[] queryDataKey) {
|
||||
AESEncryptedResult result = AESCipher.encrypt(clientKey, requestId, queryDataKey);
|
||||
return new QueryEnvelope(requestId, result.iv, result.data, result.mac);
|
||||
}
|
||||
|
||||
static class NoMatchingRequestIdException extends IOException {
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.KeyBackupRequest;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.BackupRequest;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.BackupResponse;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.DeleteRequest;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.DeleteResponse;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.Request;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.Response;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.RestoreRequest;
|
||||
import org.whispersystems.signalservice.internal.keybackup.protos.RestoreResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okio.ByteString;
|
||||
|
||||
public final class KeyBackupCipher {
|
||||
|
||||
private KeyBackupCipher() {
|
||||
}
|
||||
|
||||
private static final long VALID_FROM_BUFFER_MS = TimeUnit.DAYS.toMillis(1);
|
||||
|
||||
public static KeyBackupRequest createKeyBackupRequest(byte[] kbsAccessKey,
|
||||
byte[] kbsData,
|
||||
TokenResponse token,
|
||||
RemoteAttestation remoteAttestation,
|
||||
byte[] serviceId,
|
||||
int tries)
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
BackupRequest backupRequest = new BackupRequest.Builder()
|
||||
.serviceId(ByteString.of(serviceId))
|
||||
.backupId(ByteString.of(token.getBackupId()))
|
||||
.token(ByteString.of(token.getToken()))
|
||||
.validFrom(getValidFromSeconds(now))
|
||||
.data_(ByteString.of(kbsData))
|
||||
.pin(ByteString.of(kbsAccessKey))
|
||||
.tries(tries)
|
||||
.build();
|
||||
|
||||
Request requestData = new Request.Builder().backup(backupRequest).build();
|
||||
|
||||
return createKeyBackupRequest(requestData, remoteAttestation, "backup");
|
||||
}
|
||||
|
||||
public static KeyBackupRequest createKeyRestoreRequest(byte[] kbsAccessKey,
|
||||
TokenResponse token,
|
||||
RemoteAttestation remoteAttestation,
|
||||
byte[] serviceId)
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
|
||||
RestoreRequest restoreRequest = new RestoreRequest.Builder()
|
||||
.serviceId(ByteString.of(serviceId))
|
||||
.backupId(ByteString.of(token.getBackupId()))
|
||||
.token(ByteString.of(token.getToken()))
|
||||
.validFrom(getValidFromSeconds(now))
|
||||
.pin(ByteString.of(kbsAccessKey))
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder().restore(restoreRequest).build();
|
||||
|
||||
return createKeyBackupRequest(request, remoteAttestation, "restore");
|
||||
}
|
||||
|
||||
public static KeyBackupRequest createKeyDeleteRequest(TokenResponse token,
|
||||
RemoteAttestation remoteAttestation,
|
||||
byte[] serviceId)
|
||||
{
|
||||
DeleteRequest deleteRequest = new DeleteRequest.Builder()
|
||||
.serviceId(ByteString.of(serviceId))
|
||||
.backupId(ByteString.of(token.getBackupId()))
|
||||
.build();
|
||||
|
||||
Request request = new Request.Builder().delete(deleteRequest).build();
|
||||
|
||||
return createKeyBackupRequest(request, remoteAttestation, "delete");
|
||||
}
|
||||
|
||||
public static BackupResponse getKeyBackupResponse(KeyBackupResponse response, RemoteAttestation remoteAttestation)
|
||||
throws InvalidCiphertextException, IOException
|
||||
{
|
||||
byte[] data = decryptData(response, remoteAttestation);
|
||||
|
||||
Response backupResponse = Response.ADAPTER.decode(data);
|
||||
|
||||
return backupResponse.backup;
|
||||
}
|
||||
|
||||
public static RestoreResponse getKeyRestoreResponse(KeyBackupResponse response, RemoteAttestation remoteAttestation)
|
||||
throws InvalidCiphertextException, IOException
|
||||
{
|
||||
byte[] data = decryptData(response, remoteAttestation);
|
||||
|
||||
return Response.ADAPTER.decode(data).restore;
|
||||
}
|
||||
|
||||
public static DeleteResponse getKeyDeleteResponseStatus(KeyBackupResponse response, RemoteAttestation remoteAttestation)
|
||||
throws InvalidCiphertextException, IOException
|
||||
{
|
||||
byte[] data = decryptData(response, remoteAttestation);
|
||||
|
||||
return DeleteResponse.ADAPTER.decode(data);
|
||||
}
|
||||
|
||||
private static KeyBackupRequest createKeyBackupRequest(Request requestData, RemoteAttestation remoteAttestation, String type) {
|
||||
byte[] clientKey = remoteAttestation.getKeys().getClientKey();
|
||||
byte[] aad = remoteAttestation.getRequestId();
|
||||
|
||||
AESCipher.AESEncryptedResult aesEncryptedResult = AESCipher.encrypt(clientKey, aad, requestData.encode());
|
||||
|
||||
return new KeyBackupRequest(aesEncryptedResult.aad, aesEncryptedResult.iv, aesEncryptedResult.data, aesEncryptedResult.mac, type);
|
||||
}
|
||||
|
||||
private static byte[] decryptData(KeyBackupResponse response, RemoteAttestation remoteAttestation) throws InvalidCiphertextException {
|
||||
return AESCipher.decrypt(remoteAttestation.getKeys().getServerKey(), response.getIv(), response.getData(), response.getMac());
|
||||
}
|
||||
|
||||
private static long getValidFromSeconds(long nowMs) {
|
||||
return TimeUnit.MILLISECONDS.toSeconds(nowMs - VALID_FROM_BUFFER_MS);
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class Quote {
|
||||
|
||||
private static final long SGX_FLAGS_INITTED = 0x0000_0000_0000_0001L;
|
||||
private static final long SGX_FLAGS_DEBUG = 0x0000_0000_0000_0002L;
|
||||
private static final long SGX_FLAGS_MODE64BIT = 0x0000_0000_0000_0004L;
|
||||
private static final long SGX_FLAGS_PROVISION_KEY = 0x0000_0000_0000_0004L;
|
||||
private static final long SGX_FLAGS_EINITTOKEN_KEY = 0x0000_0000_0000_0004L;
|
||||
private static final long SGX_FLAGS_RESERVED = 0xFFFF_FFFF_FFFF_FFC8L;
|
||||
private static final long SGX_XFRM_LEGACY = 0x0000_0000_0000_0003L;
|
||||
private static final long SGX_XFRM_AVX = 0x0000_0000_0000_0006L;
|
||||
private static final long SGX_XFRM_RESERVED = 0xFFFF_FFFF_FFFF_FFF8L;
|
||||
|
||||
private final int version;
|
||||
private final boolean isSigLinkable;
|
||||
private final long gid;
|
||||
private final int qeSvn;
|
||||
private final int pceSvn;
|
||||
private final byte[] basename = new byte[32];
|
||||
private final byte[] cpuSvn = new byte[16];
|
||||
private final long flags;
|
||||
private final long xfrm;
|
||||
private final byte[] mrenclave = new byte[32];
|
||||
private final byte[] mrsigner = new byte[32];
|
||||
private final int isvProdId;
|
||||
private final int isvSvn;
|
||||
private final byte[] reportData = new byte[64];
|
||||
private final byte[] signature;
|
||||
private final byte[] quoteBytes;
|
||||
|
||||
public Quote(byte[] quoteBytes) throws InvalidQuoteFormatException {
|
||||
this.quoteBytes = quoteBytes;
|
||||
|
||||
ByteBuffer quoteBuf = ByteBuffer.wrap(quoteBytes);
|
||||
quoteBuf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
this.version = quoteBuf.getShort(0) & 0xFFFF;
|
||||
if (!(version >= 1 && version <= 2)) {
|
||||
throw new InvalidQuoteFormatException("unknown_quote_version "+version);
|
||||
}
|
||||
|
||||
int sign_type = quoteBuf.getShort(2) & 0xFFFF;
|
||||
if ((sign_type & ~1) != 0) {
|
||||
throw new InvalidQuoteFormatException("unknown_quote_sign_type "+sign_type);
|
||||
}
|
||||
|
||||
this.isSigLinkable = sign_type == 1;
|
||||
this.gid = quoteBuf.getInt(4) & 0xFFFF_FFFF;
|
||||
this.qeSvn = quoteBuf.getShort(8) & 0xFFFF;
|
||||
|
||||
if (version > 1) {
|
||||
this.pceSvn = quoteBuf.getShort(10) & 0xFFFF;
|
||||
} else {
|
||||
readZero(quoteBuf, 10, 2);
|
||||
this.pceSvn = 0;
|
||||
}
|
||||
|
||||
readZero(quoteBuf, 12, 4); // xeid (reserved)
|
||||
read(quoteBuf, 16, basename);
|
||||
|
||||
//
|
||||
// report_body
|
||||
//
|
||||
|
||||
read(quoteBuf, 48, cpuSvn);
|
||||
readZero(quoteBuf, 64, 4); // misc_select (reserved)
|
||||
readZero(quoteBuf, 68, 28); // reserved1
|
||||
this.flags = quoteBuf.getLong(96);
|
||||
if ((flags & SGX_FLAGS_RESERVED ) != 0 ||
|
||||
(flags & SGX_FLAGS_INITTED ) == 0 ||
|
||||
(flags & SGX_FLAGS_MODE64BIT) == 0) {
|
||||
throw new InvalidQuoteFormatException("bad_quote_flags "+flags);
|
||||
}
|
||||
this.xfrm = quoteBuf.getLong(104);
|
||||
if ((xfrm & SGX_XFRM_RESERVED) != 0) {
|
||||
throw new InvalidQuoteFormatException("bad_quote_xfrm "+xfrm);
|
||||
}
|
||||
read(quoteBuf, 112, mrenclave);
|
||||
readZero(quoteBuf, 144, 32); // reserved2
|
||||
read(quoteBuf, 176, mrsigner);
|
||||
readZero(quoteBuf, 208, 96); // reserved3
|
||||
this.isvProdId = quoteBuf.getShort(304) & 0xFFFF;
|
||||
this.isvSvn = quoteBuf.getShort(306) & 0xFFFF;
|
||||
readZero(quoteBuf, 308, 60); // reserved4
|
||||
read(quoteBuf, 368, reportData);
|
||||
|
||||
// quote signature
|
||||
int sig_len = quoteBuf.getInt(432) & 0xFFFF_FFFF;
|
||||
if (sig_len != quoteBytes.length - 436) {
|
||||
throw new InvalidQuoteFormatException("bad_quote_sig_len "+sig_len);
|
||||
}
|
||||
this.signature = new byte[sig_len];
|
||||
read(quoteBuf, 436, signature);
|
||||
}
|
||||
|
||||
public byte[] getReportData() {
|
||||
return reportData;
|
||||
}
|
||||
|
||||
private void read(ByteBuffer quoteBuf, int pos, byte[] buf) {
|
||||
quoteBuf.position(pos);
|
||||
quoteBuf.get(buf);
|
||||
}
|
||||
|
||||
private void readZero(ByteBuffer quoteBuf, int pos, int count) {
|
||||
byte[] zeroBuf = new byte[count];
|
||||
read(quoteBuf, pos, zeroBuf);
|
||||
for (int zeroBufIdx = 0; zeroBufIdx < count; zeroBufIdx++) {
|
||||
if (zeroBuf[zeroBufIdx] != 0) {
|
||||
throw new IllegalArgumentException("quote_reserved_mismatch "+pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getQuoteBytes() {
|
||||
return quoteBytes;
|
||||
}
|
||||
|
||||
public byte[] getMrenclave() {
|
||||
return mrenclave;
|
||||
}
|
||||
|
||||
public boolean isDebugQuote() {
|
||||
return (flags & SGX_FLAGS_DEBUG) != 0;
|
||||
}
|
||||
|
||||
public static class InvalidQuoteFormatException extends Exception {
|
||||
public InvalidQuoteFormatException(String value) {
|
||||
super(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RemoteAttestation {
|
||||
|
||||
private final byte[] requestId;
|
||||
private final RemoteAttestationKeys keys;
|
||||
private final List<String> cookies;
|
||||
|
||||
public RemoteAttestation(byte[] requestId, RemoteAttestationKeys keys, List<String> cookies) {
|
||||
this.requestId = requestId;
|
||||
this.keys = keys;
|
||||
this.cookies = cookies;
|
||||
}
|
||||
|
||||
public byte[] getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public RemoteAttestationKeys getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
public List<String> getCookies() {
|
||||
return cookies;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
import org.signal.libsignal.protocol.util.ByteUtil;
|
||||
import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException;
|
||||
import org.whispersystems.signalservice.internal.contacts.entities.RemoteAttestationResponse;
|
||||
import org.whispersystems.signalservice.internal.util.Hex;
|
||||
import org.whispersystems.signalservice.internal.util.JsonUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Period;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public final class RemoteAttestationCipher {
|
||||
|
||||
private static final Set<String> ALLOWED_ADVISORIES = new HashSet<String>() {{
|
||||
add("INTEL-SA-00334");
|
||||
add("INTEL-SA-00615");
|
||||
}};
|
||||
|
||||
private RemoteAttestationCipher() {
|
||||
}
|
||||
|
||||
private static final Set<Long> SIGNATURE_BODY_VERSIONS = new HashSet<Long>() {{
|
||||
add(3L);
|
||||
add(4L);
|
||||
}};
|
||||
|
||||
public static byte[] getRequestId(RemoteAttestationKeys keys, RemoteAttestationResponse response) throws InvalidCiphertextException {
|
||||
return AESCipher.decrypt(keys.getServerKey(), response.getIv(), response.getCiphertext(), response.getTag());
|
||||
}
|
||||
|
||||
public static void verifyServerQuote(Quote quote, byte[] serverPublicStatic, String mrenclave)
|
||||
throws UnauthenticatedQuoteException
|
||||
{
|
||||
try {
|
||||
byte[] theirServerPublicStatic = new byte[serverPublicStatic.length];
|
||||
System.arraycopy(quote.getReportData(), 0, theirServerPublicStatic, 0, theirServerPublicStatic.length);
|
||||
|
||||
if (!MessageDigest.isEqual(theirServerPublicStatic, serverPublicStatic)) {
|
||||
throw new UnauthenticatedQuoteException("Response quote has unauthenticated report data!");
|
||||
}
|
||||
|
||||
if (!MessageDigest.isEqual(Hex.fromStringCondensed(mrenclave), quote.getMrenclave())) {
|
||||
throw new UnauthenticatedQuoteException("The response quote has the wrong mrenclave value in it: " + Hex.toStringCondensed(quote.getMrenclave()));
|
||||
}
|
||||
|
||||
if (quote.isDebugQuote()) {
|
||||
throw new UnauthenticatedQuoteException("Received quote for debuggable enclave");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new UnauthenticatedQuoteException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyIasSignature(KeyStore trustStore, String certificates, String signatureBody, String signature, Quote quote)
|
||||
throws SignatureException
|
||||
{
|
||||
if (certificates == null || certificates.isEmpty()) {
|
||||
throw new SignatureException("No certificates.");
|
||||
}
|
||||
|
||||
try {
|
||||
SigningCertificate signingCertificate = new SigningCertificate(certificates, trustStore);
|
||||
signingCertificate.verifySignature(signatureBody, signature);
|
||||
|
||||
SignatureBodyEntity signatureBodyEntity = JsonUtil.fromJson(signatureBody, SignatureBodyEntity.class);
|
||||
|
||||
if (!SIGNATURE_BODY_VERSIONS.contains(signatureBodyEntity.getVersion())) {
|
||||
throw new SignatureException("Unexpected signed quote version " + signatureBodyEntity.getVersion());
|
||||
}
|
||||
|
||||
if (!MessageDigest.isEqual(ByteUtil.trim(signatureBodyEntity.getIsvEnclaveQuoteBody(), 432), ByteUtil.trim(quote.getQuoteBytes(), 432))) {
|
||||
throw new SignatureException("Signed quote is not the same as RA quote: " + Hex.toStringCondensed(signatureBodyEntity.getIsvEnclaveQuoteBody()) + " vs " + Hex.toStringCondensed(quote.getQuoteBytes()));
|
||||
}
|
||||
|
||||
if (!hasValidStatus(signatureBodyEntity)) {
|
||||
throw new SignatureException("Quote status is: " + signatureBodyEntity.getIsvEnclaveQuoteStatus() + " and advisories are: " + Arrays.toString(signatureBodyEntity.getAdvisoryIds()));
|
||||
}
|
||||
|
||||
if (Instant.from(ZonedDateTime.of(LocalDateTime.from(DateTimeFormatter.ofPattern("yyy-MM-dd'T'HH:mm:ss.SSSSSS").parse(signatureBodyEntity.getTimestamp())), ZoneId.of("UTC")))
|
||||
.plus(Period.ofDays(1))
|
||||
.isBefore(Instant.now()))
|
||||
{
|
||||
throw new SignatureException("Signature is expired");
|
||||
}
|
||||
|
||||
} catch (CertificateException | CertPathValidatorException | IOException e) {
|
||||
throw new SignatureException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasValidStatus(SignatureBodyEntity entity) {
|
||||
if ("OK".equals(entity.getIsvEnclaveQuoteStatus())) {
|
||||
return true;
|
||||
} else if ("SW_HARDENING_NEEDED".equals(entity.getIsvEnclaveQuoteStatus())) {
|
||||
return Arrays.stream(entity.getAdvisoryIds()).allMatch(ALLOWED_ADVISORIES::contains);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
|
||||
import org.signal.libsignal.protocol.InvalidKeyException;
|
||||
import org.signal.libsignal.protocol.ecc.Curve;
|
||||
import org.signal.libsignal.protocol.ecc.ECKeyPair;
|
||||
import org.signal.libsignal.protocol.ecc.ECPublicKey;
|
||||
import org.signal.libsignal.protocol.kdf.HKDF;
|
||||
import org.signal.libsignal.protocol.util.ByteUtil;
|
||||
|
||||
public class RemoteAttestationKeys {
|
||||
|
||||
private final byte[] clientKey = new byte[32];
|
||||
private final byte[] serverKey = new byte[32];
|
||||
|
||||
public RemoteAttestationKeys(ECKeyPair keyPair, byte[] serverPublicEphemeral, byte[] serverPublicStatic) throws InvalidKeyException {
|
||||
byte[] ephemeralToEphemeral = Curve.calculateAgreement(ECPublicKey.fromPublicKeyBytes(serverPublicEphemeral), keyPair.getPrivateKey());
|
||||
byte[] ephemeralToStatic = Curve.calculateAgreement(ECPublicKey.fromPublicKeyBytes(serverPublicStatic), keyPair.getPrivateKey());
|
||||
|
||||
byte[] masterSecret = ByteUtil.combine(ephemeralToEphemeral, ephemeralToStatic );
|
||||
byte[] publicKeys = ByteUtil.combine(keyPair.getPublicKey().getPublicKeyBytes(), serverPublicEphemeral, serverPublicStatic);
|
||||
|
||||
byte[] keys = HKDF.deriveSecrets(masterSecret, publicKeys, new byte[0], clientKey.length + serverKey.length);
|
||||
|
||||
System.arraycopy(keys, 0, clientKey, 0, clientKey.length);
|
||||
System.arraycopy(keys, clientKey.length, serverKey, 0, serverKey.length);
|
||||
}
|
||||
|
||||
public byte[] getClientKey() {
|
||||
return clientKey;
|
||||
}
|
||||
|
||||
public byte[] getServerKey() {
|
||||
return serverKey;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
import org.signal.core.util.Base64;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.CertPathValidator;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.PKIXParameters;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class SigningCertificate {
|
||||
|
||||
private final CertPath path;
|
||||
|
||||
public SigningCertificate(String certificateChain, KeyStore trustStore)
|
||||
throws CertificateException, CertPathValidatorException
|
||||
{
|
||||
try {
|
||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
||||
Collection<X509Certificate> certificatesCollection = (Collection<X509Certificate>) certificateFactory.generateCertificates(new ByteArrayInputStream(certificateChain.getBytes()));
|
||||
List<X509Certificate> certificates = new LinkedList<>(certificatesCollection);
|
||||
PKIXParameters pkixParameters = new PKIXParameters(trustStore);
|
||||
CertPathValidator validator = CertPathValidator.getInstance("PKIX");
|
||||
|
||||
if (certificates.isEmpty()) {
|
||||
throw new CertificateException("No certificates available! Badly-formatted cert chain?");
|
||||
}
|
||||
|
||||
this.path = certificateFactory.generateCertPath(certificates);
|
||||
|
||||
pkixParameters.setRevocationEnabled(false);
|
||||
validator.validate(path, pkixParameters);
|
||||
verifyDistinguishedName(path);
|
||||
} catch (KeyStoreException | InvalidAlgorithmParameterException | NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void verifySignature(String body, String encodedSignature)
|
||||
throws SignatureException
|
||||
{
|
||||
try {
|
||||
Signature signature = Signature.getInstance("SHA256withRSA");
|
||||
signature.initVerify(path.getCertificates().get(0));
|
||||
signature.update(body.getBytes());
|
||||
if (!signature.verify(Base64.decode(encodedSignature.getBytes()))) {
|
||||
throw new SignatureException("Signature verification failed.");
|
||||
}
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyDistinguishedName(CertPath path) throws CertificateException {
|
||||
X509Certificate leaf = (X509Certificate) path.getCertificates().get(0);
|
||||
String distinguishedName = leaf.getSubjectX500Principal().getName();
|
||||
|
||||
if (!"CN=Intel SGX Attestation Report Signing,O=Intel Corporation,L=Santa Clara,ST=CA,C=US".equals(distinguishedName)) {
|
||||
throw new CertificateException("Bad DN: " + distinguishedName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
|
||||
public class UnauthenticatedQuoteException extends Exception {
|
||||
public UnauthenticatedQuoteException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public UnauthenticatedQuoteException(Exception nested) {
|
||||
super(nested);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.contacts.crypto;
|
||||
|
||||
|
||||
public class UnauthenticatedResponseException extends Exception {
|
||||
public UnauthenticatedResponseException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
public UnauthenticatedResponseException(String s) {
|
||||
super(s);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014-2016 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
|
||||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ContactTokenList {
|
||||
|
||||
private List<String> contacts;
|
||||
|
||||
public ContactTokenList(List<String> contacts) {
|
||||
this.contacts = contacts;
|
||||
}
|
||||
|
||||
public ContactTokenList() {}
|
||||
|
||||
public List<String> getContacts() {
|
||||
return contacts;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SignalServiceEnvelopeEntityList {
|
||||
|
||||
private List<SignalServiceEnvelopeEntity> messages;
|
||||
|
||||
public SignalServiceEnvelopeEntityList() {}
|
||||
|
||||
public List<SignalServiceEnvelopeEntity> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public final class SignalServiceMessagesResult {
|
||||
private final List<SignalServiceEnvelopeEntity> envelopes;
|
||||
private final long serverDeliveredTimestamp;
|
||||
|
||||
SignalServiceMessagesResult(List<SignalServiceEnvelopeEntity> envelopes, long serverDeliveredTimestamp) {
|
||||
this.envelopes = envelopes;
|
||||
this.serverDeliveredTimestamp = serverDeliveredTimestamp;
|
||||
}
|
||||
|
||||
public List<SignalServiceEnvelopeEntity> getEnvelopes() {
|
||||
return envelopes;
|
||||
}
|
||||
|
||||
public long getServerDeliveredTimestamp() {
|
||||
return serverDeliveredTimestamp;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Exception that indicates that the data message contains something that is not supported by this
|
||||
* version of the application. Subclasses provide more specific information about what data was
|
||||
* found that is not supported.
|
||||
*/
|
||||
public abstract class UnsupportedDataMessageException extends Exception {
|
||||
|
||||
private final String sender;
|
||||
private final int senderDevice;
|
||||
private final Optional<SignalServiceGroupV2> group;
|
||||
|
||||
protected UnsupportedDataMessageException(String message,
|
||||
String sender,
|
||||
int senderDevice,
|
||||
Optional<SignalServiceGroupV2> group)
|
||||
{
|
||||
super(message);
|
||||
this.sender = sender;
|
||||
this.senderDevice = senderDevice;
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public String getSender() {
|
||||
return sender;
|
||||
}
|
||||
|
||||
public int getSenderDevice() {
|
||||
return senderDevice;
|
||||
}
|
||||
|
||||
public Optional<SignalServiceGroupV2> getGroup() {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.whispersystems.signalservice.internal.push;
|
||||
|
||||
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Exception that indicates that the data message has a higher required protocol version than the
|
||||
* current client is capable of interpreting.
|
||||
*/
|
||||
public final class UnsupportedDataMessageProtocolVersionException extends UnsupportedDataMessageException {
|
||||
private final int requiredVersion;
|
||||
|
||||
public UnsupportedDataMessageProtocolVersionException(int currentVersion,
|
||||
int requiredVersion,
|
||||
String sender,
|
||||
int senderDevice,
|
||||
Optional<SignalServiceGroupV2> group) {
|
||||
super("Required version: " + requiredVersion + ", Our version: " + currentVersion, sender, senderDevice, group);
|
||||
this.requiredVersion = requiredVersion;
|
||||
}
|
||||
|
||||
public int getRequiredVersion() {
|
||||
return requiredVersion;
|
||||
}
|
||||
}
|
||||
@@ -21,23 +21,6 @@ message SignalServiceContentProto {
|
||||
}
|
||||
}
|
||||
|
||||
message SignalServiceEnvelopeProto {
|
||||
optional int32 type = 1;
|
||||
optional string sourceServiceId = 2;
|
||||
reserved /*sourceE164*/ 3;
|
||||
optional int32 deviceId = 4;
|
||||
reserved /*legacyMessage*/ 5;
|
||||
optional bytes content = 6;
|
||||
optional int64 timestamp = 7;
|
||||
optional int64 serverReceivedTimestamp = 8;
|
||||
optional int64 serverDeliveredTimestamp = 9;
|
||||
optional string serverGuid = 10;
|
||||
optional string destinationServiceId = 11;
|
||||
optional bool urgent = 12 [default = true];
|
||||
optional bool story = 13;
|
||||
optional bytes reportingToken = 14;
|
||||
}
|
||||
|
||||
message MetadataProto {
|
||||
optional AddressProto address = 1;
|
||||
optional int32 senderDevice = 2;
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2019 Open Whisper Systems
|
||||
*
|
||||
* Licensed according to the LICENSE file in this repository.
|
||||
*/
|
||||
syntax = "proto2";
|
||||
|
||||
package textsecure;
|
||||
|
||||
option java_package = "org.whispersystems.signalservice.internal.keybackup.protos";
|
||||
option java_multiple_files = true;
|
||||
|
||||
message Request {
|
||||
optional BackupRequest backup = 1;
|
||||
optional RestoreRequest restore = 2;
|
||||
optional DeleteRequest delete = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
optional BackupResponse backup = 1;
|
||||
optional RestoreResponse restore = 2;
|
||||
optional DeleteResponse delete = 3;
|
||||
}
|
||||
|
||||
message BackupRequest {
|
||||
optional bytes serviceId = 1;
|
||||
optional bytes backupId = 2;
|
||||
optional bytes token = 3;
|
||||
optional uint64 validFrom = 4;
|
||||
optional bytes data = 5;
|
||||
optional bytes pin = 6;
|
||||
optional uint32 tries = 7;
|
||||
}
|
||||
|
||||
message BackupResponse {
|
||||
enum Status {
|
||||
OK = 1;
|
||||
ALREADY_EXISTS = 2;
|
||||
NOT_YET_VALID = 3;
|
||||
}
|
||||
|
||||
optional Status status = 1;
|
||||
optional bytes token = 2;
|
||||
}
|
||||
|
||||
message RestoreRequest {
|
||||
optional bytes serviceId = 1;
|
||||
optional bytes backupId = 2;
|
||||
optional bytes token = 3;
|
||||
optional uint64 validFrom = 4;
|
||||
optional bytes pin = 5;
|
||||
}
|
||||
|
||||
message RestoreResponse {
|
||||
enum Status {
|
||||
OK = 1;
|
||||
TOKEN_MISMATCH = 2;
|
||||
NOT_YET_VALID = 3;
|
||||
MISSING = 4;
|
||||
PIN_MISMATCH = 5;
|
||||
}
|
||||
|
||||
optional Status status = 1;
|
||||
optional bytes token = 2;
|
||||
optional bytes data = 3;
|
||||
optional uint32 tries = 4;
|
||||
}
|
||||
|
||||
message DeleteRequest {
|
||||
optional bytes serviceId = 1;
|
||||
optional bytes backupId = 2;
|
||||
}
|
||||
|
||||
message DeleteResponse {
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
syntax = "proto3";
|
||||
|
||||
package signalservice;
|
||||
|
||||
option java_package = "org.whispersystems.signalservice.internal.websocket";
|
||||
option java_outer_classname = "ShadowingStats";
|
||||
|
||||
message Snapshot {
|
||||
int32 requestsCompared = 1;
|
||||
int32 failures = 2;
|
||||
int32 badStatuses = 3;
|
||||
int32 reconnects = 4;
|
||||
int64 lastNotified = 5;
|
||||
}
|
||||
Reference in New Issue
Block a user