MeisApps / pcbu-desktop

Desktop app for PC Bio Unlock
https://meis-apps.com/pc-bio-unlock
GNU General Public License v3.0
3 stars 2 forks source link

Implementation question #6

Closed samipfjo closed 1 week ago

samipfjo commented 2 weeks ago

I've been reading through the source code and am a little puzzled about the way this is implemented.

From what I can tell without access to the source code of the mobile app, it appears that an encrypted copy of the user's password is stored in the mobile app's storage, locked behind the phone's fingerprint API. The process for unlocking is then:

1) Desktop app sends request to phone 2) Phone app prompts for fingerprint and user provides it 3) Phone app transmits encrypted password to the desktop app 4) Desktop app uses a locally stored encryption key to decrypt the received password

Then one of these two things happens (I haven't read closely enough to tell which): A) Desktop app passes the decrypted password to the OS for native authentication B) Desktop app hashes the decrypted password and checks it against a hashed copy, then sends the OS's native "credential OK" signal to the OS

If option A is required by the OS, I understand why the implementation works this way. With that said, I have read into how PAM and Windows auth works in the past though, and I'm fairly certain that in both cases the auth flow for credential providers follows option B.

If option B is indeed the case, why are passwords stored at all? It would make far more sense security-wise to use public key cryptography and store the private key on the phone, encrypted via the native fingerprint APIs. Authentication would then be a simple signing challenge. That would drastically simplify the authentication code on the PC side, as well as drastically improve the security model. Storing user passwords encrypted rather than hashed is really, really bad practice.

In any case, this is a REALLY cool idea, and I really appreciate all your hard work developing it. I know dealing with credential systems can be a huge pain in the ass.

MeisApps commented 2 weeks ago

AFAIK, option A is required by Windows. I built the Windows module based on Microsoft's sample, which requires the not hashed password to be passed. You can look at it here.

Maybe there is another way without requiring the password I am not aware of. However, during my testing of the PAM module on macOS, I noticed that the module also needs to set the user password, otherwise you will be signed out of your Apple account. The mobile app stores it using EncryptedSharedPreferences and the fingerprint encryption on top if the user wants to.

Glad you like it. It really was a pain, especially on Windows. Don't forget to leave a review for the app ;)

samipfjo commented 2 weeks ago

I've done a bit of research.

So the reason it doesn't seem possible in Windows is because the program only implements half of the Windows credential system. In order to use custom credentials you'd need to move the credential handling logic into a custom credential provider and authentication provider to handle the verification.

Docs homepage for authentication packages

Here's an example of a plugin for pGina that leverages pGina's Windows credential API wrappers. pGina is permissively licensed, so referencing its credential wrapper API could be a good approach to implementing it here.

Reading up on Linux's PAM implementation, it's super flexible, so it's absolutely possible there as well. Being able to do whatever I want with my system is one of the big reasons I daily drive Linux, so I'm happy to see that authentication is as flexible as everything else.

macOS is definitely trickier It looks like (because of course it is 🙄). The latest version of macOS supports using the fingerprint reader for sudo, so its PAM implementation appears to be opening up a bit. I'm betting that that the majority of your Mac userbase doesn't run the latest version, though.

samipfjo commented 2 weeks ago

Windows also offers the handy CredWrite and CredRead functions to store and retrieve custom credentials, so it'll even take care of storing the public key in a safe place. It's a firm policy of mine to manually handle Windows permissions as infrequently as possible haha.

MeisApps commented 1 week ago

Thank you for researching this. I really appreciate it.

I've looked into pGina for a bit, and they apparently use Kerberos tokens for authentication. Authentication packages would make it possible, too. Either way, it will be painful to implement this.

I initially wanted to implement authentication like you said with keys, but went with option A because of Windows. In the coming days, I'll implement RSA auth on Linux and see how it goes. On Windows, I need to do further research first, but I wanted to look if I can integrate it better with Windows Hello anyway and maybe this has another way of doing it.

The macOS version is very experimental and not even advertised. Their PAM support is very crude and all the UIs are ignoring any message the module wants to show to the user. However, as long as the situation there doesn't get better, I'd have to keep the option A method, at least for macOS only.