Conversation
|
Thank you very much! This looks like a major enhancement. Would you please try to resolve the failing checks? The one of them concerning code formatting can be fixed with |
|
Thank you for taking the time to review such a big feature! I tested in the Android emulator with webauthn.io, but I could validate in my real phone against websites that I'm currently using in Linux once you tell me that everything looks OK from code perspective. |
| titleRes = R.string.pref_passkey_constant_signature_counter_title | ||
| summaryRes = R.string.pref_passkey_constant_signature_counter_summary | ||
| } | ||
| switch(PreferenceKeys.PASSKEY_AUTO_GIT_SYNC) { |
There was a problem hiding this comment.
If enabled, will this automatically trigger a Git sync whenever a new passkey has been added?
There was a problem hiding this comment.
Fixed at 2c1c256
If enabled, will this automatically trigger a Git sync whenever a new passkey has been added?
Yes, that's the idea. I added to replicate passless behavior. I don't know if it worths with PASSKEY_CONSTANT_SIGNATURE_COUNTER=true.
…lity
Implement FIDO2/WebAuthn passkeys support allowing the app to function as a
credential provider for websites and services supporting passkeys.
Key features:
- CBOR credential storage compatible with passless
- ES256 (P-256) algorithm support
- DER-encoded ECDSA signatures
- Biometric/PIN authentication
- Settings for constant signature counter and auto git sync
Storage format:
- Credentials stored as CBOR with integer array byte encoding
- Filename: {rpId}/{credentialIdHex}.gpg
- PGP encrypted using existing crypto infrastructure
Architecture:
- PasskeyCredentialProviderService handles Android Credential Manager requests
- ES256CryptoHandler for key generation and signing
- FilePasskeyStorage with CBOR serialization
- IndexedPasskeyStorage for fast lookups
Compatible with passless (github.com/pando85/passless) for cross-platform
credential sharing via Git repository.
The setting existed in the UI but was never read by the passkey implementation. Now when enabled (default), the signCount is kept at 0 to help detect cloned authenticators (passless compatible).
The setting existed in the UI but was never used. Now when enabled (default), passkey creation and usage trigger a git sync operation in the background to keep the repository in sync. Changed AppPasskeyProviderActivity to extend BaseGitActivity to gain access to git sync functionality.
- Remove duplicate updateSignCount call in AppPasskeyProviderActivity that was wasting I/O after assertion was already built - Remove unused convertDerToRaw and convertRawToDer methods from ES256CryptoHandler that were never called
Critical fixes: - Persist publicKey in StoredCredential CBOR serialization Previously publicKey was never saved, breaking passkey authentication after storage roundtrip - Fix race condition in IndexedPasskeyStorage Add @volatile and Mutex for thread-safe index loading - Log storage failures instead of silently swallowing them Change empty failure handler to proper error logging CBOR hardening: - Add bounds checking for integer conversions (BigInteger to Int/Long) - Add MAX_COLLECTION_SIZE (100k) and MAX_DEPTH (100) limits - Validate string/array lengths before converting to Int - Add range validation for byte values in toByteArray() Attestation improvements: - Use credential's signCount in attestation response instead of hardcoded 0 - Add credential ID length validation (max 1023 bytes per WebAuthn spec) - Improve require messages in CBOR encoding functions
|
Thank you for this first review. I fixed both things and analyzed a bit deeper all the code in the PR. |
- Add @RequiresApi(34) annotations for CredentialProviderService APIs - Suppress deprecation warnings for Autofill APIs (deprecated in API 35) - Suppress RawDispatchersUse lint warning (no SlackDispatchers in project) - Remove unused kotlinx.serialization.encodeToString import - Replace !! operator with safe null handling in tests - Fix DER signature size range in test (68-72 bytes, not 70-72) - Add tools:targetApi to AndroidManifest for passkey service
|
I fixed CI failures |
- Disable InvalidPackage check for third-party libraries - Disable RawDispatchersUse check for Android modules - Add empty baseline files for passkeys modules
|
I guess that this could be the final commit to fix CI. I don't receive any notifications when CI fails, so I'm trying to check this from time to time. |
|
Everything green, ready to review again. |
Summary
This PR implements WebAuthn/Passkeys support in Android Password Store, making it compatible with the passless project. Users can now use the app as a FIDO2 authenticator for websites and services that support passkeys.
Key Features
Credential Storage (passless-compatible)
{rpId}/{credentialIdHex}.gpg(e.g.,webauthn.io/a1b2c3d4....gpg)sign_count,private_key,display_name)WebAuthn Implementation
crossOrigin: falseSettings
truetrueArchitecture
passless Compatibility
This implementation is fully compatible with passless, a CLI FIDO2 authenticator. Both apps can read and write the same credentials:
{credIdHex}.gpg{credIdHex}.gpgCBOR Credential Structure
Testing
Prerequisites
Test Registration (webauthn.io)
test-aps)Test Authentication (webauthn.io)
Test Cross-Compatibility with passless
passlessand authenticate to webauthn.ioTest Fixture Verification
Security Considerations
Future Work
References
Related to: #629