Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Biometric data encryption and decryption #229

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

tao-software
Copy link

This PR adds a compact API for data encryption and decryption using the devices Biometric features. Related to #41.

We've already updated the README, please refer to it for the usage details.

@f-23
Copy link

f-23 commented Dec 13, 2022

Hi @jayfunk! Could you have a look at this?

Copy link
Member

@jayfunk jayfunk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few minor changes. I still need to run it through some tests on my devices.

README.md Outdated Show resolved Hide resolved
);

PromptInfo promptInfo = new PromptInfo.Builder()
.setDeviceCredentialAllowed(false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allowing device credentials is a new aspect being added into this library. I would like to either implement that capability or note in the documentation that it is not supported.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a technical reason not to allow device credentials fallback here?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I'm guessing it's this:

Calling this method invokes crypto-based authentication, which is incompatible with Class 2 (formerly Weak) biometrics and (prior to Android 11) device credential.

Copy link
Author

@tao-software tao-software Oct 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the customer who contracted us for the feature needed it paired with strong biometrics, so we didn't bother with a fallback path, esp. since all the design work was done pre Android 11. (And 11 did have a bunch of bugs in it too, iirc. It's been a while.)

I think these days it'd be more reasonable to support them, since the bugs should hopefully be fixed…?

@f-23 Could you look into supporting allowDeviceCredentials here?

@f-23
Copy link

f-23 commented Jan 18, 2023

I have updated the README to include a note for the unsupported feature.

@mnikolaus
Copy link

I have updated the README to include a note for the unsupported feature.

Can you re-request review?

@tao-software tao-software requested a review from jayfunk February 17, 2023 09:05
@f-23
Copy link

f-23 commented Apr 28, 2023

Any update on this?

@jasny
Copy link

jasny commented May 26, 2023

@jayfunk Could you have another look at this?

@mlev
Copy link

mlev commented Oct 11, 2023

Would love to see this merged - what is it that's blocking it?

Copy link

@tamlyn tamlyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for sharing this code. It's a very welcome addition to this library.

I've left lots of comments but they're mostly questions and text changes.

One general question I have is: do we need a separate encryption key? Couldn't we use the existing private key to encrypt data? It would simplify the API and avoid confusion between methods like deleteKeys and deleteEncryptionKey.

README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
throw new Exception("Cannot generate keys on android versions below 6.0");
}
deleteBiometricEncryptionKey();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth documenting in the Readme that calling createEncryptionKey will delete any existing key, rendering any data encrypted with that key forever undecipherable.

I see that this is also the behaviour of createKeys but that's a little different because you get a public key in return and you are expected to do something with it. Here the key is not returned so it's a bit more magical and I, at least, hadn't thought about it invalidating existing data until I saw this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. We only ever used the functionality to guard authentication tokens, so it wasn't really a limitation to us.

For now I'll just document it in the readme, I'm not sure what's the best way to handle this. Should createEncryptionKeys just fail if a key exists, forcing devs to manually wipe existing keys first? Should multiple keys be supported? Both options break symmetry with the signing methods, and the latter adds another layer of complexity.

);

PromptInfo promptInfo = new PromptInfo.Builder()
.setDeviceCredentialAllowed(false)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a technical reason not to allow device credentials fallback here?

);

PromptInfo promptInfo = new PromptInfo.Builder()
.setDeviceCredentialAllowed(false)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I'm guessing it's this:

Calling this method invokes crypto-based authentication, which is incompatible with Class 2 (formerly Weak) biometrics and (prior to Android 11) device credential.

ios/ReactNativeBiometrics.m Outdated Show resolved Hide resolved
tao-software and others added 2 commits October 23, 2023 11:27
Fix typo

Co-authored-by: Tamlyn Rhodes <[email protected]>
Fix typos

Co-authored-by: Tamlyn Rhodes <[email protected]>
@jasny
Copy link

jasny commented Oct 23, 2023

One general question I have is: do we need a separate encryption key? Couldn't we use the existing private key to encrypt data? It would simplify the API and avoid confusion between methods like deleteKeys and deleteEncryptionKey.

No, you need to specify the if you want to use the key pair for signatures or encryption. See https://developer.android.com/training/sign-in/biometric-auth#crypto

Even if you could use the same key pair (which you typically can't) for signing and encryption, there's no guarantee that works across systems and versions.

@tao-software
Copy link
Author

It's usually a Very Bad Idea to reuse one key for multiple purposes (e.g.), so even if Android or iOS were unsafe enough to allow it, we would not want to support it.

@tao-software
Copy link
Author

We'll look into allowDeviceCredentials support to be more consistent with the signing methods, and some input on handling repeated createEncryptionKey calls would be appreciated, but I think we're caught up otherwise?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants