-
-
Notifications
You must be signed in to change notification settings - Fork 456
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
Add OsRng wasm support #272
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
First I have to say that I know nothing about js 😄. But left a couple of comments.
src/os.rs
Outdated
|
||
#[derive(Debug)] | ||
pub struct OsRng; | ||
|
||
impl OsRng { | ||
pub fn new() -> Result<OsRng, Error> { | ||
Err(Error::new(ErrorKind::Unavailable, "not supported on WASM")) | ||
Ok(OsRng) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice if we could know here if OsRng
is available or not. Would it add a lot of overhead to test here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can check if window.crypto.getRandomValues
、require("crypto")
is available, but there is a certain overhead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not really sure it matters — any of the other system interfaces may succeed with new
but fail on try_fill_bytes
.
src/os.rs
Outdated
HEAPU8.set(array, ptr); | ||
} catch(err) { | ||
if (err instanceof ReferenceError) { | ||
let bytes = require("crypto").randomBytes(len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a fallback for Node.js or something? Could you maybe add a comment?
src/os.rs
Outdated
Ok(()) | ||
} else { | ||
let err: WebError = js!{ return @{ result }.error }.try_into().unwrap(); | ||
Err(Error::with_cause(ErrorKind::Other, "WASM Error", err)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should probably give a Unavailable
error if window.crypto.getRandomValues
is not available (can that happen, or does every implementation of webassembly support this?). And do you know when we can get a QuotaExceededError
?
b.t.w. Other
just got renamed to Unknown
Unexpected
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, to Unexpected
. But I agree, it doesn't look like this is recoverable so it should be Unavailable
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Found an answer: https://w3c.github.io/webcrypto/Overview.html#dfn-Crypto-method-getRandomValues. QuotaExceededError
is returned "If the byteLength of array is greater than 65536". We maybe want to break up larger request, like the implementations of OsRng
on other systems (although I would say an error is reasonable...)
let mut v2 = [0u8; 1000]; | ||
r.fill_bytes(&mut v2); | ||
|
||
assert_ne!(v[..], v2[..]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. I also no next-to-nothing about JS; is this expected to work on most WASM platforms?
src/os.rs
Outdated
Ok(()) | ||
} else { | ||
let err: WebError = js!{ return @{ result }.error }.try_into().unwrap(); | ||
Err(Error::with_cause(ErrorKind::Other, "WASM Error", err)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, to Unexpected
. But I agree, it doesn't look like this is recoverable so it should be Unavailable
.
src/os.rs
Outdated
pub fn try_fill_bytes(&mut self, v: &mut [u8]) -> Result<(), Error> { | ||
Err(Error::new(ErrorKind::Unavailable, "not supported on WASM")) | ||
let len = v.len() as u32; | ||
let ptr = v.as_mut_ptr() as i32; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A 32-bit pointer? Surely that's not going to work on 64-bit platforms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is wasm32
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, then could you at least assert_eq!(size_of::<usize>(), 4)
?
assert_eq!(&sample_slice(&mut r, empty, 0)[..], []); | ||
assert_eq!(&sample_slice(&mut r, &[42, 2, 42], 0)[..], []); | ||
assert_eq!(&sample_slice(&mut r, empty, 0)[..], [0u8; 0]); | ||
assert_eq!(&sample_slice(&mut r, &[42, 2, 42], 0)[..], [0u8; 0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the extra verbosity useful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try removing the first &
; the function returns a Vec
so it's not necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merged, with a tweak to the test. Thanks @quininer. |
Sorry for the hostile tone. This PR was done with the best intentions but this shouldn't have been merged. As its name says, the environment is unknown and the environment shouldn't be assumed to be the web. Also The stdlib faces the same problem and "solves" it by panicking at runtime in every single function that requires some support from the OS or the environment in general. The stdlib also has an unstable feature flag that assumes the presence of a support function provided by the user. This crate should follow the same idiom. |
I agree with @tomaka , I neglect this point. As a remedy, we can provide a |
An |
Thanks for the review @tomaka; I was hoping for extra review but didn't know who to ask. I believe however the worst case is this will simply return |
:)