> Each message session with each contact is encrypted with a different set of keys"
Is this not a bad thing? Since transferring key-pairs is the weakest link on these apps. To be really secure, wouldn't you want to do this as infrequently as possible and ideally outside in person outside the app?
Sounds like they are trying to achieve perfect forward secrecy per message. Typically you might do this with Diffie-Hellman using ephemeral derivation pairs per session. This is good practice as if any one session key is broken, that has no effect on the privacy of past or future messages encrypted under different session keys. They seem to be claiming to use their own crypto based on the parent comment (red flag) and no signature scheme over the top of it to prove a consistent identity, so I'm not sure what they would be doing. Establishing encrypted pipes over an observable medium is very doable, but providing a way to trust that the party on the other end of the pipe is who you think it is is the hard part as you pointed out.
Session keys are fine, and they're usually not the top level identity or key. So long as this is what they're doing, i.e. using an asymmetric KEx (e.g. Diffie-Hellman) to exchange public keys, from which a shared secret would be derived, and then from that a KDF would be used to generate a key using a salt, you can keep generating new keys for each session from that shared secret (shared in the sense that it's symmetric, not that you send it over the wire).
You can still be more secure, but that's a decent start.
No, this is actually normal. For instance, each time you make a SSH connection, it will use a different key for the bulk encryption. A key exchange has to happen to negotiate this randomly generated session key.
Is this not a bad thing? Since transferring key-pairs is the weakest link on these apps. To be really secure, wouldn't you want to do this as infrequently as possible and ideally outside in person outside the app?