Closed zombiehoffa closed 7 months ago
I never understood the point of having the fingerprint on the same page/source as the APK download - if someone could tamper with the APK, couldn't they just as easily change a bit of HTML? I closed a similar issue #63 before for that reason.
But the Signal devs know more about this stuff so if they've done it, it's worth supporting I guess 🙃
Yah, I don't fully understand the logistics of how all this stuff works but I do want to verify the apk hasn't been tampered with some how. It would be much better if it was a input once, verify all subsequent apks for me to be able to set it manually and then have it warn me if it doesn't match but I don't think this is how it works.
Yeah, this would only be added for sources that provide a signature for each release, that can be extracted automatically. Manual input per release (and it would have to be per-apk per-release) is too impractical and would break silent updates when/if that is ever implemented.
Then sadly automagical scraping each time from the same page seems to be the only option. I wish it wasn't so.
If it can't be extracted automatically, how about giving us a way to input and store the hash of the key. Then we can be flagged if the .apk doesn't pass.
If it can't be extracted automatically, how about giving us a way to input and store the hash of the key. Then we can be flagged if the .apk doesn't pass.
This was my thought. As far as I'm aware, signing keys don't change often so a user could save the value of the current hash and Obtanium could warn when installing an .apk that doesn't match. Then the user could go to the source, check to see if the key has been rotated and update the saved hash if necessary.
I never understood the point of having the fingerprint on the same page/source as the APK download - if someone could tamper with the APK, couldn't they just as easily change a bit of HTML? I closed a similar issue #63 before for that reason.
I was wrong before - I confused the signing key hash for a hash of the APK itself. You're right, the hash of the signing key would not change often and could not be changed without the user noticing if they already got it from a trusted source earlier.
Just as a note, Android already does verify the signing key for updates, so that part is covered - the user only needs to be careful the first time they install the app. So this new feature would only be used when an app is being newly installed - the rest of the time it can be left to the OS.
Gotcha, glad to hear Android checks the signing key hash for upgrades. Didn't know that was built in. Will you be making this feature soon? If not I might try my hand at it. I haven't done anything Android development related in a long while but might be fun to take a whack at it.
Not sure what my timeline is but any PRs are welcome!
We could support finding out the developer's or app's nostr public key and check if it has an SHA256 on it's metadata nostr profile and offer it as an option to check on first install if it matches with .apk signature.
nostr public key
Forgive me, but that seems a bit obscure. At this juncture, at least, how many dev's are using nostr??
Distribution of key material is chaotic, to say the least. I think sticking to digging the key (it's hash) out by hand, is probably the best approach for now.
If a dev doesn't use nostr it just would require by hand. But if someone does and you can automatically get the SHA256 from it's profile instead of manually by hand, why not do it? Nostr usage by dev's would do nothing forced on you as a user of Obtainium. You always can replace by hand the SHA256 it would be used for signature verification even if it gets it from a dev's nostr profile. It's an opt-in, not forced thing.
why not do it?
Because there are many ways keys are distributed, and pushing this one over and above all others seems to be dependent your idiosyncratic interests.
So push other ways. That's no reason to not allow one of the ways. And again it is not forced on anyone, it's just an option to avoid having to do it manually for the apps/devs that do use nostr and decide to have their sha256 there.
I was precisely looking for such a feature and I 100% support this request. If I'm not mistaken, all the confidence in APK building process precisely relies on the fact that the package is built and signed by someone the community trusts. This is exactly what Signal is doing when asking to verify that the APK is rightly signed by a key known by the community. When you say @ImranR98
I never understood the point of having the fingerprint on the same page/source as the APK download - if someone could tamper with the APK, couldn't they just as easily change a bit of HTML?
You are completely right except that if the key changes from Signal's website for instance, the whole community should be aware of it and could alert everybody if there is something wrong. Furthermore, as it was already said, signing key should be pretty stable and if developers want to change it, they should make the community aware of it before.
When you think about it, this feature is exactly what is done by packages manager in Linux distributions. When you install packages from a new repo, you have to confirm that you recognize the public key which was used to sign packages from the repo.
It's however clear that the key distribution for each developer/app is a pain and is totally different from an app to another. Some projects, like Signal, try to do it properly so it would be really nice to have a feature showing on first install the public key of the key pair used to sign the APK. Similarly to Linux distribution, once the key is recognized, it is up to the system to alert you if you try to update a package signed with another key. As already mentioned, this is what Android is also doing.
Android verifies the signature for every app when installing them. It pins the signing key and enforces that the same signing key is used to sign each update. The version also has to be equal or greater to prevent downgrade attacks. The only time it makes sense to do something more is for the initial install, where you can verify that the key fingerprint matches. This is meant to be the responsibility of the app store, where app stores use signed metadata and chain trust to the app based on that. It's simply not possible to override signing key pinning or downgrade protection once an app is installed, other than uninstalling it first, which will wipe the data for the app. If you preserve data on uninstall, it continues doing signing key pinning and downgrade protection.
There's little value in obtaining the fingerprint from the same place you download the app at the same time, but there's a lot of value in an app like Obtainium pinning the expected keys. It should at least do this for any special cases it supports such as Signal, but it's unrealistic to do it for a significant number of apps. Keys can be rotated but it only happens extremely rarely and the new key must be signed by the other key via APK signing v3/v3.1. Only using APK signing v3.1 is recommended for apps which support older Android versions like Android 7 where APK signing v3 was buggy. APK signing v3.1 is the same thing but older Android versions ignore it. It was unfortunately not added as soon as key rotation worked properly so versions with working key rotation such as Android 11 won't use the new signing key since they predate v3.1.
Signal (as TextSecure) started out using an RSA 1024 key which was a poor choice with barely adequate security. They used the bare minimum of what was considered adequate at the time. It's not longer considered secure. They should be using APK signing v3.1 to rotate the signing key for modern Android. It will continue working fine for people on both old and new Android versions, but new versions with APK signing v3.1 support will move to pinning the new signing key which should be at least RSA 3072 (128-bit equivalent security).
Thanks for the detailed info @thestinger 👀
So this feature seems simple in theory:
But in practice it sounds like there are issues with different Android versions and key signing methods that would have to be dealt with (I'd have to read more on it to understand properly), plus having to support key rotation. Maybe there's a Flutter plugin that does all that already but I doubt it.
Most apps have 1 key for their releases outside the Play Store and have never rotated it. v3 added rotation, which initially didn't work perfectly, but was fixed. All currently supported Android versions (Android 11+) have fully worked v3 key rotation. See https://source.android.com/docs/security/features/apksigning/v3 for the note about that.
v3.1 key rotation is the same thing as v3 but is ignored on operating systems before it was introduced (Android 13+) which rules out the earlier issues. The issues with v3 key rotation on end-of-life Android versions aren't relevant to your app, only to app developers who want to rotate their key. It just means they can only rotate their key for Android 13+, which is unfortunate since v3 rotation works fine on Android 11 and Android 12, but Android 11 is approaching end-of-life anyway, and then Android 12 will be end-of-life in a year, so it's not going to be relevant to security much longer. Android 10 and earlier completely lack security patches so it doesn't matter at all.
v2 signing is required for apps targeting Android 7 and later which has been required for the Play Store for a long time now, which currently requires targeting Android 13+. v2 signing greatly simplified things. v2 signing is considered a security improvement and you might as well just reject apps without v2 or later signatures to avoid needing to deal with the overly complex and inadequate earlier system (JAR signing).
But in practice it sounds like there are issues with different Android versions and key signing methods that would have to be dealt with (I'd have to read more on it to understand properly), plus having to support key rotation. Maybe there's a Flutter plugin that does all that already but I doubt it.
You should be able to parse the package with the OS before triggering installation.
I have the same issue with https://www.privateinternetaccess.com/installer/download_installer_android That post SHA256
Could it maybe be an option you can enable? If I would enable "Verify checksum before install" and obtanium would run a checksum on the APK, then you can manually paste the checksum from the site and obtanium will verify it. If it is correct it could say "Checksum Verified" and move on to the install.
I have the same issue with https://www.privateinternetaccess.com/installer/download_installer_android That post SHA256
Could it maybe be an option you can enable? If I would enable "Verify checksum before install" and obtanium would run a checksum on the APK, then you can manually paste the checksum from the site and obtanium will verify it. If it is correct it could say "Checksum Verified" and move on to the install.
The solution to that one is easy, switch to mullvad as they have an fdroid package. As an added bonus they are owned by people that demonstrably care about privacy instead of a secretive data brokering company gobbling up vpn providers for possibly nefarious purposes.
I have the same issue with https://www.privateinternetaccess.com/installer/download_installer_android That post SHA256 Could it maybe be an option you can enable? If I would enable "Verify checksum before install" and obtanium would run a checksum on the APK, then you can manually paste the checksum from the site and obtanium will verify it. If it is correct it could say "Checksum Verified" and move on to the install.
The solution to that one is easy, switch to mullvad as they have an fdroid package. As an added bonus they are owned by people that demonstrably care about privacy instead of a secretive data brokering company gobbling up vpn providers for possibly nefarious purposes.
So does PIA (support to various privacy networks), they are cheaper (I need a dedicated IP for work), run RAM-disks only, do not log (court proof and not long ago audited by Deloitte) and I never had issues with it. I was never able to get stable connections with Mullvad. While PIA has never been an issue. Is Kape annoying as parent company? Yes. However they did good work so far, its a benefit of the doubt. I also have three years of sub left hehe. But I get why you made the suggestion.
Every APK is already signed. The OS package manager requires that it's a valid signature for every install and update. Obtaining a hash from the same place you obtain the APK and verifying it has little purpose. The same goes for obtaining a key fingerprint from the same place. For it to be useful, it has to be obtained in a different way. An app having a database of them is valuable. Downloading an APK from a site and verifying a hash of the APK or public key from the same site doesn't protect you from the website or connection being compromised.
The solution to that one is easy, switch to mullvad as they have an fdroid package.
This doesn't resolve anything since F-Droid has major security and trust issues, which is part of why people are using a different approach to obtaining apps which avoids them as a middleman.
Every APK is already signed. The OS package manager requires that it's a valid signature for every install and update. Obtaining a hash from the same place you obtain the APK and verifying it has little purpose. The same goes for obtaining a key fingerprint from the same place. For it to be useful, it has to be obtained in a different way. An app having a database of them is valuable. Downloading an APK from a site and verifying a hash of the APK or public key from the same site doesn't protect you from the website or connection being compromised.
Yes but this requires the OS to keep an uptodate sha list. Google does this but iirc graphineos is still working on it. The APK has a sha, a lot of users still use the posted sha to verify (while its only a sha, its not a PGP or some better way to verify) it gives some ease of mind. In the example I posted you can download the APK from two different links on the same site (the one I linked is harder to find than the download page so tampering had "slightly" lower chances).
This doesn't resolve anything since F-Droid has major security and trust issues, which is part of why people are using a different approach to obtaining apps which avoids them as a middleman.
I agree, f-doid, Aurora, droid-ify, even the play store are all easy to use stores. They are still a middleman. While they do all do their job and do it pretty well, they are middleman between FOSS and mass distribution
Yes but this requires the OS to keep an uptodate sha list.
No, every Android APK is signed. If it's not signed, you can't install it.
Google does this
No, they don't.
The APK has a sha, a lot of users still use the posted sha to verify
You're downloading an APK from the same website where you download the web page with the hash. The APK is already signed and verified by the package manager. What is the value of verifying a hash from the same place you got the APK?
while its only a sha, its not a PGP or some better way to verify) it gives some ease of mind.
PGP is a much worse far of verifying apps than their signature. Android's signing is a significantly better system than PGP with support for automatic key rotation and has much lower attack surface than GPG.
In the example I posted you can download the APK from two different links on the same site (the one I linked is harder to find than the download page so tampering had "slightly" lower chances).
It's coming from the same place.
I agree, f-doid, Aurora, droid-ify, even the play store are all easy to use stores. They are still a middleman. While they do all do their job and do it pretty well, they are middleman between FOSS and mass distribution
Aurora Store is a frontend to the Play Store which does not verify the added signing metadata by the Play Store proving apps came from the Play Store even if they're not using Play Signing themselves. That's needed to bootstrap trust from it properly. Aurora Store also doesn't use a reduced CA set or key pinning, and unlike a web browser doesn't enforce Certificate Transparency.
F-Droid's builds and sign nearly all the apps they distribute, so they aren't only a trusted middleman for the initial install but also every update. Their app and repository system doesn't follow basic security best practices. Their build server infrastructure is very problematic and has often been on an ancient OS release of an OS not providing proper security patches (being on end-of-life variants of Debian is quite bad but even Debian stable lacks a lot of security patches).
droid-ify
This and other apps like it are alternate F-Droid frontends. They share the issues of the F-Droid repository system and the main repository. Some may be better than the official F-Droid client, but they're still limited by using the same repository system and main repository.
Due to many developers losing keys, having their keys compromised, etc. and old Android releases not supporting key rotation properly, all new apps have to be signed with Play Signing on the Play Store, which makes it more trusted. It has also become more trusted when using the standard approach of it being a heavily integrated OS component. On an OS with standard Google Play integration, it's nearly completely trusted and you might as well use it as your main source of apps since you aren't actually reducing trust in it by using other sources.
but iirc graphineos is still working on it
GrapheneOS is planning to make a signing key fingerprint database for pinning signing keys, with support for the standard Android key rotation mechanism so rotated keys will still work if they were properly rotated. This is not something implemented elsewhere. Google doesn't have pinning for either APK hashes or signing key hashes. They have Play Protect only detects known malware apps, nothing else. It's just a classic anti-virus approach with the impossible task of enumerating everything bad they discover, which only helps against widely deployed malware which it can tell is the same as the definitions that were hard-wired.
No, every Android APK is signed. If it's not signed, you can't install it.
You are right, but every malicious APK is also signed
No, they don't.
but at least the play protect checks for "known" malicious keys, I don't know of any good "virus scanner" that does more on android. If you do, please tell me
You're downloading an APK from the same website where you download the web page with the hash. The APK is already signed and verified by the package manager. What is the value of verifying a hash from the same place you got the APK?
it are two different links, I don't know if the DNS resolve ends on the same download but having two download pages (one with and one without sha) "slightly" lowers tampering chances (and I do say "slightly")
PGP is a much worse far of verifying apps than their signature. Android's signing is a significantly better system than PGP with support for automatic key rotation and has much lower attack surface than GPG. But who updates this? The once a month Google update? That's not very often. If I download zeroday.apk (fiction) and execute it, it's running until unloaded on reboot. If it does not start again.
Aurora Store is a frontend to the Play Store which does not verify the added signing metadata by the Play Store proving apps came from the Play Store even if they're not using Play Signing themselves. That's needed to bootstrap trust from it properly. Aurora Store also doesn't use a reduced CA set or key pinning, and unlike a web browser doesn't enforce Certificate Transparency.
you lost me after "Aurora is less secure" haha. I do not know how to combat this. I know F-Droid has their own testing servers making service a little better but not prefect. I also do not know how to combat this. I know droid-ify is a frontend that adds Izzy too, which makes it more convenient but once again, I do not know how to combat tampering or "virus scanning" the right way.
Due to many developers losing keys, having their keys compromised, etc. and old Android releases not supporting key rotation properly, all new apps have to be signed with Play Signing on the Play Store, which makes it more trusted. It has also become more trusted when using the standard approach of it being a heavily integrated OS component. On an OS with standard Google Play integration, it's nearly completely trusted and you might as well use it as your main source of apps since you aren't actually reducing trust in it by using other sources.
this is the upside of the bigger downside of it being Google :(
So for something like Bitwarden which publishes the SHA256 hash along with their releases (ie. https://github.com/bitwarden/mobile/releases/tag/v2023.12.0) , what is the easiest way on GrapheneOS to take the hash of the apk file and confirm it matches? Is this not something Obtainium could do as a sanity check to confirm there was no MITM during the download? The user could check on another device, or another source, that the SHA256 hash matches. In theory the signed release is doing the same thing, it is just hidden behind the scenes. Verifying a hash matches is a nice feel-good double check.
It doesn't verify that when you're downloading it from the same place as the APK. Anyone who has control to replace the APK can replace the hash and vice versa. You would also normally even be using exactly the same connection to download them.
I know, but by showing the hash of the apk that is being installed, the user has the option of verifying somewhere else. In some cases, this might still mean the user is verifying with GitHub, but from a different device with a different network connection, for example, if they are paranoid and want to confirm the network of the device running Obtainium isn't being MITM'd. In other cases, the user could verify the expected hash out of band from a different trusted path.
The public key hash is what you should verify since it doesn't change for each release and can be listed in a central place and automatically verified from there. Adding a hash of the APKs for each release to a pinning list is improper since whoever is maintaining it would simply be blindly trusting each new release instead of pinning the public key once and then having releases verified from that going forward even after the key is rotated. It can be updated when the key is rotated based on the key rotation proof, just like the package manager does for it.
So for something like Bitwarden which publishes the SHA256 hash along with their releases (ie. https://github.com/bitwarden/mobile/releases/tag/v2023.12.0) , what is the easiest way on GrapheneOS to take the hash of the apk file and confirm it matches? Is this not something Obtainium could do as a sanity check to confirm there was no MITM during the download? The user could check on another device, or another source, that the SHA256 hash matches. In theory the signed release is doing the same thing, it is just hidden behind the scenes. Verifying a hash matches is a nice feel-good double check.
If you want to hash check there are various apps, it is also possible to drop it into VirusTotal (not very useful for Android but it shows SHA256). Then you can copy the SHA from the site, search on page in your browser and if it finds the SHA256 it matches. Its primitive but it works for ease of mind. While others here have already explained it us useless.
The public key hash is what you should verify since it doesn't change for each release and can be listed in a central place and automatically verified from there. Adding a hash of the APKs for each release to a pinning list is improper since whoever is maintaining it would simply
I'll have to check the next time I install an apk with Obtainium, but before install, especially before the first installation, is the public key hash of the key the apk was signed with displayed somewhere so the user can go verify the public key from a second source before continuing with the install? If so, that would be great and I must have missed it (relatively new GrapheneOS user).
It's not displayed, and this was the upshot of the request that came from the OP. If you want, you can display it by running apksigner yourself.
And see Imran's comment:
Just as a note, Android already does verify the signing key for updates, so that part is covered - the user only needs to be careful the first time they install the app. So this new feature would only be used when an app is being newly installed - the rest of the time it can be left to the OS.
He also says that PR's are welcome.
Thanks. So the best option if someone was paranoid would be to download the apk onto a desktop device, use apksigner to check the public key that signed the apk, and then find a second source for that public key for a sanity check. Then move the apk to the mobile device for the initial install, then use Obtainium for all future updates, and the same public key will be enforced for those.
Does anyone know of an open source android tool that can check the public key of a APK file to skip the necessity of the desktop device in the above scenario?
As for PR’s welcome, maybe the 35+ comments here will pique someone’s interest who has the ability to implement that feature.
Thanks. So the best option if someone was paranoid would be to download the apk onto a desktop device, use apksigner to check the public key that signed the apk, and then find a second source for that public key for a sanity check. Then move the apk to the mobile device for the initial install, then use Obtainium for all future updates, and the same public key will be enforced for those.
No, you should use an app to check it instead of unnecessarily trusting an extra less secure device. You're going through all these steps to increase security but are really going to end up reducing it. You're usually going to obtain public key from the same place, cancelling out it accomplishing anything, unless someone starts maintaining a database of them.
Thanks. So the best option if someone was paranoid would be to download the apk onto a desktop device, use apksigner to check the public key that signed the apk, and then find a second source for that public key for a sanity check. Then move the apk to the mobile device for the initial install, then use Obtainium for all future updates, and the same public key will be enforced for those.
If your lap/desktop is secure, sure; but you could probably just download the .apk on the phone, and then use apksigner in Termux or UserLand, unless you can find some android app that does the equivalent. (Let us know if you do.)
Does anyone know of an open source android tool that can check the public key of a APK file to skip the necessity of the desktop device in the above scenario?
As theStinger says, No. There is no standard place that those keys are saved.
There is no standard place that those keys are saved.
Every APK contains the public keys and signature.
There is no standard place that those keys are saved.
Every APK contains the public keys and signature.
Of course. The issue is, how to confirm that's actually the developer's key. We don't have key servers, for example, providing those keys. There is no "Web of Trust." etc.
Every APK contains the public keys and signature.
Of course. The issue is, how to confirm that's actually the developer's key. We don't have key servers, for example, providing those keys. There is no "Web of Trust." etc.
Yes unfortunately there is no "Web of Trust" equivalent in android ecosystem, however I would argue that App Verifier approach is sufficient in most of the cases and it is much better than nothing. It is done through cross-verification of APK signature fingerprints. The App Verifier database consists of signature fingerprints retrieved from official APK sources. Contributors submit signature fingerprints of apps and the main dev cross-verifies them. In case something happens (e.g. key ration, key compromise, failed verification) a contributor may open an issue and the fingerprints in question will be reviewed.
I should say that I actually thought of several issues with this approach. Most of them come down to limited resources of main (trusted) developers.
In all of these cases the App Verifier may actually cause an opposite, negative effect in terms of security. Giving the user a false sense of safety. This may result in ignorance when installing from untrusted sources or not doing additional verification.
As I said the first two issues are related to fundamental design of this approach. These events may only actually be detected and reported by contributors simply because trusted developers do not have enough time to scan through the whole database of apps for problems. For the last issue it is important to either somehow closely verify App Verifier on initial installation or establish a good Root of Trust. For example I hope that eventually App Verifier app, its database, or something equivalent will be integrated into GOS.
I hope that eventually App Verifier app, its database, or something equivalent will be integrated into GOS.
I would argue that it would be more appropriately integrated into Obtainium
Yes unfortunately there is no "Web of Trust" equivalent in android ecosystem, however I would argue that App Verifier approach is sufficient in most of the cases and it is much better than nothing.
Agreed.
It is done through cross-verification of APK signature fingerprints. The App Verifier database consists of signature fingerprints retrieved from official APK sources. Contributors submit signature fingerprints of apps and the main dev cross-verifies them.
This is a discussion for the AppVerifier git, but I might consider collecting reports of key location & key verification through the app. In a manner something like Moxie's Convergence, the total of positive or negative reports could be displayed, giving more or less confidence in the result.
I hope that eventually App Verifier app, its database, or something equivalent will be integrated into GOS.
I would argue that it would be more appropriately integrated into Obtainium
The description of Obtainium repo says that "[Obtainium is used to] Get Android App Updates Directly From the Source". Its always better to keep projects simple. Obtainium focuses on retrieving the APKs and doing automatic updates, while App Verifier (or future OS integration) focuses on verifying the app signatures and maintaining the database, but that's my personal opinion. Its up to the devs here really.
Between getting the apk and installing it, verification would be a very good idea! :)
Between getting the apk and installing it, verification would be a very good idea! :)
I think an ideal place to put verification is into the OS app installer. This way it verifies all apps you ever want to install from any source before actually installing.
I think an ideal place to put verification is into the OS app installer.
That seems like a big ask. Wouldn't the next most viable place be in our app stores? eg. including in GOS' App, Accrescent, Obtainium, etc. some kind of verification? I believe the first two of those do have a system in place, though their app selection is very limited.
That seems like a big ask. Wouldn't the next most viable place be in our app stores? eg. including in GOS' App, Accrescent, Obtainium, etc. some kind of verification? I believe the first two of those do have a system in place, though their app selection is very limited.
Implementing such a feature in every app store? This sounds unnecessary and demanding, plus this won't verify apps that are installed manually. There is also no centralized database or any kind of system (yet), so you suggest every app store to implement their own? Probably not but it would require collective initiative, and at that points I feel like its just better to integrate it into the installer. Also a side-note: if I am not mistaking Accrescent has something like this, and that's one of the reasons I recommend it.
GrapheneOS is planning to make a signing key fingerprint database for pinning signing keys, with support for the standard Android key rotation mechanism so rotated keys will still work if they were properly rotated. This is not something implemented elsewhere. Google doesn't have pinning for either APK hashes or signing key hashes. They have Play Protect only detects known malware apps, nothing else. It's just a classic anti-virus approach with the impossible task of enumerating everything bad they discover, which only helps against widely deployed malware which it can tell is the same as the definitions that were hard-wired.
https://github.com/GrapheneOS/os-issue-tracker/issues/989
The feasibility and design is up to the @thestinger, and other non-stock OS developers to decide. Users on stock will only be able to use something like App Verifier.
Just checked out AppVerifier, seems to work really well + it automatically verifies installed apps with its built in DB. Instead of trying to duplicate functionality in Obtainium, maybe it would make sense for AppVerifier to provide a method for other apps to use it without user interaction? Obtainium could send the APK (via an intent?) and AppVerifier could return a success/fail result. This would be an optional/recommended feature for users with AppVerifier installed. If it doesn't already provide functionality like this (and they're open to it) I could create an issue.
It would be great if we could verify the signing certificate on the apk matches for apps such as signal that provide that ability
https://signal.org/android/apk/