mozilla / application-services

Firefox Application Services
https://mozilla.github.io/application-services/
Other
620 stars 227 forks source link

EncryptorDecryptor Trait for Logins Component #6469

Open jo opened 3 weeks ago

jo commented 3 weeks ago

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 current EncryptorDecryptor struct. Instead of using the decrypt_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 and decrypt_struct anymore. Also EncryptedLogin will not be exposed anymore.

A ManagedEncryptorDecryptor will provide an EncryptorDecryptor implementation which uses the currently used crypto methods, given a KeyManager 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 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

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.

TODO