Skip to content

Conversation

JakeDern
Copy link

Which issue does this PR close?

Closes #413.

Rationale for this change

Many companies, including my current employer, are picky about what cryptographic implementations may be used. This PR seeks to accomplish two things:

  1. Make it possible to have no default crypto provider, such as ring, in the dependency tree
  2. Make it possible to bring your own crypto provider

What changes are included in this PR?

This is heavily WIP - I'm just opening this to make it clear how the approach with generic types would work vs an implementation that would use dyn instead at the expense of having to allocate and copy the outputs of various crypto implementations.

  • Add a CryptoProvider trait
  • Add an optional RingProvider implementation based on the ring feature

Are there any user-facing changes?

Yes, several including:

  • Making builders for clouds that need crypto generic
  • Making default::Default implementations dependent on the ring feature
  • Making new() require a crypto provider

Copy link
Contributor

@tustvold tustvold left a comment

Choose a reason for hiding this comment

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

Took a quick look, some comments

  • I think Object safety is pretty important, given the computed types are fixed width it should be possible to use [u8; 32] or similar to avoid allocations (although given the operations involved an allocation is likely irrelevant)
  • We should avoid changing the signature of new as this will break lots of code, instead we could add a new constructor, e.g. new_with_crypto or something

src/crypto.rs Outdated
type DynError = Box<dyn std::error::Error + Send + Sync>;

#[derive(Debug)]
pub struct Error {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it'd be better to just use object_store::Error, whilst it contains variants that aren't relevant, I don't think this matters

src/crypto.rs Outdated
pub trait CryptoProvider: Send + Sync + Debug + 'static {
fn digest_sha256(bytes: &[u8]) -> Result<impl AsRef<[u8]>, Error>;
fn hmac_sha256(secret: &[u8], bytes: &[u8]) -> Result<impl AsRef<[u8]>, Error>;
fn hex_digest(bytes: &[u8]) -> Result<String, Error> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably don't need this to be here unless you expect people to override it

}
}

pub mod openssl_crypto {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would personally prefer people to add additional providers out of tree if they need them. I'm not massively excited about adding a dependency on openssl, optional or not.

Copy link
Author

Choose a reason for hiding this comment

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

Yep, will take this out - Was just trying out a couple of providers to see how they compare and if the trait was flexible enough

@JakeDern
Copy link
Author

@tustvold I have a pretty complete implementation here. Other than more docs and bits of cleanup along those lines, the last major bit I haven't accounted for is the Rsa key stuff for GCP credentials.

This is (today) specific to GCP and appears at first glance to be quite a bit more complicated to put into an object safe trait due to the requirement to create an intermediate RsaKeyPair equivalent type that you can then re-use.

I'm assuming we'd want to also encapsulate that into the trait, but I just want to raise it for discussion. Maybe there's a straightforward way to do this that I don't know, I only have a few months experience with rust. Usually I'd have something in the interface that returns impl MyRsaKeyPairTrait that I could hold the library specific state in, but of course that won't be object safe anymore.

Let me know what your thoughts are and thanks again for working with me on this! I know it's a lot of mental overhead, so I appreciate it!

@JakeDern
Copy link
Author

@tustvold friendly ping on the above - Please let me know if you have thoughts about whether the GCP certificate credential stuff should be included in this trait and if you have any ideas on a reasonable object safe way to do so. Thanks again for your time!

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.

Change crypto provider from ring to aws-rust-lc

2 participants