use of org.whispersystems.libsignal.LegacyMessageException in project Signal-Android by signalapp.
the class SignalServiceCipher method decrypt.
private Plaintext decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) throws InvalidMetadataMessageException, InvalidMetadataVersionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException, InvalidMessageStructureException {
try {
byte[] paddedMessage;
SignalServiceMetadata metadata;
if (!envelope.hasSourceUuid() && !envelope.isUnidentifiedSender()) {
throw new InvalidMessageStructureException("Non-UD envelope is missing a UUID!");
}
if (envelope.isPreKeySignalMessage()) {
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSourceUuid().get(), envelope.getSourceDevice());
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext));
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent());
signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(sourceAddress));
} else if (envelope.isSignalMessage()) {
SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSourceUuid().get(), envelope.getSourceDevice());
SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext));
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent());
} else if (envelope.isPlaintextContent()) {
paddedMessage = new PlaintextContent(ciphertext).getBody();
metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent());
} else if (envelope.isUnidentifiedSender()) {
SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getServiceId().uuid(), localAddress.getNumber().orNull(), localDeviceId));
DecryptionResult result = sealedSessionCipher.decrypt(certificateValidator, ciphertext, envelope.getServerReceivedTimestamp());
SignalServiceAddress resultAddress = new SignalServiceAddress(ACI.parseOrThrow(result.getSenderUuid()), result.getSenderE164());
Optional<byte[]> groupId = result.getGroupId();
boolean needsReceipt = true;
if (envelope.hasSourceUuid()) {
Log.w(TAG, "[" + envelope.getTimestamp() + "] Received a UD-encrypted message sent over an identified channel. Marking as needsReceipt=false");
needsReceipt = false;
}
if (result.getCiphertextMessageType() == CiphertextMessage.PREKEY_TYPE) {
signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(new SignalProtocolAddress(result.getSenderUuid(), result.getDeviceId())));
}
paddedMessage = result.getPaddedMessage();
metadata = new SignalServiceMetadata(resultAddress, result.getDeviceId(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), needsReceipt, envelope.getServerGuid(), groupId);
} else {
throw new InvalidMetadataMessageException("Unknown type: " + envelope.getType());
}
PushTransportDetails transportDetails = new PushTransportDetails();
byte[] data = transportDetails.getStrippedPaddingMessageBody(paddedMessage);
return new Plaintext(metadata, data);
} catch (DuplicateMessageException e) {
throw new ProtocolDuplicateMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (LegacyMessageException e) {
throw new ProtocolLegacyMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidMessageException e) {
throw new ProtocolInvalidMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidKeyIdException e) {
throw new ProtocolInvalidKeyIdException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidKeyException e) {
throw new ProtocolInvalidKeyException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (UntrustedIdentityException e) {
throw new ProtocolUntrustedIdentityException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidVersionException e) {
throw new ProtocolInvalidVersionException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (NoSessionException e) {
throw new ProtocolNoSessionException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
}
}
use of org.whispersystems.libsignal.LegacyMessageException in project Signal-Android by signalapp.
the class PushDecryptJob method handleMessage.
private void handleMessage(SignalServiceEnvelope envelope, Optional<Long> smsMessageId) {
try {
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
SignalProtocolStore axolotlStore = new SignalProtocolStoreImpl(context);
SignalServiceAddress localAddress = new SignalServiceAddress(TextSecurePreferences.getLocalNumber(context));
SignalServiceCipher cipher = new SignalServiceCipher(localAddress, axolotlStore);
SignalServiceContent content = cipher.decrypt(envelope);
if (content.getDataMessage().isPresent()) {
SignalServiceDataMessage message = content.getDataMessage().get();
if (message.isEndSession())
handleEndSessionMessage(envelope, message, smsMessageId);
else if (message.isGroupUpdate())
handleGroupMessage(envelope, message, smsMessageId);
else if (message.isExpirationUpdate())
handleExpirationUpdate(envelope, message, smsMessageId);
else if (message.getAttachments().isPresent())
handleMediaMessage(envelope, message, smsMessageId);
else if (message.getBody().isPresent())
handleTextMessage(envelope, message, smsMessageId);
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))) {
handleUnknownGroupMessage(envelope, message.getGroupInfo().get());
}
if (message.getProfileKey().isPresent() && message.getProfileKey().get().length == 32) {
handleProfileKey(envelope, message);
}
} else if (content.getSyncMessage().isPresent()) {
SignalServiceSyncMessage syncMessage = content.getSyncMessage().get();
if (syncMessage.getSent().isPresent())
handleSynchronizeSentMessage(envelope, syncMessage.getSent().get());
else if (syncMessage.getRequest().isPresent())
handleSynchronizeRequestMessage(syncMessage.getRequest().get());
else if (syncMessage.getRead().isPresent())
handleSynchronizeReadMessage(syncMessage.getRead().get(), envelope.getTimestamp());
else if (syncMessage.getVerified().isPresent())
handleSynchronizeVerifiedMessage(syncMessage.getVerified().get());
else
Log.w(TAG, "Contains no known sync types...");
} else if (content.getCallMessage().isPresent()) {
Log.w(TAG, "Got call message...");
SignalServiceCallMessage message = content.getCallMessage().get();
if (message.getOfferMessage().isPresent())
handleCallOfferMessage(envelope, message.getOfferMessage().get(), smsMessageId);
else if (message.getAnswerMessage().isPresent())
handleCallAnswerMessage(envelope, message.getAnswerMessage().get());
else if (message.getIceUpdateMessages().isPresent())
handleCallIceUpdateMessage(envelope, message.getIceUpdateMessages().get());
else if (message.getHangupMessage().isPresent())
handleCallHangupMessage(envelope, message.getHangupMessage().get(), smsMessageId);
else if (message.getBusyMessage().isPresent())
handleCallBusyMessage(envelope, message.getBusyMessage().get());
} else if (content.getReceiptMessage().isPresent()) {
SignalServiceReceiptMessage message = content.getReceiptMessage().get();
if (message.isReadReceipt())
handleReadReceipt(envelope, message);
else if (message.isDeliveryReceipt())
handleDeliveryReceipt(envelope, message);
} else {
Log.w(TAG, "Got unrecognized message...");
}
if (envelope.isPreKeySignalMessage()) {
ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context));
}
} catch (InvalidVersionException e) {
Log.w(TAG, e);
handleInvalidVersionMessage(envelope, smsMessageId);
} catch (InvalidMessageException | InvalidKeyIdException | InvalidKeyException | MmsException e) {
Log.w(TAG, e);
handleCorruptMessage(envelope, smsMessageId);
} catch (NoSessionException e) {
Log.w(TAG, e);
handleNoSessionMessage(envelope, smsMessageId);
} catch (LegacyMessageException e) {
Log.w(TAG, e);
handleLegacyMessage(envelope, smsMessageId);
} catch (DuplicateMessageException e) {
Log.w(TAG, e);
handleDuplicateMessage(envelope, smsMessageId);
} catch (UntrustedIdentityException e) {
Log.w(TAG, e);
handleUntrustedIdentityMessage(envelope, smsMessageId);
}
}
use of org.whispersystems.libsignal.LegacyMessageException in project Conversations by siacs.
the class XmppAxolotlSession method processReceiving.
@Nullable
byte[] processReceiving(List<AxolotlKey> possibleKeys) throws CryptoFailedException {
byte[] plaintext = null;
FingerprintStatus status = getTrust();
if (!status.isCompromised()) {
Iterator<AxolotlKey> iterator = possibleKeys.iterator();
while (iterator.hasNext()) {
AxolotlKey encryptedKey = iterator.next();
try {
if (encryptedKey.prekey) {
PreKeySignalMessage preKeySignalMessage = new PreKeySignalMessage(encryptedKey.key);
Optional<Integer> optionalPreKeyId = preKeySignalMessage.getPreKeyId();
IdentityKey identityKey = preKeySignalMessage.getIdentityKey();
if (!optionalPreKeyId.isPresent()) {
if (iterator.hasNext()) {
continue;
}
throw new CryptoFailedException("PreKeyWhisperMessage did not contain a PreKeyId");
}
preKeyId = optionalPreKeyId.get();
if (this.identityKey != null && !this.identityKey.equals(identityKey)) {
if (iterator.hasNext()) {
continue;
}
throw new CryptoFailedException("Received PreKeyWhisperMessage but preexisting identity key changed.");
}
this.identityKey = identityKey;
plaintext = cipher.decrypt(preKeySignalMessage);
} else {
SignalMessage signalMessage = new SignalMessage(encryptedKey.key);
try {
plaintext = cipher.decrypt(signalMessage);
} catch (InvalidMessageException | NoSessionException e) {
if (iterator.hasNext()) {
Log.w(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring crypto exception because possible keys left to try", e);
continue;
}
throw new BrokenSessionException(this.remoteAddress, e);
}
// better safe than sorry because we use that to do special after prekey handling
preKeyId = null;
}
} catch (InvalidVersionException | InvalidKeyException | LegacyMessageException | InvalidMessageException | DuplicateMessageException | InvalidKeyIdException | UntrustedIdentityException e) {
if (iterator.hasNext()) {
Log.w(Config.LOGTAG, account.getJid().asBareJid() + ": ignoring crypto exception because possible keys left to try", e);
continue;
}
throw new CryptoFailedException("Error decrypting SignalMessage", e);
}
if (iterator.hasNext()) {
break;
}
}
if (!status.isActive()) {
setTrust(status.toActive());
// TODO: also (re)add to device list?
}
} else {
throw new CryptoFailedException("not encrypting omemo message from fingerprint " + getFingerprint() + " because it was marked as compromised");
}
return plaintext;
}
use of org.whispersystems.libsignal.LegacyMessageException in project Smack by igniterealtime.
the class SignalOmemoRatchet method doubleRatchetDecrypt.
@Override
public byte[] doubleRatchetDecrypt(OmemoDevice sender, byte[] encryptedKey) throws CorruptedOmemoKeyException, NoRawSessionException, CryptoFailedException, UntrustedOmemoIdentityException, IOException {
SessionCipher cipher = getCipher(sender);
byte[] decryptedKey;
// Try to handle the message as a PreKeySignalMessage...
try {
PreKeySignalMessage preKeyMessage = new PreKeySignalMessage(encryptedKey);
if (!preKeyMessage.getPreKeyId().isPresent()) {
throw new CryptoFailedException("PreKeyMessage did not contain a preKeyId.");
}
IdentityKey messageIdentityKey = preKeyMessage.getIdentityKey();
IdentityKey previousIdentityKey = store.loadOmemoIdentityKey(storeConnector.getOurDevice(), sender);
if (previousIdentityKey != null && !previousIdentityKey.getFingerprint().equals(messageIdentityKey.getFingerprint())) {
throw new UntrustedOmemoIdentityException(sender, store.keyUtil().getFingerprintOfIdentityKey(previousIdentityKey), store.keyUtil().getFingerprintOfIdentityKey(messageIdentityKey));
}
try {
decryptedKey = cipher.decrypt(preKeyMessage);
} catch (UntrustedIdentityException e) {
throw new AssertionError("Signals trust management MUST be disabled.");
} catch (LegacyMessageException | InvalidKeyException e) {
throw new CryptoFailedException(e);
} catch (InvalidKeyIdException e) {
throw new NoRawSessionException(sender, e);
} catch (DuplicateMessageException e) {
LOGGER.log(Level.INFO, "Decryption of PreKeyMessage from " + sender + " failed, since the message has been decrypted before.");
return null;
}
} catch (InvalidVersionException | InvalidMessageException noPreKeyMessage) {
// ...if that fails, handle it as a SignalMessage
try {
SignalMessage message = new SignalMessage(encryptedKey);
decryptedKey = getCipher(sender).decrypt(message);
} catch (UntrustedIdentityException e) {
throw new AssertionError("Signals trust management MUST be disabled.");
} catch (InvalidMessageException | NoSessionException e) {
throw new NoRawSessionException(sender, e);
} catch (LegacyMessageException e) {
throw new CryptoFailedException(e);
} catch (DuplicateMessageException e1) {
LOGGER.log(Level.INFO, "Decryption of SignalMessage from " + sender + " failed, since the message has been decrypted before.");
return null;
}
}
return decryptedKey;
}
use of org.whispersystems.libsignal.LegacyMessageException in project libsignal-service-java by signalapp.
the class SignalServiceCipher method decrypt.
private Plaintext decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) throws InvalidMetadataMessageException, InvalidMetadataVersionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException {
try {
byte[] paddedMessage;
Metadata metadata;
int sessionVersion;
if (!envelope.hasSource() && !envelope.isUnidentifiedSender()) {
throw new ProtocolInvalidMessageException(new InvalidMessageException("Non-UD envelope is missing a source!"), null, 0);
}
if (envelope.isPreKeySignalMessage()) {
SignalProtocolAddress sourceAddress = getPreferredProtocolAddress(signalProtocolStore, envelope.getSourceAddress(), envelope.getSourceDevice());
SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);
paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext));
metadata = new Metadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), false);
sessionVersion = sessionCipher.getSessionVersion();
} else if (envelope.isSignalMessage()) {
SignalProtocolAddress sourceAddress = getPreferredProtocolAddress(signalProtocolStore, envelope.getSourceAddress(), envelope.getSourceDevice());
SessionCipher sessionCipher = new SessionCipher(signalProtocolStore, sourceAddress);
paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext));
metadata = new Metadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), false);
sessionVersion = sessionCipher.getSessionVersion();
} else if (envelope.isUnidentifiedSender()) {
SealedSessionCipher sealedSessionCipher = new SealedSessionCipher(signalProtocolStore, localAddress.getUuid().orNull(), localAddress.getNumber().orNull(), 1);
DecryptionResult result = sealedSessionCipher.decrypt(certificateValidator, ciphertext, envelope.getServerTimestamp());
SignalServiceAddress resultAddress = new SignalServiceAddress(UuidUtil.parse(result.getSenderUuid().orNull()), result.getSenderE164());
SignalProtocolAddress protocolAddress = getPreferredProtocolAddress(signalProtocolStore, resultAddress, result.getDeviceId());
paddedMessage = result.getPaddedMessage();
metadata = new Metadata(resultAddress, result.getDeviceId(), envelope.getTimestamp(), true);
sessionVersion = sealedSessionCipher.getSessionVersion(protocolAddress);
} else {
throw new InvalidMetadataMessageException("Unknown type: " + envelope.getType());
}
PushTransportDetails transportDetails = new PushTransportDetails(sessionVersion);
byte[] data = transportDetails.getStrippedPaddingMessageBody(paddedMessage);
return new Plaintext(metadata, data);
} catch (DuplicateMessageException e) {
throw new ProtocolDuplicateMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (LegacyMessageException e) {
throw new ProtocolLegacyMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidMessageException e) {
throw new ProtocolInvalidMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidKeyIdException e) {
throw new ProtocolInvalidKeyIdException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidKeyException e) {
throw new ProtocolInvalidKeyException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (UntrustedIdentityException e) {
throw new ProtocolUntrustedIdentityException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (InvalidVersionException e) {
throw new ProtocolInvalidVersionException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
} catch (NoSessionException e) {
throw new ProtocolNoSessionException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
}
}
Aggregations