tink-rust icon indicating copy to clipboard operation
tink-rust copied to clipboard

Non-blocking API

Open chanced opened this issue 2 years ago • 0 comments

A non-blocking API would be great. The crate is not that ergonomic to use in a project that relies on the tokio runtime. This is due to the fact that you can not spawn a tokio::Runtime from within a runtime.

    #[tokio::test]
    async fn test_construction() -> Result<(), Box<dyn std::error::Error>> {
        tink_aead::init();
        dotenv::dotenv().unwrap();
        let key_uri = std::env::var("GOOGLE_KMS_KEY_URI")?;
        let credential_path_var = std::env::var("GOOGLE_APPLICATION_CREDENTIALS").unwrap();
        let credential_path = std::path::Path::new(&credential_path_var);
        let client =
            tink_gcpkms::GcpClient::new_with_credentials(&key_uri, credential_path).unwrap();
        let backend = client.get_aead(&key_uri).unwrap();
        // ...
        Ok(())
    }
thread 'key_manager::tests::test_construction' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.'

Also, dyn <Primitive> are cumbersome without Send + Sync.

/// Returns a [`tink_core::Aead`] primitive from the given keyset handle.
pub fn new(h: &tink_core::keyset::Handle) -> Result<Box<dyn tink_core::Aead>, TinkError> {
    new_with_key_manager(h, None)
}

I can get around the first issue with an actor and spawning a thread, but lack of Send + Sync on the primitives is a tough one.

I believe there are a few changes that would need to be made:

  1. Create a feature flag, something like "non-blocking" to avoid breaking changes.
  2. Add async-trait as a dependency
  3. Add an AeadEnvelope trait:
#[async_trait::async_trait]
pub trait AeadEnvelope {
    async fn encrypt(
        &self,
        plaintext: &[u8],
        additional_data: &[u8],
    ) -> Result<Vec<u8>, TinkError>;

    async fn decrypt(
        &self,
        ciphertext: &[u8],
        additional_data: &[u8],
    ) -> Result<Vec<u8>, TinkError>;
}
  1. A good bit of the dyn <Primitive> will likely need to be dyn 'static + <Primitive> + Send + Sync
  2. Possibly provide implementations for the integrations but that's not as important as the above.

Thank you for your work and effort porting this.

chanced avatar Jan 19 '23 00:01 chanced