-
Notifications
You must be signed in to change notification settings - Fork 228
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
EncryptorDecryptor Trait for Logins Component #6469
base: main
Are you sure you want to change the base?
Conversation
03f06ad
to
a3c0e96
Compare
be673a2
to
af91a5e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fantastic and a massive improvement, thanks! Dealing with Android and iOS will be a challenge though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really great to me, I like the overall approach. I commented on some of the details -- treat them as suggestions only. I don't have strong feelings either way.
Hopefully the consumer app updates aren't too bad.
The pull request has been modified, dismissing previous reviews.
2f13b8a
to
497ca51
Compare
8a434a3
to
4cbc6da
Compare
949c187
to
ac69d88
Compare
789c735
to
b615389
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great!
b615389
to
033d8de
Compare
The pull request has been modified, dismissing previous reviews.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added you as an admin I think, so hopefully you will not need re-approval for all new pushes! Note however you have an iOS test failure
that iOS test failure is a flaky one. This time, it passed. It seems as it has nothing to do with the changes of in PR. |
58877ec
to
b84b18a
Compare
This prepares the Logins component for the desktop and simplifies its API. BREAKING CHANGE: This commit introduces breaking changes to the Logins component: During initialization, it receives an additional argument, a EncryptorDecryptorTrait implementation. In addition, several LoginsStore API methods have been changed to not require an encryption key argument anymore, and return Logins objects instead of EncryptedLogins. Additionally, a new API method has been added to the LoginsStore, `has_logins_by_base_domain(&self, base_domain: &str)`, which can be used to check for the existence of a login for a given base domain. **EncryptorDecryptor** With the introduction of the EncryptorDecryptor trait, encryption becomes transparent. That means, the LoginStore API receives some breaking changes as outlined above. A ManagedEncryptorDecryptor will provide an EncryptorDecryptor implementation which uses the currently used crypto methods, given a KeyManager implementation. This eases adaption for mobile. Furthermore, we provide a StaticKeyManager implementation, which can be used in tests and in cases where the key is - you name it - static. Constructors Now an implementation of the above property must be passed to the constructors. To do this, the signatures are extended as follows: ``` pub fn new(path: impl AsRef<Path>, encdec: Arc<dyn EncryptorDecryptor>) -> ApiResult<Self> pub fn new_from_db(db: LoginDb, encdec: Arc<dyn EncryptorDecryptor>) -> Self pub fn new_in_memory(encdec: Arc<dyn EncryptorDecryptor>) -> ApiResult<Self> ``` **LoginStore API Methods** This allows the LoginStore API to be simplified as follows, making encryption transparent by eliminating the need to pass the key and allowing the methods to return decrypted login objects. ``` pub fn list(&self) -> ApiResult<Vec<Login>> pub fn get(&self, id: &str) -> ApiResult<Option<Login>> pub fn get_by_base_domain(&self, base_domain: &str) -> ApiResult<Vec<Login>> pub fn find_login_to_update(&self, entry: LoginEntry) -> ApiResult<Option<Login>> pub fn update(&self, id: &str, entry: LoginEntry) -> ApiResult<Login> pub fn add(&self, entry: LoginEntry) -> ApiResult<Login> pub fn add_or_update(&self, entry: LoginEntry) -> ApiResult<Login> ``` We will stop Uniffi-exposing the crypto primitives encrypt, decrypt, encrypt_struct and decrypt_struct. Also EncryptedLogin will not be exposed anymore. Checking for the Existence of Logins for a given Base Domain In order to check for the existence of stored logins for a given base domain, we provide an additional store method, has_logins_by_base_domain(&self, base_domain: &str), which does not utilize the EncryptorDecryptor. Another by-change is in the `check_canary` function: here we do not throw anymore if a wrong key is used but return false.
The current Login structure is nested: ``` Login { RecordFields record; LoginFields fields; SecureLoginFields sec_fields; } ``` and thus exposes internal data structuring to the consumer. Since we make the encryption transparent for the consumer (Android, iOS, desktop) here, such a separation no longer makes sense here and above can be simplified to ``` Login { // record fields string id; i64 times_used; i64 time_created; i64 time_last_used; i64 time_password_changed; // login fields string origin; string? http_realm; string? form_action_origin; string username_field; string password_field; // secure login fields string password; string username; } ``` The advantage of eliminating this separation lies, on the one hand, in the simplification of the API and the resulting easier use of the component, and on the other hand, in the easier changeability of the internal data structure. If, for example, we decide later to encrypt additional fields, such a change is possible without having to adapt the consumers.
78bc7eb
to
4c3f04e
Compare
to check whether the database is empty
4c3f04e
to
ec4de55
Compare
The encryption and decryption of credentials is outsourced to a Foreign Trait so that Android, desktop and iOS can each bring their own implementations of encryption, including key management. This makes the Logins API way simpler and cleaner. It is the first step in making AS-Logins desktop-ready.
The new
EncryptorDecryptor
trait replaces the currentEncryptorDecryptor
struct. Instead of using thedecrypt_struct
method, which involves serializing and deserializing the string to be encrypted, this trait uses only byte-based operations and serialization is up to the consumer.We do not Uniffi-expose the crypto primitives
encrypt
,decrypt
,encrypt_struct
anddecrypt_struct
anymore. AlsoEncryptedLogin
will not be exposed anymore.A
ManagedEncryptorDecryptor
will provide anEncryptorDecryptor
implementation which uses the currently used crypto methods, given aKeyManager
implementation to ease adaption for mobile.BREAKING CHANGE
This commit introduces breaking changes to the Logins component:
During initialization, it receives an additional argument, a
EncryptorDecryptor
implementation. In addition, severalLoginsStore
API methods have been changed to not require an encryption key argument anymore, and returnLogin
objects instead ofEncryptedLogin
.Additionally, a new API method has been added to the LoginsStore,
has_logins_by_base_domain(&self, base_domain: &str)
, which can be used to check for the existence of a login for a given base domain.EncryptorDecryptor
With the introduction of the
EncryptorDecryptor
trait, encryption becomes transparent. That means, the LoginStore API receives some breaking changes as outlined above. AManagedEncryptorDecryptor
will provide anEncryptorDecryptor
implementation which uses the currently used crypto methods, given aKeyManager
implementation. This eases adaption for mobile. Furthermore, we provide aStaticKeyManager
implementation, which can be used in tests and in cases where the key is - you name it - static. Constructors Now an implementation of the above property must be passed to the constructors. To do this, the signatures are extended as follows:LoginStore API Methods
This allows the
LoginStore
API to be simplified as follows, making encryption transparent by eliminating the need to pass the key and allowing the methods to return decrypted login objects.New LoginsStore methods:
We will stop Uniffi-exposing the crypto primitives
encrypt
,decrypt
,encrypt_struct
anddecrypt_struct
. AlsoEncryptedLogin
will not be exposed anymore.SyncEngine
The logins sync engine has been adapted for above EncryptorDecryptor trait and therefore does not support
set_local_encryption_key
anymore.Flattened Login Struct
The current Login structure is nested:
and thus exposes internal data structuring to the consumer. Since we make the encryption transparent for the consumer (Android, iOS, desktop) here, such a separation no longer makes sense here and above can be simplified to
The advantage of eliminating this separation lies, on the one hand, in the simplification of the API and the resulting easier use of the component, and on the other hand, in the easier changeability of the internal data structure. If, for example, we decide later to encrypt additional fields, such a change is possible without having to adapt the consumers.
So in addition to the changes mentioned above we will stop Uniffi-exposing the structs
RecordFields
,LoginFields
andSecureLoginFields
.Pull Request checklist
[ci full]
to the PR title.Branch builds: add
[firefox-android: branch-name]
to the PR title.