Search in sources :

Example 91 with ProfileKey

use of org.signal.zkgroup.profiles.ProfileKey in project Signal-Android by WhisperSystems.

the class RetrieveProfileAvatarJob method onRun.

@Override
public void onRun() throws IOException {
    RecipientDatabase database = SignalDatabase.recipients();
    ProfileKey profileKey = ProfileKeyUtil.profileKeyOrNull(recipient.resolve().getProfileKey());
    if (profileKey == null) {
        Log.w(TAG, "Recipient profile key is gone!");
        return;
    }
    if (Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) {
        Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar);
        return;
    }
    if (TextUtils.isEmpty(profileAvatar)) {
        Log.w(TAG, "Removing profile avatar (no url) for: " + recipient.getId().serialize());
        AvatarHelper.delete(context, recipient.getId());
        database.setProfileAvatar(recipient.getId(), profileAvatar);
        return;
    }
    File downloadDestination = File.createTempFile("avatar", "jpg", context.getCacheDir());
    try {
        SignalServiceMessageReceiver receiver = ApplicationDependencies.getSignalServiceMessageReceiver();
        InputStream avatarStream = receiver.retrieveProfileAvatar(profileAvatar, downloadDestination, profileKey, AvatarHelper.AVATAR_DOWNLOAD_FAILSAFE_MAX_SIZE);
        try {
            AvatarHelper.setAvatar(context, recipient.getId(), avatarStream);
            if (recipient.isSelf()) {
                SignalStore.misc().markHasEverHadAnAvatar();
            }
        } catch (AssertionError e) {
            throw new IOException("Failed to copy stream. Likely a Conscrypt issue.", e);
        }
    } catch (PushNetworkException e) {
        if (e.getCause() instanceof NonSuccessfulResponseCodeException) {
            Log.w(TAG, "Removing profile avatar (no image available) for: " + recipient.getId().serialize());
            AvatarHelper.delete(context, recipient.getId());
        } else {
            throw e;
        }
    } finally {
        if (downloadDestination != null)
            downloadDestination.delete();
    }
    database.setProfileAvatar(recipient.getId(), profileAvatar);
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) PushNetworkException(org.whispersystems.signalservice.api.push.exceptions.PushNetworkException) SignalServiceMessageReceiver(org.whispersystems.signalservice.api.SignalServiceMessageReceiver) InputStream(java.io.InputStream) NonSuccessfulResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException) IOException(java.io.IOException) File(java.io.File) ProfileKey(org.signal.zkgroup.profiles.ProfileKey)

Example 92 with ProfileKey

use of org.signal.zkgroup.profiles.ProfileKey in project Signal-Android by WhisperSystems.

the class MultiDeviceProfileKeyUpdateJob method onRun.

@Override
public void onRun() throws IOException, UntrustedIdentityException {
    if (!Recipient.self().isRegistered()) {
        throw new NotPushRegisteredException();
    }
    if (!TextSecurePreferences.isMultiDevice(context)) {
        Log.i(TAG, "Not multi device...");
        return;
    }
    Optional<ProfileKey> profileKey = Optional.of(ProfileKeyUtil.getSelfProfileKey());
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DeviceContactsOutputStream out = new DeviceContactsOutputStream(baos);
    out.write(new DeviceContact(RecipientUtil.toSignalServiceAddress(context, Recipient.self()), Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), profileKey, false, Optional.absent(), Optional.absent(), false));
    out.close();
    SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
    SignalServiceAttachmentStream attachmentStream = SignalServiceAttachment.newStreamBuilder().withStream(new ByteArrayInputStream(baos.toByteArray())).withContentType("application/octet-stream").withLength(baos.toByteArray().length).build();
    SignalServiceSyncMessage syncMessage = SignalServiceSyncMessage.forContacts(new ContactsMessage(attachmentStream, false));
    messageSender.sendSyncMessage(syncMessage, UnidentifiedAccessUtil.getAccessForSync(context));
}
Also used : DeviceContact(org.whispersystems.signalservice.api.messages.multidevice.DeviceContact) ByteArrayInputStream(java.io.ByteArrayInputStream) DeviceContactsOutputStream(org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsOutputStream) NotPushRegisteredException(org.thoughtcrime.securesms.net.NotPushRegisteredException) SignalServiceMessageSender(org.whispersystems.signalservice.api.SignalServiceMessageSender) ContactsMessage(org.whispersystems.signalservice.api.messages.multidevice.ContactsMessage) ByteArrayOutputStream(java.io.ByteArrayOutputStream) SignalServiceSyncMessage(org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) SignalServiceAttachmentStream(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream)

Example 93 with ProfileKey

use of org.signal.zkgroup.profiles.ProfileKey in project Signal-Android by WhisperSystems.

the class DeviceContactsInputStream method read.

public DeviceContact read() throws IOException {
    int detailsLength = (int) readRawVarint32();
    if (detailsLength == -1) {
        return null;
    }
    byte[] detailsSerialized = new byte[(int) detailsLength];
    Util.readFully(in, detailsSerialized);
    SignalServiceProtos.ContactDetails details = SignalServiceProtos.ContactDetails.parseFrom(detailsSerialized);
    if (!SignalServiceAddress.isValidAddress(details.getUuid(), details.getNumber())) {
        throw new IOException("Missing contact address!");
    }
    SignalServiceAddress address = new SignalServiceAddress(ACI.parseOrThrow(details.getUuid()), details.getNumber());
    Optional<String> name = Optional.fromNullable(details.getName());
    Optional<SignalServiceAttachmentStream> avatar = Optional.absent();
    Optional<String> color = details.hasColor() ? Optional.of(details.getColor()) : Optional.<String>absent();
    Optional<VerifiedMessage> verified = Optional.absent();
    Optional<ProfileKey> profileKey = Optional.absent();
    boolean blocked = false;
    Optional<Integer> expireTimer = Optional.absent();
    Optional<Integer> inboxPosition = Optional.absent();
    boolean archived = false;
    if (details.hasAvatar()) {
        long avatarLength = details.getAvatar().getLength();
        InputStream avatarStream = new LimitedInputStream(in, avatarLength);
        String avatarContentType = details.getAvatar().getContentType();
        avatar = Optional.of(new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, Optional.<String>absent(), false, false, false, null, null));
    }
    if (details.hasVerified()) {
        try {
            if (!SignalServiceAddress.isValidAddress(details.getVerified().getDestinationUuid(), details.getVerified().getDestinationE164())) {
                throw new InvalidMessageException("Missing Verified address!");
            }
            IdentityKey identityKey = new IdentityKey(details.getVerified().getIdentityKey().toByteArray(), 0);
            SignalServiceAddress destination = new SignalServiceAddress(ACI.parseOrThrow(details.getVerified().getDestinationUuid()), details.getVerified().getDestinationE164());
            VerifiedMessage.VerifiedState state;
            switch(details.getVerified().getState()) {
                case VERIFIED:
                    state = VerifiedMessage.VerifiedState.VERIFIED;
                    break;
                case UNVERIFIED:
                    state = VerifiedMessage.VerifiedState.UNVERIFIED;
                    break;
                case DEFAULT:
                    state = VerifiedMessage.VerifiedState.DEFAULT;
                    break;
                default:
                    throw new InvalidMessageException("Unknown state: " + details.getVerified().getState());
            }
            verified = Optional.of(new VerifiedMessage(destination, identityKey, state, System.currentTimeMillis()));
        } catch (InvalidKeyException | InvalidMessageException e) {
            Log.w(TAG, e);
            verified = Optional.absent();
        }
    }
    if (details.hasProfileKey()) {
        try {
            profileKey = Optional.fromNullable(new ProfileKey(details.getProfileKey().toByteArray()));
        } catch (InvalidInputException e) {
            Log.w(TAG, "Invalid profile key ignored", e);
        }
    }
    if (details.hasExpireTimer() && details.getExpireTimer() > 0) {
        expireTimer = Optional.of(details.getExpireTimer());
    }
    if (details.hasInboxPosition()) {
        inboxPosition = Optional.of(details.getInboxPosition());
    }
    blocked = details.getBlocked();
    archived = details.getArchived();
    return new DeviceContact(address, name, avatar, color, verified, profileKey, blocked, expireTimer, inboxPosition, archived);
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) SignalServiceAttachmentStream(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) InvalidInputException(org.signal.zkgroup.InvalidInputException) IdentityKey(org.whispersystems.libsignal.IdentityKey) InputStream(java.io.InputStream) IOException(java.io.IOException) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) SignalServiceProtos(org.whispersystems.signalservice.internal.push.SignalServiceProtos)

Example 94 with ProfileKey

use of org.signal.zkgroup.profiles.ProfileKey in project Signal-Android by WhisperSystems.

the class GroupChangeUtil_resolveConflict_Test method field_16__changes_to_add_requesting_members_when_pending_are_promoted.

@Test
public void field_16__changes_to_add_requesting_members_when_pending_are_promoted() {
    UUID member1 = UUID.randomUUID();
    UUID member2 = UUID.randomUUID();
    UUID member3 = UUID.randomUUID();
    ProfileKey profileKey1 = randomProfileKey();
    ProfileKey profileKey2 = randomProfileKey();
    ProfileKey profileKey3 = randomProfileKey();
    DecryptedGroup groupState = DecryptedGroup.newBuilder().addPendingMembers(pendingMember(member1)).addPendingMembers(pendingMember(member3)).build();
    DecryptedGroupChange decryptedChange = DecryptedGroupChange.newBuilder().addNewRequestingMembers(requestingMember(member1, profileKey1)).addNewRequestingMembers(requestingMember(member2, profileKey2)).addNewRequestingMembers(requestingMember(member3, profileKey3)).build();
    GroupChange.Actions change = GroupChange.Actions.newBuilder().addAddRequestingMembers(GroupChange.Actions.AddRequestingMemberAction.newBuilder().setAdded(encryptedRequestingMember(member1, profileKey1))).addAddRequestingMembers(GroupChange.Actions.AddRequestingMemberAction.newBuilder().setAdded(encryptedRequestingMember(member2, profileKey2))).addAddRequestingMembers(GroupChange.Actions.AddRequestingMemberAction.newBuilder().setAdded(encryptedRequestingMember(member3, profileKey3))).build();
    GroupChange.Actions resolvedActions = GroupChangeUtil.resolveConflict(groupState, decryptedChange, change).build();
    GroupChange.Actions expected = GroupChange.Actions.newBuilder().addPromotePendingMembers(GroupChange.Actions.PromotePendingMemberAction.newBuilder().setPresentation(presentation(member1, profileKey1))).addAddRequestingMembers(GroupChange.Actions.AddRequestingMemberAction.newBuilder().setAdded(encryptedRequestingMember(member2, profileKey2))).addPromotePendingMembers(GroupChange.Actions.PromotePendingMemberAction.newBuilder().setPresentation(presentation(member3, profileKey3))).build();
    assertEquals(expected, resolvedActions);
}
Also used : DecryptedGroupChange(org.signal.storageservice.protos.groups.local.DecryptedGroupChange) GroupChange(org.signal.storageservice.protos.groups.GroupChange) DecryptedGroupChange(org.signal.storageservice.protos.groups.local.DecryptedGroupChange) UUID(java.util.UUID) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) ProtoTestUtils.randomProfileKey(org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.randomProfileKey) DecryptedGroup(org.signal.storageservice.protos.groups.local.DecryptedGroup) Test(org.junit.Test)

Example 95 with ProfileKey

use of org.signal.zkgroup.profiles.ProfileKey in project Signal-Android by WhisperSystems.

the class GroupsV2Operations_decrypt_change_Test method can_decrypt_modify_member_profile_key_action_field6.

@Test
public void can_decrypt_modify_member_profile_key_action_field6() {
    UUID self = UUID.randomUUID();
    ProfileKey profileKey = newProfileKey();
    GroupCandidate groupCandidate = groupCandidate(self, profileKey);
    assertDecryption(groupOperations.createUpdateProfileKeyCredentialChange(groupCandidate.getProfileKeyCredential().get()).setRevision(10), DecryptedGroupChange.newBuilder().setRevision(10).addModifiedProfileKeys(DecryptedMember.newBuilder().setRole(Member.Role.UNKNOWN).setJoinedAtRevision(-1).setProfileKey(ByteString.copyFrom(profileKey.serialize())).setUuid(UuidUtil.toByteString(self))));
}
Also used : UUID(java.util.UUID) ProfileKey(org.signal.zkgroup.profiles.ProfileKey) Test(org.junit.Test)

Aggregations

ProfileKey (org.signal.zkgroup.profiles.ProfileKey)150 Test (org.junit.Test)102 UUID (java.util.UUID)90 DecryptedGroup (org.signal.storageservice.protos.groups.local.DecryptedGroup)50 ProtoTestUtils.randomProfileKey (org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.randomProfileKey)50 DecryptedGroupChange (org.signal.storageservice.protos.groups.local.DecryptedGroupChange)34 ProtoTestUtils.newProfileKey (org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.newProfileKey)28 ProtoTestUtils.withProfileKey (org.whispersystems.signalservice.api.groupsv2.ProtoTestUtils.withProfileKey)28 IOException (java.io.IOException)24 GroupChange (org.signal.storageservice.protos.groups.GroupChange)14 DecryptedMember (org.signal.storageservice.protos.groups.local.DecryptedMember)14 InvalidCiphertextException (org.whispersystems.signalservice.api.crypto.InvalidCiphertextException)12 InvalidInputException (org.signal.zkgroup.InvalidInputException)8 ProfileKeyCredential (org.signal.zkgroup.profiles.ProfileKeyCredential)8 Recipient (org.thoughtcrime.securesms.recipients.Recipient)8 InvalidKeyException (org.whispersystems.libsignal.InvalidKeyException)8 NonNull (androidx.annotation.NonNull)6 ByteArrayOutputStream (java.io.ByteArrayOutputStream)6 RecipientDatabase (org.thoughtcrime.securesms.database.RecipientDatabase)6 IdentityKey (org.whispersystems.libsignal.IdentityKey)6