Search in sources :

Example 6 with PreKeySignalMessage

use of org.whispersystems.libsignal.protocol.PreKeySignalMessage 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;
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) IdentityKey(org.whispersystems.libsignal.IdentityKey) UntrustedIdentityException(org.whispersystems.libsignal.UntrustedIdentityException) SignalMessage(org.whispersystems.libsignal.protocol.SignalMessage) PreKeySignalMessage(org.whispersystems.libsignal.protocol.PreKeySignalMessage) InvalidVersionException(org.whispersystems.libsignal.InvalidVersionException) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) NoSessionException(org.whispersystems.libsignal.NoSessionException) PreKeySignalMessage(org.whispersystems.libsignal.protocol.PreKeySignalMessage) DuplicateMessageException(org.whispersystems.libsignal.DuplicateMessageException) InvalidKeyIdException(org.whispersystems.libsignal.InvalidKeyIdException) LegacyMessageException(org.whispersystems.libsignal.LegacyMessageException) Nullable(androidx.annotation.Nullable)

Example 7 with PreKeySignalMessage

use of org.whispersystems.libsignal.protocol.PreKeySignalMessage 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;
}
Also used : CryptoFailedException(org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException) InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) IdentityKey(org.whispersystems.libsignal.IdentityKey) UntrustedIdentityException(org.whispersystems.libsignal.UntrustedIdentityException) PreKeySignalMessage(org.whispersystems.libsignal.protocol.PreKeySignalMessage) SignalMessage(org.whispersystems.libsignal.protocol.SignalMessage) InvalidVersionException(org.whispersystems.libsignal.InvalidVersionException) NoRawSessionException(org.jivesoftware.smackx.omemo.exceptions.NoRawSessionException) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) PreKeySignalMessage(org.whispersystems.libsignal.protocol.PreKeySignalMessage) DuplicateMessageException(org.whispersystems.libsignal.DuplicateMessageException) InvalidKeyIdException(org.whispersystems.libsignal.InvalidKeyIdException) LegacyMessageException(org.whispersystems.libsignal.LegacyMessageException) SessionCipher(org.whispersystems.libsignal.SessionCipher) UntrustedOmemoIdentityException(org.jivesoftware.smackx.omemo.exceptions.UntrustedOmemoIdentityException)

Aggregations

InvalidMessageException (org.whispersystems.libsignal.InvalidMessageException)7 PreKeySignalMessage (org.whispersystems.libsignal.protocol.PreKeySignalMessage)7 InvalidVersionException (org.whispersystems.libsignal.InvalidVersionException)6 IdentityKey (org.whispersystems.libsignal.IdentityKey)5 SignalMessage (org.whispersystems.libsignal.protocol.SignalMessage)5 DuplicateMessageException (org.whispersystems.libsignal.DuplicateMessageException)4 InvalidKeyException (org.whispersystems.libsignal.InvalidKeyException)4 InvalidKeyIdException (org.whispersystems.libsignal.InvalidKeyIdException)4 LegacyMessageException (org.whispersystems.libsignal.LegacyMessageException)4 UntrustedIdentityException (org.whispersystems.libsignal.UntrustedIdentityException)4 NoSessionException (org.whispersystems.libsignal.NoSessionException)3 SessionCipher (org.whispersystems.libsignal.SessionCipher)3 InsertResult (org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult)2 IncomingPreKeyBundleMessage (org.thoughtcrime.securesms.sms.IncomingPreKeyBundleMessage)2 IncomingTextMessage (org.thoughtcrime.securesms.sms.IncomingTextMessage)2 SignalProtocolAddress (org.whispersystems.libsignal.SignalProtocolAddress)2 SignalServiceAddress (org.whispersystems.signalservice.api.push.SignalServiceAddress)2 PushTransportDetails (org.whispersystems.signalservice.internal.push.PushTransportDetails)2 Nullable (android.support.annotation.Nullable)1 Nullable (androidx.annotation.Nullable)1