diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f71dc6a5a6..ab79d38ed4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -70,6 +70,8 @@ wire { protoPath { srcDir("${project.rootDir}/libsignal-service/src/main/protowire") } + // Handled by libsignal + prune("signalservice.DecryptionErrorMessage") } ktlint { diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InternalValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InternalValues.kt index 7ac47a62ee..f8822a2c5c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InternalValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/InternalValues.kt @@ -176,8 +176,6 @@ class InternalValues internal constructor(store: KeyValueStore) : SignalStoreVal var useConversationItemV2Media by booleanValue(CONVERSATION_ITEM_V2_MEDIA, false).defaultForExternalUsers() - var webSocketShadowingStats by nullableBlobValue(WEB_SOCKET_SHADOWING_STATS, null).defaultForExternalUsers() - var forceSsre2Capability by booleanValue("internal.force_ssre2_capability", false).defaultForExternalUsers() private fun SignalStoreValueDelegate.defaultForExternalUsers(): SignalStoreValueDelegate { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SvrPinData.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SvrPinData.java deleted file mode 100644 index a3b7e25bef..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SvrPinData.java +++ /dev/null @@ -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(); - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/TokenException.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/TokenException.java deleted file mode 100644 index baea0c0cb8..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/TokenException.java +++ /dev/null @@ -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; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/groupsv2/UuidProfileKey.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/groupsv2/UuidProfileKey.java deleted file mode 100644 index 0c49ecbac6..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/groupsv2/UuidProfileKey.java +++ /dev/null @@ -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; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceGroup.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceGroup.java deleted file mode 100644 index 010bb204f8..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceGroup.java +++ /dev/null @@ -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 name; - private final Optional> members; - private final Optional 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 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 getName() { - return name; - } - - public Optional> getMembers() { - return members; - } - - public Optional 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 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 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); - } - - } - -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServicePniSignatureMessage.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServicePniSignatureMessage.java deleted file mode 100644 index c2aeb67358..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServicePniSignatureMessage.java +++ /dev/null @@ -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; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceGroup.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceGroup.java deleted file mode 100644 index 21013cf624..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceGroup.java +++ /dev/null @@ -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 name; - private final List members; - private final Optional avatar; - private final boolean active; - private final Optional expirationTimer; - private final Optional color; - private final boolean blocked; - private final Optional inboxPosition; - private final boolean archived; - - public DeviceGroup(byte[] id, - Optional name, - List members, - Optional avatar, - boolean active, - Optional expirationTimer, - Optional color, - boolean blocked, - Optional 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 getAvatar() { - return avatar; - } - - public Optional getName() { - return name; - } - - public byte[] getId() { - return id; - } - - public List getMembers() { - return members; - } - - public boolean isActive() { - return active; - } - - public Optional getExpirationTimer() { - return expirationTimer; - } - - public Optional getColor() { - return color; - } - - public boolean isBlocked() { - return blocked; - } - - public Optional getInboxPosition() { - return inboxPosition; - } - - public boolean isArchived() { - return archived; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/Svr2PinHasher.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/Svr2PinHasher.kt deleted file mode 100644 index dbc3c5687e..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/Svr2PinHasher.kt +++ /dev/null @@ -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) - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/Svr2Socket.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/Svr2Socket.kt index e728783bdf..ce36148d2e 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/Svr2Socket.kt +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/Svr2Socket.kt @@ -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 } diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/AESCipher.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/AESCipher.java deleted file mode 100644 index 0180e6d7d9..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/AESCipher.java +++ /dev/null @@ -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; - } - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/ContactDiscoveryCipher.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/ContactDiscoveryCipher.java deleted file mode 100644 index 46d42502c8..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/ContactDiscoveryCipher.java +++ /dev/null @@ -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 addressBook, Map remoteAttestations) { - byte[] queryDataKey = Util.getSecretBytes(32); - byte[] queryData = buildQueryData(addressBook); - AESEncryptedResult encryptedQueryData = AESCipher.encrypt(queryDataKey, null, queryData); - byte[] commitment = CryptoUtil.sha256(queryData); - Map envelopes = new HashMap<>(remoteAttestations.size()); - - for (Map.Entry 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 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 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 { - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/KeyBackupCipher.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/KeyBackupCipher.java deleted file mode 100644 index 0a5f2c81c2..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/KeyBackupCipher.java +++ /dev/null @@ -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); - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/Quote.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/Quote.java deleted file mode 100644 index 7337ff2fc1..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/Quote.java +++ /dev/null @@ -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); - } - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestation.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestation.java deleted file mode 100644 index 62ad1cfdf1..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestation.java +++ /dev/null @@ -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 cookies; - - public RemoteAttestation(byte[] requestId, RemoteAttestationKeys keys, List cookies) { - this.requestId = requestId; - this.keys = keys; - this.cookies = cookies; - } - - public byte[] getRequestId() { - return requestId; - } - - public RemoteAttestationKeys getKeys() { - return keys; - } - - public List getCookies() { - return cookies; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationCipher.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationCipher.java deleted file mode 100644 index d6e0c9f847..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationCipher.java +++ /dev/null @@ -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 ALLOWED_ADVISORIES = new HashSet() {{ - add("INTEL-SA-00334"); - add("INTEL-SA-00615"); - }}; - - private RemoteAttestationCipher() { - } - - private static final Set SIGNATURE_BODY_VERSIONS = new HashSet() {{ - 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; - } - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationKeys.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationKeys.java deleted file mode 100644 index 5566728923..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationKeys.java +++ /dev/null @@ -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; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java deleted file mode 100644 index 48bd02f6d7..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SigningCertificate.java +++ /dev/null @@ -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 certificatesCollection = (Collection) certificateFactory.generateCertificates(new ByteArrayInputStream(certificateChain.getBytes())); - List 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); - } - } - -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/UnauthenticatedQuoteException.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/UnauthenticatedQuoteException.java deleted file mode 100644 index f0aceb643b..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/UnauthenticatedQuoteException.java +++ /dev/null @@ -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); - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/UnauthenticatedResponseException.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/UnauthenticatedResponseException.java deleted file mode 100644 index ca36b460b3..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/UnauthenticatedResponseException.java +++ /dev/null @@ -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); - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ContactTokenList.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ContactTokenList.java deleted file mode 100644 index 8a50c49dc9..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/ContactTokenList.java +++ /dev/null @@ -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 contacts; - - public ContactTokenList(List contacts) { - this.contacts = contacts; - } - - public ContactTokenList() {} - - public List getContacts() { - return contacts; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceEnvelopeEntityList.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceEnvelopeEntityList.java deleted file mode 100644 index 276591ced2..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceEnvelopeEntityList.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.whispersystems.signalservice.internal.push; - -import java.util.List; - -public class SignalServiceEnvelopeEntityList { - - private List messages; - - public SignalServiceEnvelopeEntityList() {} - - public List getMessages() { - return messages; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceMessagesResult.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceMessagesResult.java deleted file mode 100644 index 089a08c9a8..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/SignalServiceMessagesResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.whispersystems.signalservice.internal.push; - -import java.util.List; - -public final class SignalServiceMessagesResult { - private final List envelopes; - private final long serverDeliveredTimestamp; - - SignalServiceMessagesResult(List envelopes, long serverDeliveredTimestamp) { - this.envelopes = envelopes; - this.serverDeliveredTimestamp = serverDeliveredTimestamp; - } - - public List getEnvelopes() { - return envelopes; - } - - public long getServerDeliveredTimestamp() { - return serverDeliveredTimestamp; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageException.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageException.java deleted file mode 100644 index e3b5ec83f8..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageException.java +++ /dev/null @@ -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 group; - - protected UnsupportedDataMessageException(String message, - String sender, - int senderDevice, - Optional group) - { - super(message); - this.sender = sender; - this.senderDevice = senderDevice; - this.group = group; - } - - public String getSender() { - return sender; - } - - public int getSenderDevice() { - return senderDevice; - } - - public Optional getGroup() { - return group; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageProtocolVersionException.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageProtocolVersionException.java deleted file mode 100644 index 402eb960d7..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/UnsupportedDataMessageProtocolVersionException.java +++ /dev/null @@ -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 group) { - super("Required version: " + requiredVersion + ", Our version: " + currentVersion, sender, senderDevice, group); - this.requiredVersion = requiredVersion; - } - - public int getRequiredVersion() { - return requiredVersion; - } -} diff --git a/libsignal-service/src/main/protowire/InternalSerialization.proto b/libsignal-service/src/main/protowire/InternalSerialization.proto index 7138f129e7..7b30654de9 100644 --- a/libsignal-service/src/main/protowire/InternalSerialization.proto +++ b/libsignal-service/src/main/protowire/InternalSerialization.proto @@ -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; diff --git a/libsignal-service/src/main/protowire/KeyBackupService.proto b/libsignal-service/src/main/protowire/KeyBackupService.proto deleted file mode 100644 index 4f61da13d4..0000000000 --- a/libsignal-service/src/main/protowire/KeyBackupService.proto +++ /dev/null @@ -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 { -} diff --git a/libsignal-service/src/main/protowire/ShadowingStats.proto b/libsignal-service/src/main/protowire/ShadowingStats.proto deleted file mode 100644 index 3d62d8510a..0000000000 --- a/libsignal-service/src/main/protowire/ShadowingStats.proto +++ /dev/null @@ -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; -} diff --git a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java b/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java deleted file mode 100644 index 982ab80e24..0000000000 --- a/libsignal-service/src/test/java/org/whispersystems/signalservice/api/crypto/SigningCertificateTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.whispersystems.signalservice.api.crypto; - -import org.conscrypt.Conscrypt; -import org.junit.Test; -import org.whispersystems.signalservice.internal.contacts.crypto.SigningCertificate; -import org.signal.core.util.Base64; - -import java.io.IOException; -import java.net.URLDecoder; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.Security; -import java.security.SignatureException; -import java.security.cert.CertPathValidatorException; -import java.security.cert.CertificateException; - -import static org.junit.Assert.assertThrows; - -public class SigningCertificateTest { - - static { - // https://github.com/google/conscrypt/issues/1034 - if (!System.getProperty("os.arch").equals("aarch64")) { - Security.insertProviderAt(Conscrypt.newProvider(), 1); - } - } - - @Test - public void testGoodSignature() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException, CertPathValidatorException, SignatureException { - String certificateChain = URLDecoder.decode("-----BEGIN%20CERTIFICATE-----%0AMIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV%0ABAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV%0ABAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0%0AYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIw%0AMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1Nh%0AbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwk%0ASW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG%0A9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA%2Bt%0AbeCTUR106AL1ENcWA4FX3K%2BE9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtId%0Acv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuv%0ALUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV%2BW9tOhA%0AImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt%2B%2BqO/6%2BKAXJuKwZqjRlEtSEz8%0AgZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGh%0AMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN%2Bs1fDuHAVE8MA4GA1UdDwEB/wQEAwIG%0AwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVk%0Ac2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJl%0AcG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4r%0ARq%2BZKE%2B7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9%0AlpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYv%0AWLrtXXfFBSSPD4Afn7%2B3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUd%0AZseZCcaZZZn65tdqee8UXZlDvx0%2BNdO0LR%2B5pFy%2BjuM0wWbu59MvzcmTXbjsi7HY%0A6zd53Yq5K244fwFHRQ8eOB0IWB%2B4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW7%0A2uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN%2BKwPbpA39%2BxOsStjhP9N1Y1a2%0AtQAVo%2ByVgLgV2Hws73Fc0o3wC78qPEA%2Bv2aRs/Be3ZFDgDyghc/1fgU%2B7C%2BP6kbq%0Ad4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA%3D%3D%0A-----END%20CERTIFICATE-----%0A-----BEGIN%20CERTIFICATE-----%0AMIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV%0ABAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV%0ABAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0%0AYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy%0AMzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL%0AU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD%0ADCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G%0ACSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR%2BtXc8u1EtJzLA10Feu1Wg%2Bp7e%0ALmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh%0ArgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT%0AL/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe%0ANpEJUmg4ktal4qgIAxk%2BQHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ%0AbyinkNndn%2BBgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H%0AafuVeLHcDsRp6hol4P%2BZFIhu8mmbI1u0hH3W/0C2BuYXB5PC%2B5izFFh/nP0lc2Lf%0A6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM%0ARoOaX4AS%2B909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX%0AMFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50%0AL0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW%0ABBR4Q3t2pn680K9%2BQjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9%2BQjfr%0ANXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq%0AhkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir%0AIEqucRiJSSx%2BHjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi%2BripMtPZ%0AsFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi%0AzLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra%0AUd4APK0wZTGtfPXU7w%2BIBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA%0A152Sq049ESDz%2B1rRGc2NVEqh1KaGXmtXvqxXcTB%2BLjy5Bw2ke0v8iGngFBPqCTVB%0A3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5%2BxmBc388v9Dm21HGfcC8O%0ADD%2BgT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R%2BmJTLwPXVMrv%0ADaVzWh5aiEx%2BidkSGMnX%0A-----END%20CERTIFICATE-----%0A"); - String signature = "Kn2Ya2T039qvEWIzIQeSksNyyCQIkcVjciClcp3a6C766dJANXxLLIn6CfyvUZddMtePrTOLpC2e5QTQxB4RwtWmFfr7nxRdFUtA3dH2DAQL5DqqlmPv46ZWSPfiiOXUsu8vNgX3Z4Znt4Q+dIPIquNPY8ZmiAcpKR7n2K3QtabgOnJ2EyngabY3LMQTtriXbZjpl53ynhVhV1rciMdvMaTz4DUYt7gKi+KeNd3CBFSev+eTgYPC3em96J/3bfVR+wC5m3JGbIBCrwAsbO05JkiNIMck3s+p4d/hwiABR75EplxaWmGgIm6VvUKtGhdJ/cNrmF0nxMX6Vi6N2WaLTA=="; - String signatureBody = "{\"id\":\"287419896494669543891634765983074535548\",\"timestamp\":\"2019-03-11T20:01:21.658293\",\"version\":3,\"isvEnclaveQuoteStatus\":\"OK\",\"isvEnclaveQuoteBody\":\"AgAAADILAAAIAAcAAAAAAPiLWcRSSA3shraxepsGV9qF4zYUPJgE42ZZZXS2G9zaBQUCBP//AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAHAAAAAAAAAM1s/DQpN7I7G907v5chqlYVrJ/1CnXFUn1EHNMnaCbJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADrzm117Qj8NlEllyDkV4Pae4UgsPjgVXtAA5UsG90gVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHgz6GaO6bkxfPLBYcR5rEf9Itrt81OEanXteSMcd/BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}"; - - KeyStore keyStore = KeyStore.getInstance("JKS"); - keyStore.load(getClass().getResourceAsStream("/ias.jks"), "whisper".toCharArray()); - - SigningCertificate certificate = new SigningCertificate(certificateChain, keyStore); - - certificate.verifySignature(signatureBody, signature); - } - - @Test - public void testBadSignature() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException, CertPathValidatorException, SignatureException { - String certificateChain = URLDecoder.decode("-----BEGIN%20CERTIFICATE-----%0AMIIEoTCCAwmgAwIBAgIJANEHdl0yo7CWMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV%0ABAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV%0ABAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0%0AYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwHhcNMTYxMTIyMDkzNjU4WhcNMjYxMTIw%0AMDkzNjU4WjB7MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFDASBgNVBAcMC1Nh%0AbnRhIENsYXJhMRowGAYDVQQKDBFJbnRlbCBDb3Jwb3JhdGlvbjEtMCsGA1UEAwwk%0ASW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG%0A9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqXot4OZuphR8nudFrAFiaGxxkgma/Es/BA%2Bt%0AbeCTUR106AL1ENcWA4FX3K%2BE9BBL0/7X5rj5nIgX/R/1ubhkKWw9gfqPG3KeAtId%0Acv/uTO1yXv50vqaPvE1CRChvzdS/ZEBqQ5oVvLTPZ3VEicQjlytKgN9cLnxbwtuv%0ALUK7eyRPfJW/ksddOzP8VBBniolYnRCD2jrMRZ8nBM2ZWYwnXnwYeOAHV%2BW9tOhA%0AImwRwKF/95yAsVwd21ryHMJBcGH70qLagZ7Ttyt%2B%2BqO/6%2BKAXJuKwZqjRlEtSEz8%0AgZQeFfVYgcwSfo96oSMAzVr7V0L6HSDLRnpb6xxmbPdqNol4tQIDAQABo4GkMIGh%0AMB8GA1UdIwQYMBaAFHhDe3amfrzQr35CN%2Bs1fDuHAVE8MA4GA1UdDwEB/wQEAwIG%0AwDAMBgNVHRMBAf8EAjAAMGAGA1UdHwRZMFcwVaBToFGGT2h0dHA6Ly90cnVzdGVk%0Ac2VydmljZXMuaW50ZWwuY29tL2NvbnRlbnQvQ1JML1NHWC9BdHRlc3RhdGlvblJl%0AcG9ydFNpZ25pbmdDQS5jcmwwDQYJKoZIhvcNAQELBQADggGBAGcIthtcK9IVRz4r%0ARq%2BZKE%2B7k50/OxUsmW8aavOzKb0iCx07YQ9rzi5nU73tME2yGRLzhSViFs/LpFa9%0AlpQL6JL1aQwmDR74TxYGBAIi5f4I5TJoCCEqRHz91kpG6Uvyn2tLmnIdJbPE4vYv%0AWLrtXXfFBSSPD4Afn7%2B3/XUggAlc7oCTizOfbbtOFlYA4g5KcYgS1J2ZAeMQqbUd%0AZseZCcaZZZn65tdqee8UXZlDvx0%2BNdO0LR%2B5pFy%2BjuM0wWbu59MvzcmTXbjsi7HY%0A6zd53Yq5K244fwFHRQ8eOB0IWB%2B4PfM7FeAApZvlfqlKOlLcZL2uyVmzRkyR5yW7%0A2uo9mehX44CiPJ2fse9Y6eQtcfEhMPkmHXI01sN%2BKwPbpA39%2BxOsStjhP9N1Y1a2%0AtQAVo%2ByVgLgV2Hws73Fc0o3wC78qPEA%2Bv2aRs/Be3ZFDgDyghc/1fgU%2B7C%2BP6kbq%0Ad4poyb6IW8KCJbxfMJvkordNOgOUUxndPHEi/tb/U7uLjLOgPA%3D%3D%0A-----END%20CERTIFICATE-----%0A-----BEGIN%20CERTIFICATE-----%0AMIIFSzCCA7OgAwIBAgIJANEHdl0yo7CUMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNV%0ABAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExGjAYBgNV%0ABAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQDDCdJbnRlbCBTR1ggQXR0ZXN0%0AYXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwIBcNMTYxMTE0MTUzNzMxWhgPMjA0OTEy%0AMzEyMzU5NTlaMH4xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwL%0AU2FudGEgQ2xhcmExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0aW9uMTAwLgYDVQQD%0ADCdJbnRlbCBTR1ggQXR0ZXN0YXRpb24gUmVwb3J0IFNpZ25pbmcgQ0EwggGiMA0G%0ACSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCfPGR%2BtXc8u1EtJzLA10Feu1Wg%2Bp7e%0ALmSRmeaCHbkQ1TF3Nwl3RmpqXkeGzNLd69QUnWovYyVSndEMyYc3sHecGgfinEeh%0ArgBJSEdsSJ9FpaFdesjsxqzGRa20PYdnnfWcCTvFoulpbFR4VBuXnnVLVzkUvlXT%0AL/TAnd8nIZk0zZkFJ7P5LtePvykkar7LcSQO85wtcQe0R1Raf/sQ6wYKaKmFgCGe%0ANpEJUmg4ktal4qgIAxk%2BQHUxQE42sxViN5mqglB0QJdUot/o9a/V/mMeH8KvOAiQ%0AbyinkNndn%2BBgk5sSV5DFgF0DffVqmVMblt5p3jPtImzBIH0QQrXJq39AT8cRwP5H%0AafuVeLHcDsRp6hol4P%2BZFIhu8mmbI1u0hH3W/0C2BuYXB5PC%2B5izFFh/nP0lc2Lf%0A6rELO9LZdnOhpL1ExFOq9H/B8tPQ84T3Sgb4nAifDabNt/zu6MmCGo5U8lwEFtGM%0ARoOaX4AS%2B909x00lYnmtwsDVWv9vBiJCXRsCAwEAAaOByTCBxjBgBgNVHR8EWTBX%0AMFWgU6BRhk9odHRwOi8vdHJ1c3RlZHNlcnZpY2VzLmludGVsLmNvbS9jb250ZW50%0AL0NSTC9TR1gvQXR0ZXN0YXRpb25SZXBvcnRTaWduaW5nQ0EuY3JsMB0GA1UdDgQW%0ABBR4Q3t2pn680K9%2BQjfrNXw7hwFRPDAfBgNVHSMEGDAWgBR4Q3t2pn680K9%2BQjfr%0ANXw7hwFRPDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADANBgkq%0AhkiG9w0BAQsFAAOCAYEAeF8tYMXICvQqeXYQITkV2oLJsp6J4JAqJabHWxYJHGir%0AIEqucRiJSSx%2BHjIJEUVaj8E0QjEud6Y5lNmXlcjqRXaCPOqK0eGRz6hi%2BripMtPZ%0AsFNaBwLQVV905SDjAzDzNIDnrcnXyB4gcDFCvwDFKKgLRjOB/WAqgscDUoGq5ZVi%0AzLUzTqiQPmULAQaB9c6Oti6snEFJiCQ67JLyW/E83/frzCmO5Ru6WjU4tmsmy8Ra%0AUd4APK0wZTGtfPXU7w%2BIBdG5Ez0kE1qzxGQaL4gINJ1zMyleDnbuS8UicjJijvqA%0A152Sq049ESDz%2B1rRGc2NVEqh1KaGXmtXvqxXcTB%2BLjy5Bw2ke0v8iGngFBPqCTVB%0A3op5KBG3RjbF6RRSzwzuWfL7QErNC8WEy5yDVARzTA5%2BxmBc388v9Dm21HGfcC8O%0ADD%2BgT9sSpssq0ascmvH49MOgjt1yoysLtdCtJW/9FZpoOypaHx0R%2BmJTLwPXVMrv%0ADaVzWh5aiEx%2BidkSGMnX%0A-----END%20CERTIFICATE-----%0A"); - String signature = "Kn2Ya2T039qvEWIzIQeSksNyyCQIkcVjciClcp3a6C766dJANXxLLIn6CfyvUZddMtePrTOLpC2e5QTQxB4RwtWmFfr7nxRdFUtA3dH2DAQL5DqqlmPv46ZWSPfiiOXUsu8vNgX3Z4Znt4Q+dIPIquNPY8ZmiAcpKR7n2K3QtabgOnJ2EyngabY3LMQTtriXbZjpl53ynhVhV1rciMdvMaTz4DUYt7gKi+KeNd3CBFSev+eTgYPC3em96J/3bfVR+wC5m3JGbIBCrwAsbO05JkiNIMck3s+p4d/hwiABR75EplxaWmGgIm6VvUKtGhdJ/cNrmF0nxMX6Vi6N2WaLTA=="; - String signatureBody = "{\"id\":\"287419896494669543891634765983074535548\",\"timestamp\":\"2019-03-11T20:01:21.658293\",\"version\":3,\"isvEnclaveQuoteStatus\":\"OK\",\"isvEnclaveQuoteBody\":\"AgAAADILAAAIAAcAAAAAAPiLWcRSSA3shraxepsGV9qF4zYUPJgE42ZZZXS2G9zaBQUCBP//AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAHAAAAAAAAAM1s/DQpN7I7G907v5chqlYVrJ/1CnXFUn1EHNMnaCbJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADrzm117Qj8NlEllyDkV4Pae4UgsPjgVXtAA5UsG90gVgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACHgz6GaO6bkxfPLBYcR5rEf9Itrt81OEanXteSMcd/BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}"; - - KeyStore keyStore = KeyStore.getInstance("JKS"); - keyStore.load(getClass().getResourceAsStream("/ias.jks"), "whisper".toCharArray()); - - SigningCertificate certificate = new SigningCertificate(certificateChain, keyStore); - byte[] decodedSignature = Base64.decode(signature); - - for (int i=0;i new SigningCertificate(certificateChain, keyStore) - ); - } -}