kanidm/webauthn-rs

Pure Rust cryptography backend

Opened this issue · 5 comments

Is your feature request related to a problem? Please describe.

Not exactly a problem, but would swappable cryptography backends be in scope for this project?
Or is this something that you'd rather not bother with.

I do get why OpenSSL is a nice choice, since you can just point at it and say "our crypto provider. You already know it", but the portability story to things like Windows is a bit painful.

Describe the solution you'd like

A set of traits via which the crypto provider can be made pluggable, that way someone can develop a Rust-native cryptography provider.

Describe alternatives you've considered

N/A

Additional context

The README mentions that OpenSSL is the only Rust-available cryptography library which can construct keys from their raw parts. Well, that isn't 100% correct.
The p256 crate supports this, if a bit convoluted.

You need to:

  • Create an EncodedPoint from the X and Y coordinates
  • Convert it into an AffinePoint
  • Convert the AffinePoint into a PublicKey

But it does work!
And about RSA, both, the rsa crate and ring, support construction from raw components.

Is your feature request related to a problem? Please describe.

Not exactly a problem, but would swappable cryptography backends be in scope for this project? Or is this something that you'd rather not bother with.

I do get why OpenSSL is a nice choice, since you can just point at it and say "our crypto provider. You already know it", but the portability story to things like Windows is a bit painful.

We know the windows story is a bit rough.

The real limit here is time. Swappable backends is a nice idea, but we'd need a pretty big effort to actually do it. If we did, we'd only support the openssl backend as a project anyway, so third parties would need to support their own externally.

Describe the solution you'd like

A set of traits via which the crypto provider can be made pluggable, that way someone can develop a Rust-native cryptography provider.

Describe alternatives you've considered

N/A

Additional context

The README mentions that OpenSSL is the only Rust-available cryptography library which can construct keys from their raw parts. Well, that isn't 100% correct. The p256 crate supports this, if a bit convoluted.

You need to:

* Create an `EncodedPoint` from the X and Y coordinates

* Convert it into an `AffinePoint`

* Convert the `AffinePoint` into a `PublicKey`

But it does work! And about RSA, both, the rsa crate and ring, support construction from raw components.

In the past they did not :)

A set of traits via which the crypto provider can be made pluggable, that way someone can develop a Rust-native cryptography provider.

The devil is in the details as well with all this:

An alternative cryptography backend isn't just "write the code": it's something we'd need to support going forward, and is another variable in our already large build matrix (currently 33 targets; each new backend would increase that by 30 targets).

This feels like an X-Y problem, but I think the main point you're making is:

I do get why OpenSSL is a nice choice, since you can just point at it and say "our crypto provider. You already know it", but the portability story to things like Windows is a bit painful.

Providing a choice of cryptographic backend provider risks not being a technical consideration of security trade-offs, but a choice based on the path of least resistance: where someone who couldn't (or wouldn't) setup vcpkg or install the openssl-devel package ends up picking the option which required neither of those.

I've spent a lot of time improving the Windows (and aarch64-pc-windows-msvc) build process for rust-openssl, vcpkg-rs and webauthn-rs. It's actually not that bad now for "native" builds if you've setup vcpkg properly – it just hasn't been documented very well, and there's a significant volume of bad advice in the rust-openssl issue tracker filling that void.

I feel that making the build process well polished, follow best-practices1 and well documented2 is the better way to deal with that issue. We can do our part, but really a lot of that effort belongs upstream.

Footnotes

  1. rust-openssl is one of a few Rust FFI crates which does this well, and doesn't have nasty surprises

  2. rust-openssl needs improvement here, and I have an open PR for this

To be honest, the security of the rsa crate has been doubted for a long time (even by myself, which is why I don't use it beyond keygen), simply by virtue of them using a slightly modified version of num-bigint which is anything but suitable for cryptographic usecases.

As for p256, the disclaimer is fair because LLVM can mess up all careful programming. Damn modern compilers and their optimizations.

My main idea was to probably use ring. The reason for this is because it compiles easier than OpenSSL while being audited as part of the rustls audits.
I'm most definitely not trying to go the path of least resistence here, rather I want to find a tradeoff, since I personally haven't experienced issues with compiling it on Windows (cross-compiling is a different discussion, never tried that).


Also about the backends, the issue might needs its title changed to something like "Enable alternative cryptography backends", where webauthn-rs would only abstract away cryptographic operations and offer a set of traits.

The only officially supported backend would remain the OpenSSL backend. Just to allow for other alternative implementors to provide crypto primitives.

My main idea was to probably use ring. The reason for this is because it compiles easier than OpenSSL while being audited as part of the rustls audits.

Ironically we opted not to use ring, because it breaks on anything that isn't x86_64/aarch64 with annoying regularity.

I think however, what you are proposing to make a "cryptography" trait, would work.

We might end up ditching openssl for the rust-crypto ecosystem because we've had too many issues getting things into rust-openssl.