use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project Signal-Android by WhisperSystems.
the class MessageDecryptionUtil method decrypt.
/**
* Takes a {@link SignalServiceEnvelope} and returns a {@link DecryptionResult}, which has either
* a plaintext {@link SignalServiceContent} or information about an error that happened.
*
* Excluding the data updated in our protocol stores that results from decrypting a message, this
* method is side-effect free, preferring to return the decryption results to be handled by the
* caller.
*/
@NonNull
public static DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci();
SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireServiceId(), Recipient.self().requireE164());
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
List<Job> jobs = new LinkedList<>();
if (envelope.isPreKeySignalMessage()) {
jobs.add(new RefreshPreKeysJob());
}
try {
try {
return DecryptionResult.forSuccess(cipher.decrypt(envelope), jobs);
} catch (ProtocolInvalidVersionException e) {
Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
return DecryptionResult.forError(MessageState.INVALID_VERSION, toExceptionMetadata(e), jobs);
} catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolUntrustedIdentityException | ProtocolNoSessionException | ProtocolInvalidMessageException e) {
Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
Recipient sender = Recipient.external(context, e.getSender());
if (sender.supportsMessageRetries() && Recipient.self().supportsMessageRetries() && FeatureFlags.retryReceipts()) {
jobs.add(handleRetry(context, sender, envelope, e));
postInternalErrorNotification(context);
} else {
jobs.add(new AutomaticSessionResetJob(sender.getId(), e.getSenderDevice(), envelope.getTimestamp()));
}
return DecryptionResult.forNoop(jobs);
} catch (ProtocolLegacyMessageException e) {
Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
return DecryptionResult.forError(MessageState.LEGACY_MESSAGE, toExceptionMetadata(e), jobs);
} catch (ProtocolDuplicateMessageException e) {
Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
return DecryptionResult.forError(MessageState.DUPLICATE_MESSAGE, toExceptionMetadata(e), jobs);
} catch (InvalidMetadataVersionException | InvalidMetadataMessageException | InvalidMessageStructureException e) {
Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
return DecryptionResult.forNoop(jobs);
} catch (SelfSendException e) {
Log.i(TAG, "Dropping UD message from self.");
return DecryptionResult.forNoop(jobs);
} catch (UnsupportedDataMessageException e) {
Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
return DecryptionResult.forError(MessageState.UNSUPPORTED_DATA_MESSAGE, toExceptionMetadata(e), jobs);
}
} catch (NoSenderException e) {
Log.w(TAG, "Invalid message, but no sender info!");
return DecryptionResult.forNoop(jobs);
}
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.
the class DeviceGroupsInputStream method read.
public DeviceGroup read() throws IOException {
long detailsLength = readRawVarint32();
byte[] detailsSerialized = new byte[(int) detailsLength];
Util.readFully(in, detailsSerialized);
GroupDetails details = GroupDetails.parseFrom(detailsSerialized);
if (!details.hasId()) {
throw new IOException("ID missing on group record!");
}
byte[] id = details.getId().toByteArray();
Optional<String> name = Optional.fromNullable(details.getName());
List<GroupDetails.Member> members = details.getMembersList();
Optional<SignalServiceAttachmentStream> avatar = Optional.absent();
boolean active = details.getActive();
Optional<Integer> expirationTimer = Optional.absent();
Optional<String> color = Optional.fromNullable(details.getColor());
boolean blocked = details.getBlocked();
if (details.hasAvatar()) {
long avatarLength = details.getAvatar().getLength();
InputStream avatarStream = new ChunkedInputStream.LimitedInputStream(in, avatarLength);
String avatarContentType = details.getAvatar().getContentType();
avatar = Optional.of(new SignalServiceAttachmentStream(avatarStream, avatarContentType, avatarLength, Optional.<String>absent(), false, null));
}
if (details.hasExpireTimer() && details.getExpireTimer() > 0) {
expirationTimer = Optional.of(details.getExpireTimer());
}
List<SignalServiceAddress> addressMembers = new ArrayList<>(members.size());
for (GroupDetails.Member member : members) {
if (SignalServiceAddress.isValidAddress(member.getUuid(), member.getE164())) {
addressMembers.add(new SignalServiceAddress(UuidUtil.parseOrNull(member.getUuid()), member.getE164()));
} else {
throw new IOException("Missing group member address!");
}
}
return new DeviceGroup(id, name, addressMembers, avatar, active, expirationTimer, color, blocked);
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.
the class SignalServiceCipher method createSynchronizeMessage.
private SignalServiceSyncMessage createSynchronizeMessage(Metadata metadata, SyncMessage content) throws ProtocolInvalidMessageException, ProtocolInvalidKeyException, UnsupportedDataMessageException {
if (content.hasSent()) {
SyncMessage.Sent sentContent = content.getSent();
SignalServiceDataMessage dataMessage = createSignalServiceMessage(metadata, sentContent.getMessage());
Optional<SignalServiceAddress> address = SignalServiceAddress.isValidAddress(sentContent.getDestinationUuid(), sentContent.getDestinationE164()) ? Optional.of(new SignalServiceAddress(UuidUtil.parseOrNull(sentContent.getDestinationUuid()), sentContent.getDestinationE164())) : Optional.<SignalServiceAddress>absent();
Map<SignalServiceAddress, Boolean> unidentifiedStatuses = new HashMap<>();
if (!address.isPresent() && !dataMessage.getGroupInfo().isPresent()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("SyncMessage missing both destination and group ID!"), null, 0);
}
for (SyncMessage.Sent.UnidentifiedDeliveryStatus status : sentContent.getUnidentifiedStatusList()) {
if (SignalServiceAddress.isValidAddress(status.getDestinationUuid(), status.getDestinationE164())) {
SignalServiceAddress recipient = new SignalServiceAddress(UuidUtil.parseOrNull(status.getDestinationUuid()), status.getDestinationE164());
unidentifiedStatuses.put(recipient, status.getUnidentified());
} else {
Log.w(TAG, "Encountered an invalid UnidentifiedDeliveryStatus in a SentTranscript! Ignoring.");
}
}
return SignalServiceSyncMessage.forSentTranscript(new SentTranscriptMessage(address, sentContent.getTimestamp(), dataMessage, sentContent.getExpirationStartTimestamp(), unidentifiedStatuses, sentContent.getIsRecipientUpdate()));
}
if (content.hasRequest()) {
return SignalServiceSyncMessage.forRequest(new RequestMessage(content.getRequest()));
}
if (content.getReadList().size() > 0) {
List<ReadMessage> readMessages = new LinkedList<>();
for (SyncMessage.Read read : content.getReadList()) {
if (SignalServiceAddress.isValidAddress(read.getSenderUuid(), read.getSenderE164())) {
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parseOrNull(read.getSenderUuid()), read.getSenderE164());
readMessages.add(new ReadMessage(address, read.getTimestamp()));
} else {
Log.w(TAG, "Encountered an invalid ReadMessage! Ignoring.");
}
}
return SignalServiceSyncMessage.forRead(readMessages);
}
if (content.hasViewOnceOpen()) {
if (SignalServiceAddress.isValidAddress(content.getViewOnceOpen().getSenderUuid(), content.getViewOnceOpen().getSenderE164())) {
SignalServiceAddress address = new SignalServiceAddress(UuidUtil.parseOrNull(content.getViewOnceOpen().getSenderUuid()), content.getViewOnceOpen().getSenderE164());
ViewOnceOpenMessage timerRead = new ViewOnceOpenMessage(address, content.getViewOnceOpen().getTimestamp());
return SignalServiceSyncMessage.forViewOnceOpen(timerRead);
} else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("ViewOnceOpen message has no sender!"), null, 0);
}
}
if (content.hasVerified()) {
if (SignalServiceAddress.isValidAddress(content.getVerified().getDestinationUuid(), content.getVerified().getDestinationE164())) {
try {
Verified verified = content.getVerified();
SignalServiceAddress destination = new SignalServiceAddress(UuidUtil.parseOrNull(verified.getDestinationUuid()), verified.getDestinationE164());
IdentityKey identityKey = new IdentityKey(verified.getIdentityKey().toByteArray(), 0);
VerifiedState verifiedState;
if (verified.getState() == Verified.State.DEFAULT) {
verifiedState = VerifiedState.DEFAULT;
} else if (verified.getState() == Verified.State.VERIFIED) {
verifiedState = VerifiedState.VERIFIED;
} else if (verified.getState() == Verified.State.UNVERIFIED) {
verifiedState = VerifiedState.UNVERIFIED;
} else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Unknown state: " + verified.getState().getNumber()), metadata.getSender().getIdentifier(), metadata.getSenderDevice());
}
return SignalServiceSyncMessage.forVerified(new VerifiedMessage(destination, identityKey, verifiedState, System.currentTimeMillis()));
} catch (InvalidKeyException e) {
throw new ProtocolInvalidKeyException(e, metadata.getSender().getIdentifier(), metadata.getSenderDevice());
}
} else {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Verified message has no sender!"), null, 0);
}
}
if (content.getStickerPackOperationList().size() > 0) {
List<StickerPackOperationMessage> operations = new LinkedList<>();
for (SyncMessage.StickerPackOperation operation : content.getStickerPackOperationList()) {
byte[] packId = operation.hasPackId() ? operation.getPackId().toByteArray() : null;
byte[] packKey = operation.hasPackKey() ? operation.getPackKey().toByteArray() : null;
StickerPackOperationMessage.Type type = null;
if (operation.hasType()) {
switch(operation.getType()) {
case INSTALL:
type = StickerPackOperationMessage.Type.INSTALL;
break;
case REMOVE:
type = StickerPackOperationMessage.Type.REMOVE;
break;
}
}
operations.add(new StickerPackOperationMessage(packId, packKey, type));
}
return SignalServiceSyncMessage.forStickerPackOperations(operations);
}
if (content.hasBlocked()) {
List<String> numbers = content.getBlocked().getNumbersList();
List<String> uuids = content.getBlocked().getUuidsList();
List<SignalServiceAddress> addresses = new ArrayList<>(numbers.size() + uuids.size());
List<byte[]> groupIds = new ArrayList<>(content.getBlocked().getGroupIdsList().size());
for (String e164 : numbers) {
Optional<SignalServiceAddress> address = SignalServiceAddress.fromRaw(null, e164);
if (address.isPresent()) {
addresses.add(address.get());
}
}
for (String uuid : uuids) {
Optional<SignalServiceAddress> address = SignalServiceAddress.fromRaw(uuid, null);
if (address.isPresent()) {
addresses.add(address.get());
}
}
for (ByteString groupId : content.getBlocked().getGroupIdsList()) {
groupIds.add(groupId.toByteArray());
}
return SignalServiceSyncMessage.forBlocked(new BlockedListMessage(addresses, groupIds));
}
if (content.hasConfiguration()) {
Boolean readReceipts = content.getConfiguration().hasReadReceipts() ? content.getConfiguration().getReadReceipts() : null;
Boolean unidentifiedDeliveryIndicators = content.getConfiguration().hasUnidentifiedDeliveryIndicators() ? content.getConfiguration().getUnidentifiedDeliveryIndicators() : null;
Boolean typingIndicators = content.getConfiguration().hasTypingIndicators() ? content.getConfiguration().getTypingIndicators() : null;
Boolean linkPreviews = content.getConfiguration().hasLinkPreviews() ? content.getConfiguration().getLinkPreviews() : null;
return SignalServiceSyncMessage.forConfiguration(new ConfigurationMessage(Optional.fromNullable(readReceipts), Optional.fromNullable(unidentifiedDeliveryIndicators), Optional.fromNullable(typingIndicators), Optional.fromNullable(linkPreviews)));
}
if (content.hasFetchLatest() && content.getFetchLatest().hasType()) {
switch(content.getFetchLatest().getType()) {
case LOCAL_PROFILE:
return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.LOCAL_PROFILE);
case STORAGE_MANIFEST:
return SignalServiceSyncMessage.forFetchLatest(SignalServiceSyncMessage.FetchType.STORAGE_MANIFEST);
}
}
return SignalServiceSyncMessage.empty();
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.
the class SignalServiceMessageSender method createMultiDeviceSentTranscriptContent.
private byte[] createMultiDeviceSentTranscriptContent(SentTranscriptMessage transcript, Optional<UnidentifiedAccessPair> unidentifiedAccess) throws IOException {
SignalServiceAddress address = transcript.getDestination().get();
SendMessageResult result = SendMessageResult.success(address, unidentifiedAccess.isPresent(), true);
return createMultiDeviceSentTranscriptContent(createMessageContent(transcript.getMessage()), Optional.of(address), transcript.getTimestamp(), Collections.singletonList(result), false);
}
use of org.whispersystems.signalservice.api.push.SignalServiceAddress in project libsignal-service-java by signalapp.
the class SignalServiceMessageSender method createMultiDeviceBlockedContent.
private byte[] createMultiDeviceBlockedContent(BlockedListMessage blocked) {
Content.Builder container = Content.newBuilder();
SyncMessage.Builder syncMessage = createSyncMessageBuilder();
SyncMessage.Blocked.Builder blockedMessage = SyncMessage.Blocked.newBuilder();
for (SignalServiceAddress address : blocked.getAddresses()) {
if (address.getUuid().isPresent()) {
blockedMessage.addUuids(address.getUuid().get().toString());
}
if (address.getNumber().isPresent()) {
blockedMessage.addNumbers(address.getNumber().get());
}
}
for (byte[] groupId : blocked.getGroupIds()) {
blockedMessage.addGroupIds(ByteString.copyFrom(groupId));
}
return container.setSyncMessage(syncMessage.setBlocked(blockedMessage)).build().toByteArray();
}
Aggregations