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);
}
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));
}
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);
}
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);
}
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))));
}
Aggregations