-
Notifications
You must be signed in to change notification settings - Fork 709
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
Which features work with WASM (WebAssembly)? #918
Comments
The port's incomplete, and possibly in need of a sponsor. If you search through the issues (including closed) you can get a better idea of where it's at. (I'm not associated with this project, I'm just replying as the maintainer appears to be otherwise engaged at the minute.) |
In which wasm platform are you trying to use ring? Browser? Node? Wasmer? Something else? |
For another datapoint, I would also love to use ring with WebAssembly, and am targeting the browser. In particular, I'm trying to use rustls, which depends on ring. |
@briansmith I tried using it for the browser, but indeed get the same error. It seems the C files aren't implemented yet in wasm? I have too little knowledge about |
I intend to add more functionality to wasm builds soon. A few months ago, when I started the port, I couldn't get the wasm32 toolchain to handle some of the ECC code. It seems like the wasm32 backend of clang wasn't quite up to snuff, and/or there was a problem with the wasm32 "linker". I wouldn't be surprised if things are better now. Before I can add more stuff here, I need to merge the latest BoringSSL changes. I'm doing that now. |
I wish I could help with that, but I'm afraid it's outside of my expertise. Anything else I can look into to help? |
As I mentioned above, it would be useful to know which ring features are needed in wasm32. I probably won't have them all working all at once, but one at a time, so it would be useful to prioritize the work. |
I've had success compiling the LIMBS subdirectory to wasm using emscripten. Currently the functionality I at least know I require is montgomery multiplication. If I understand correctly, the port involves writing this assembly code in either C or Rust, correct? |
As far as I see it's mainly the |
I understand that when people talk about "limbs" they mean the underlying bigint math. But, which features (ECDSA signing, ECDSA verification, RSA signing, RSA verification, ECDH, etc.) do you need? Just because something compiles and the tests seem to pass, doesn't mean that it is correct, especially w.r.t. the side-channel mitigations. It's also useful to know which wasm32 environment people are deploying to. Just browsers? Node? Something else? |
Hey Brian, I'm mainly interested in compiling and running the QUIC protocol in both the browser and node environments. I'm planning to leverage existing QUIC implementations written in Rust. I don't know the full list of cryptographic functions QUIC uses, but if you aren't sure either, I'm happy to compile one. Thanks so much. |
I'm deploying to Cloudflare Workers, which should be the same as browser (Chromium). I need RSA verification, I've implemented a full FIDO2 authentication into workers, but it's too slow with the Javascript implementation, so was looking into Rust -> WASM for that reason. Ring seems to be the only mature library for this. UPDATE: Specifically, ECDSA with SHA-256 (ES256) and RSASSA-PKCS1-v1_5 with SHA-256 (RS256) at minimum. |
I'll add my use case as well then, I'm porting a ECDH Triple Diffie–Hellman key exchange to wasm - targeting the browser. I'm using it (implemented in JS atm) for end-to-end encrypted WebRTC signalling. |
My plan is to do AES-GCM first, then RSA, and then make a plan for the rest. Issue #104 is tracking the AES-GCM effort. |
PR #992 is the next step in expanding the wasm32 functionality. It it the first step to allowing ring to use C code in WebAssembly. Going forward I intend to make it unnecessary to have a C compiler for targeting wasm32; this is a stepping stone to that. I expect that somebody could now enable Ed25519 and X25519 support on top of PR #992, guarded by the |
RSA signatures (signing and verifying) is in PR #996. |
Since #992 and #996 have been done it's closer to potentially work in WASM, however it's quite hard to test the current progress for Webassembly.
Is there a way to disable EC at compile-time from Ring so that I can test the JWT RSA code path within WebAssembly? |
My plan is to implement those functions in a way that works on all targets, including WebAssembly. I don't intend to spend effort to work around the lack of the functions in the interim because I don't have time to do one and then the other.
What tools were you using to get this output? I usually target browsers for webassembly and I don't get nearly as useful error messages; I just get some vague error about "env" that doesn't list the missing symbols. |
Thanks that makes sense. To get that output I used The trace was obtained by running |
For reference, here's how to go about testing whether a particular module works in wasm via wasm-bindgen-test. I have particular interest in the key agreement module, so here's a patch that enables a single, failing browser test. From 8cddf22bc0b2d9227dc65e8075118534071a81ec Mon Sep 17 00:00:00 2001
From: Anthony Miyaguchi <[email protected]>
Date: Fri, 22 Jan 2021 16:20:30 -0800
Subject: [PATCH] Enable failing agreement tests (dependent on ecdsa)
---
build.rs | 9 +++++----
tests/agreement_tests.rs | 8 ++++++++
2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/build.rs b/build.rs
index f2db9a841..5517dcded 100644
--- a/build.rs
+++ b/build.rs
@@ -45,10 +45,11 @@ const RING_SRCS: &[(&[&str], &str)] = &[
(&[AARCH64, ARM, X86_64, X86], "crypto/crypto.c"),
(&[AARCH64, ARM, X86_64, X86], "crypto/curve25519/curve25519.c"),
- (&[AARCH64, ARM, X86_64, X86], "crypto/fipsmodule/ec/ecp_nistz.c"),
- (&[AARCH64, ARM, X86_64, X86], "crypto/fipsmodule/ec/ecp_nistz256.c"),
- (&[AARCH64, ARM, X86_64, X86], "crypto/fipsmodule/ec/gfp_p256.c"),
- (&[AARCH64, ARM, X86_64, X86], "crypto/fipsmodule/ec/gfp_p384.c"),
+ (&[], "crypto/curve25519/curve25519.c"),
+ (&[], "crypto/fipsmodule/ec/ecp_nistz.c"),
+ (&[], "crypto/fipsmodule/ec/ecp_nistz256.c"),
+ (&[], "crypto/fipsmodule/ec/gfp_p256.c"),
+ (&[], "crypto/fipsmodule/ec/gfp_p384.c"),
(&[X86_64, X86], "crypto/cpu-intel.c"),
diff --git a/tests/agreement_tests.rs b/tests/agreement_tests.rs
index 416201537..ae7891802 100644
--- a/tests/agreement_tests.rs
+++ b/tests/agreement_tests.rs
@@ -16,7 +16,15 @@ extern crate alloc;
use ring::{agreement, error, rand, test, test_file};
+#[cfg(target_arch = "wasm32")]
+use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
+
+#[cfg(target_arch = "wasm32")]
+wasm_bindgen_test_configure!(run_in_browser);
+
#[test]
+#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
+#[cfg(any(not(target_arch = "wasm32"), feature = "wasm32_c"))]
fn agreement_traits() {
use alloc::vec::Vec;
--
2.30.0
Run the tests using % wasm-pack test --firefox --headless -- --features wasm32_c --test agreement_tests This fails with the following error: JavaScript error: http://127.0.0.1:50603/wasm-bindgen-test, line 1: TypeError: Error resolving module specifier “env”. Relative module specifiers must start with “./”, “../” or “/”. Find the path to the built wasm module from the test output and inspect the imports, which match with most of the other comments here: % wasm2wat target/wasm32-unknown-unknown/debug/deps/agreement_tests-0e45a4224d6f1446.wasm | grep 'import "env"'
(import "env" "GFp_nistz256_add" (func $GFp_nistz256_add (type 6)))
(import "env" "GFp_nistz256_mul_mont" (func $GFp_nistz256_mul_mont (type 6)))
(import "env" "GFp_nistz256_sqr_mont" (func $GFp_nistz256_sqr_mont (type 5)))
(import "env" "GFp_nistz256_point_double" (func $GFp_nistz256_point_double (type 5)))
(import "env" "GFp_nistz256_neg" (func $GFp_nistz256_neg (type 5)))
(import "env" "GFp_bn_mul_mont" (func $GFp_bn_mul_mont (type 19))) These files only exist in generated assembly, so a cross-architecture implementation of these functions would solve most of the issues here. |
@briansmith My use case is verifying the ECDSA signature on a JWT with jsonwebtoken in a browser. The tokens come from an issuer that mandates use of ECDSA. |
For another use case, I'm trying to receive an AEAD-sealed message on a browser. (For technical reasons I can't use the built-in Building for the
Edit: I misunderstood the status of the implementation; AES support still requires the |
Adding this line: |
I am testing "0.17.0-alpha.11" which appears to have far less exports but still produces some. My wasm environment requires no exports other than the custom defined ones (none useful to ring). It would be really nice to have a feature flag to disable all wasm exports. The changes I needed to make to get it working:
`[target.'cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", target_env = ""))'.dependencies] [target.'cfg(target_arch = "wasm32")'.dev-dependencies] |
It seems that for now you can use jwt-compact crate for using JWT in WASM. It is explicitly tested for WASM compatiblity |
What about aead functionality, how is web assembly support looking there? |
@rhomber is there anything you can share about how you got things to work? I'm running into errors like More info here: #1453 (comment) |
This mostly depends on resolving #1455 and then expanding the test coverage. |
AFAICT the entire feature set works in WASM now. |
Yep, compiles fine with |
Any news on this? Trying to use ring on CF Workers fails with the build. Trying to build the repo with
Adding the crate-type and you'd get an error from getrandom:
Finally explicitly enabling that feature when declaring the dependency, the error:
|
@jyrihogman I think you need to set TARGET_CC or equivalent to point to a clang that supports wasm32. On macOS, you can't use Apple Clang; you must use LLVM clang. |
If you are encountering failed ring builds and getrandom asking you to enable the js feature, you juste have to enable |
In your own project's Cargo.toml, you can add this if you are targeting web environments (web pages, browser extensions, etc.):
or for non-web situations, you can use the "custom" feature:
Putting this in your project's top-level Cargo.toml will work even for your dependencies, so you don't need to fork Rustls or other ring-based projects to enable the features. Cargo decides which features to enable at the time it builds ring by taking the union of all activated features in all relevant Cargo.toml files in the build. |
I'm trying to write a WASM module which uses ECDSA in part of its communication protocol with a backend server. I was hoping to use ring for this.
Various functions from ring::signature e.g. verify, result in the line
import * as __wbg_star0 from 'env';
being generated in the .js file generated by wasm-bindgen. This prevents my browser loading the WASM module and it gives the message:
Error resolving module specifier: env
Is ECDSA sign/verify supported for WASM. If so, how do I use it?
The text was updated successfully, but these errors were encountered: