rust-random / getrandom Goto Github PK
View Code? Open in Web Editor NEWA small cross-platform library for retrieving random data from (operating) system source
License: Apache License 2.0
A small cross-platform library for retrieving random data from (operating) system source
License: Apache License 2.0
Line 105 in 199b115
Since rust-lang/rust#60139 is still open, we probably don't want to do anything about this yet. In this case however we also need to disable rand tests (see this failure).
There isn't a lot of documentation on how to actually use the crate. I used the example from the README.md page, but its throwing errors because its returning a type of [u8;32] instead of the enum Result. I've never used Result so forgive me for not knowing much about it, but I can't seem to get it to work correctly.
I really want to use this crate, as its minimal and its exactly what I need for another crypto project I am working on.
Could you add a full example on how you would generate random bytes as the one in the readme does not work (tested on Mac OS and Windows). Do I have to import std::result::Result as I tried that with no success? I tried messing around with the code and can not get it to work at all.
I then tried compiling with nightly and same thing.
It expects the enum std::result::Result to return, not the array of bytes. Maybe I am just doing something wrong, but it would really help if there was a full example file.
So the master has been switch to using cfg-if v1 but the getrandom v0.2.0 on crates.io is still on the older version. Now that rand v0.8.0 has been released using cfg-if v1 it would be nice to have a published version of getrandom that has done the same.
If we are to make this crate independent of rand_core
, then we need to include an error type here.
We could simply copy the one rand_core
uses; I think something simpler and equivalent on no_std
may be preferable however. A quick look at the code shows that where we do include a cause, we are mostly just using an integer error code. Whether it is even worth forwarding the cause is another question.
See: rust-lang/rust#52609
Here, we create a File
from a raw fd. However, as this object is created on the stack, at the endo the function, the file will be dropped, and thus closed.
This means that on systems using a shared FD, the second call to getrandom
will fail. This can be fixed by just storing a File
instead of a RawFd
in static memory.
the trait `std::error::Error` is not implemented for `getrandom::error::Error`
Why error being a normal error is platform-dependent?
@burdges in rust-random/rand#991:
There exist wasm targets where getrandom should never work, which may warrant a comment somewhere.
Current implementation of rdrand code fails to compile if the user does not enable the rdrand
feature during compilation. Instead, the code should enable the feature for the relevant portions of the code itself with #[target_feature(enable="rdrand")]
.
Not sure if this is the correct place to discuss this or whether this is a problem at all.
In Microsoft's documentation for RtlGenRandom, it states:
When you have finished using the random number, free the RandomBuffer buffer by calling the SecureZeroMemory function.
Is this done/called automatically in this crate?
Also, it has a warning:
The RtlGenRandom function is available for use in the operating systems specified in the Requirements section. It may be altered or unavailable in subsequent versions. Instead, use the CryptGenRandom function.
And CryptGenRandom is deprecated. I already read the issue thread about why you don't want to use BCryptGenRandom rn because it doesn't support Windows XP, but I honestly think the change should be made soon. BCryptGenRandom works on minimum of Windows Vista.
See this issue: rust-lang-nursery/lazy-static.rs#150
I think we can relatively easily replace code here with something like this:
fn is_rdrand_supported() -> bool {
use core::arch::x86_64::__cpuid;
use std::sync::atomic::{AtomicUsize, Ordering};
static RDRAND: AtomicUsize = AtomicUsize::new(0);
const RDRAND_FLAG: u32 = 1 << 30;
const STATE_FLAG: usize = 1 << 1;
const RESULT_FLAG: usize = 1 << 0;
let flags = RDRAND.load(Ordering::Relaxed);
if (flags & STATE_FLAG) == 0 {
let leaf1_ecx = unsafe { __cpuid(1).ecx };
if leaf1_ecx & RDRAND_FLAG != 0 {
// rdrand is supported
RDRAND.store(RESULT_FLAG | STATE_FLAG, Ordering::Release);
true
} else {
// rdrand is not supported
RDRAND.store(STATE_FLAG, Ordering::Release);
false
}
} else {
(flags & RESULT_FLAG) != 0
}
}
In the worst-case scenario we may call CPUID several times instead of just one, but I don't think it's a big deal. Also it will remove spin
crate from our dependency tree, which will help a bit with std
inclusion.
cc @josephlr
Sorry to be the bearer of versioning news, 0.1.10
contains a backwards-incompatible change with respect to 0.1.8
and so on - the feature flags around error_impls
changed, and had been accidentally(?) including error_impls
for specific OSes regardless of std
being selected or not.
The change around feature flags makes sense, but without bumping major versions, version 0.1.10
can cause breakages: see the end of the log here. The missing impl is because minisign
depends on getrandom = "0.1.3"
, where 0.1.10
should be a backwards compatible update, but is not due to the missing trait. We can work around that by specifying std
, but I wanted to make sure y'all knew about this.
Discussed in rust-random/rand#699, we may use RDRAND as a fallback generator. This is already used by OsRng
for SGX where no other generators are available.
We could depend on the rdrand crate, but my preference is to avoid dependence on rand_core
, which implies we would need another implementation (probably just as an internal module).
License note: the rdrand code uses the ISC licence; I think this means we can simply relicence this under MIT+APLv2, though we should of course mention @nagisa's copyright. (Also note: the MIT license arguably includes a patent grant anyway; probably the ISC licence is equivalent.)
It would mean that project will use a single CI service instead of two and CI will have a nicer integration with GitHub UI.
Relevant issue: rust-random/rand#1066
In #180 we have migrated to GitHub Actions almost all tests except related to WASM and Emscripten.
I think we can replace TLS for several targets by using a mutable static RawFd
initialized via std::sync::Once
. I think it should be safe to read from /dev/urandom
using a single file descriptor from several threads without any synchronization, but it's better to check it. A small experiment shows that reading a huge amount of random data in one thread does block other threads.
Right now, stdweb
depends on wasm-bindgen
so it doesn't really make a whole lot of sense to have two seperate implementations in getrandom
for this.
A better approach might just be to depend on the web_sys
crate from the wasm-bindgen
repo and eliminate the need for separate wasm32 features.
I'm not sure how this would work with Node, but for Client Web, we could just use Crypto::get_random_values_with_u8_array
A project i'm trying to build fails with All entropy sources failed (permanently unavailable); cause: OsRng: support for wasm32 requires emscripten, stdweb or wasm-bindgen (permanently unavailable)
, though getrandom
says it supports __wasi_random_get
Currently, a vendored getrandom
archive includes 40! dependencies and 20MB on disk. This is not a problem when people simply using it as a crate, because all of those dependencies will be omitted, but in case of a vendored archive use case it ends up as pretty serious bloat.
Is there a way to reduces the number of indirect dependencies?
Related to #17
I have the following deps for my WASM project (it uses easy_reader to read random lines from a text file).
stdweb = "0.4.20"
getopts = "0.2"
rand = {version = "0.7", features = ['stdweb']}
easy_reader = "0.5.0"
yew = { path = "../.." }
I think the line which required the stdweb feature was reader.random_line()
but I am not sure if that will work with rand 0.8 and it says that I should change the getrandom crate instead but how can I verify that it works and will it work today already if I tried to remove the rand 0.7 dependency and use getrandom instead?
What I am compiling to WASM is the following:
let mut c = Cursor::new(Vec::new());
let str42 = include_str!("spook.lines").as_bytes();
// // Write into the "file" and seek to the beginning
c.write_all(str42).unwrap();
c.seek(SeekFrom::Start(0)).unwrap();
let mut reader = EasyReader::new(c).unwrap();
let _res = reader.build_index();
let tmpspooks = reader.random_line().unwrap().unwrap()...
I read that the way I do it might be removed from rand 0.8 if I understand correctly.
"stdweb implies getrandom/stdweb to enable getrandom support on wasm32-unknown-unknown (will be removed in rand 0.8; activate via getrandom crate instead)
wasm-bindgen implies getrandom/wasm-bindgen to enable getrandom support on wasm32-unknown-unknown (will be removed in rand 0.8; activate via getrandom crate instead)"
I just started to get CI breaks today with 0.1.9, saying that wasm32-unknown-unknown is an unsupported platform, but things were fine before today.
Does the new version need to be yanked and then published as 0.2.0?
The assumption that it does a short read for long buffers isn't always true. After reviewing the code in the NetBSD kernel we decided to adopt this behaviour moving forward (because it seems safer after reviewing real-world code using it), but older NetBSD releases will simply return E2BIG if more than 256 bytes are requested.
The semantics should be the same as getentropy(), which does loop on 256 byte chunks. The only difference is that the output size should be checked (however, the NetBSD kernel at least will never return short reads when <=256 bytes are requested, and will otherwise always return 256 bytes).
The re-addition of the default-implementations of std::error::Error without the std feature got all the relevant Linux platforms, but missed Windows, making it still a breaking change. I'm experiencing this issue downstream from bcrypt, which no longer compiles on Windows without overriding the getrandom dep.
IIUC both functions use the same algorithm under the hood (also see this). The main difference is that BCryptGenRandom
will not work on Windows XP, but otherwise it looks like BCryptGenRandom
should be preferred. IIRC Rust explicitly does not support Windows XP anymore, so it should not matter.
@chouquette
Can you help here? In rust-lang/rust#60260 you have used BCryptGenRandom
for UWP targets and left RtlGenRandom
for non-UWP targets. Is there a reason for that?
Stdweb seems to be abandoned, making the duplicate wasm feature options redundant.
https://github.com/RustSec/advisory-db/blob/master/crates/stdweb/RUSTSEC-2020-0056.md
It has been proposed to include roughly this code into the std
lib. This is an issue to summarise the proposal and track future development.
Draft RFC: https://github.com/dhardy/rfcs/blob/system-random/text/0000-system-random.md
Discussions:
The Windows implementation for getrandom_inner()
calls RtlGenRandom
. However, the length parameter is a ULONG
(i.e. a u32
).
Thus, if a buffer of length 2^32
is passed to getrandom()
on Windows, the call dest.len() as ULONG
truncates the value to 0. This results in the function seeming to succeed, but without writing any data.
Thanks to @briansmith's ring implementation, for pointing this out.
First, thanks for splitting out this functionality from rand
/rand_os
, it's very pleasant to use!
Second, I'm wondering if it'd make sense to consider including getrandom_infallible()
API that was basically getrandom().expect("...")
. That's what most (all?) of my callers are doing ATM.
If the buffer passed to the Linux getrandom(2)
system call is longer than 256 bytes, the buffer can be partially written. This happens when the system call is interrupted, which becomes more likely the longer the buffer is.
The current implementation returns an error in this case, when it should just try the call again, attempting to fill the remainder of the buffer.
Thanks to @briansmith's ring implementation, for pointing this out.
In the process of addressing #94, we realized that some of the changes we want to do would require breaking backwards compatibility. If we are going to release a version 0.2, we should consider other changes to getrandom
.
A potential list is below. @dhardy and @newpavlov feel free to edit this to include your own ideas.
std
traits if the std
feature is enabled (see #94 and #96)
wasm-bindgen -> bindgen
, would make it much easier to use js_sys
or web_sys
.wasm32-unknown-unknown
(with no explicit features). Options are:
bindgen
wasm32
error codes
hermit
, l4re
, and uefi
and just use this feature instead, as these platforms (especially UEFI) have multiple ways to get randomness.If you have suggestions, please comment!
Currently for wasm32-unknown-unknown
target we have two features stdweb
and wasm-bindgen
. In future the following changes can happen:
stdweb
will become compatible with wasm-bindgen
, which will allow us to deprecate stdweb
feature. See: koute/stdweb#318wasm32-unknown-unknown
target. See: rustwasm/team#38Following those changes may cause getrandom
build breakage for some users, e.g. even if we'll write stdweb = ["wasm-indgen"]
in Cargo.toml
it may break build for users of older stdweb
versions. Thus I believe we should think about how those changes can be handled in future.
I see 3 options:
rand
crates.I'm building a project (bevy
) on multithreaded wasm via web workers and this library crashes with exception:
Uncaught (in promise) TypeError: Failed to execute 'getRandomValues' on 'Crypto': The provided ArrayBufferView value must not be shared.
Indeed the spec does not allow generating random numbers into a memory backed by SharedArrayBuffer
.
I managed to fix this issue by generating numbers into an intermediate buffer allocated by javascript:
for chunk in dest.chunks_mut(65536) {
let arr = js_sys::Uint8Array::new_with_length(chunk.len() as u32);
n.get_random_values(&arr);
arr.copy_to(chunk);
}
This introduces some overhead, but I'm not sure if there is a standard way to check whether rust's memory is backed by SharedArrayBuffer
.
I can submit a PR for this, so let me know how you want me to proceed.
Inspired by @dhardy's comment rust-lang/rust#62082 (comment)
This would simply remove the dummy implementation, causing a compiler error on unsupported platforms. This makes it much easier to detect platform support issues (as a compiler error is permeable to a run time error). This would also make it clear that when porting libstd
or rand
to a different platform, an implementation in getrandom
is needed.
For example, @newpavlov's code in rust-lang/rust#62082 would be changed to:
let mut buf = [0u8; 16];
// Using a constant value is acceptable on whitelisted targets.
#[cfg(not(target = "wasm32-unknown-unknown"))]
if let Err(err) = getrandom::getrandom(&mut buf) {
panic!("getrandom failure: {:?}", err)
}
let n = u128::from_ne_bytes(buf);
Cell::new([n as u64, (n >> 64) as u64])
Note that this would be a breaking change, so it would require 0.2
Hi, was trying to run memory sanitizer (RUSTFLAGS='-Zsanitizer=memory -Zsanitizer-memory-track-origins'
) for my tests, but got this:
error: failed to run custom build command for `getrandom v0.1.15`
Caused by:
process didn't exit successfully: `<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build` (exit code: 77)
--- stderr
Uninitialized bytes in __interceptor_memchr at offset 0 inside [0x701000000000, 4)
==29302==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x55e418d5458a (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0xa358a)
#1 0x55e418d5bb12 (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0xaab12)
#2 0x55e418d424d7 (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0x914d7)
#3 0x55e418d3bd1c (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0x8ad1c)
#4 0x7f2d678ecc7c (/nix/store/9df65igwjmf2wbw0gbrrgair6piqjgmi-glibc-2.31/lib/libc.so.6+0x23c7c)
#5 0x55e418cbe189 (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0xd189)
Uninitialized value was created by a heap allocation
#0 0x55e418cc902d (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0x1802d)
#1 0x55e418d5bae7 (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0xaaae7)
SUMMARY: MemorySanitizer: use-of-uninitialized-value (<basedir>/target/debug/build/getrandom-0105b7f3c822c0c9/build-script-build+0xa358a)
Exiting
Due to let this = Function::new("return this").call(&JsValue::undefined());
I'm currently seeing an error using a sensible CSP:
EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' 'wasm-eval'".
js_sys
uses a more involved method to fetch the global object that eventually falls back to the unsafe version.
https://rustwasm.github.io/wasm-bindgen/api/src/js_sys/lib.rs.html#4450-4523
Can either js_sys
be added as a dependency or this logic (or a subset) be reproduced here?
let mut buf = [0u8; 32];
getrandom::getrandom(&mut buf);
returns an array of zeroes when executing in stdweb
There are no tags in this repo for releases 0.1.7 and 0.1.8. Would be great to have tags that match the source on crates.io.
Mirror rust-random/rand#730
error[E0432]: unresolved import libc::__error
--> /home/vmuser/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.1.13/src/util_libc.rs:22:13
|
22 | use libc::__error as errno_location;
| ^^^^^^-------^^^^^^^^^^^^^^^^^^
| | |
| | help: a similar name exists in the module: ferror
| no __error
in the root
error: aborting due to previous error
For more information about this error, try rustc --explain E0432
.
error: Could not compile getrandom
.
Hi,
Version 0.1.7
broke backwards compatibility with older rust compilers (like the one shipped with OS and ones that can be safely bootstrapped)
without bumping the major version.
This broke a bunch of stuff in https://github.com/rust-bitcoin/rust-bitcoin
Our users want very specific use cases that require older rust compilers.
I understand if you want to use newer rust code and you don't want to support older versions(this changes broke everything earlier than 1.32) I just ask if 0.1.7 can be yanked and bumped to 0.2 because this is a big break (before 0.1.7 this crate supported compiler versions as early as 1.16)
Would appreciate a response. Thanks!
This may well be a false positive with TSAN and false issue, but I figured I'd report it just in case its real. This was originally detected via Tokio's TSAN CI tests, in tokio-rs/tokio#1358 (comment) .
I went ahead and created a minimized, out of tokio tree, repro for this here:
https://github.com/dekellum/rng-tsan-min-repro
See the README for repro-steps. I have reproduced with these two rustc --version
s:
rustc 1.38.0-nightly (83e4eed16 2019-07-14)
rustc 1.38.0-nightly (4560cb830 2019-07-28)
See test.out for failing output form ThreadSanitizer:
WARNING: ThreadSanitizer: data race (pid=28325)
Read of size 8 at 0x559290ec6050 by thread T3:
#0 lazy_static::lazy::Lazy<T>::get /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.3.0/src/inline_lazy.rs:35 (rng_tsan_min_repro-6bc72839c6f31b66+0x1235d8)
#1 <c2_chacha::guts::init_chacha::IMPL as core::ops::deref::Deref>::deref::__stability /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/c2-chacha-0.2.2/<::lazy_static::__lazy_static_internal macros>:17 (rng_tsan_min_repro-6bc72839c6f31b66+0x1235d8)
#2 <c2_chacha::guts::init_chacha::IMPL as core::ops::deref::Deref>::deref /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/c2-chacha-0.2.2/<::lazy_static::__lazy_static_internal macros>:19 (rng_tsan_min_repro-6bc72839c6f31b66+0x1235d8)
#3 c2_chacha::guts::init_chacha /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.0/<::ppv_lite86::x86_64::dispatch_light128 macros>:35 (rng_tsan_min_repro-6bc72839c6f31b66+0xd7a30)
#4 c2_chacha::guts::ChaCha::new /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/c2-chacha-0.2.2/src/guts.rs:60 (rng_tsan_min_repro-6bc72839c6f31b66+0xd7a30)
#5 <rand_chacha::chacha::ChaCha20Core as rand_core::SeedableRng>::from_seed /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_chacha-0.2.1/src/chacha.rs:94 (rng_tsan_min_repro-6bc72839c6f31b66+0xd7a30)
#6 rand_core::SeedableRng::from_rng /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_core-0.5.0/src/lib.rs:359 (rng_tsan_min_repro-6bc72839c6f31b66+0xd835a)
#7 rand::rngs::thread::THREAD_RNG_KEY::__init /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.0/src/rngs/thread.rs:64 (rng_tsan_min_repro-6bc72839c6f31b66+0xde031)
#8 core::ops::function::FnOnce::call_once /rustc/4560cb830fce63fcffdc4558f4281aaac6a3a1ba/src/libcore/ops/function.rs:235 (rng_tsan_min_repro-6bc72839c6f31b66+0xdb1b7)
#9 std::thread::local::lazy::LazyKeyInner<T>::initialize /rustc/4560cb830fce63fcffdc4558f4281aaac6a3a1ba/src/libstd/thread/local.rs:285 (rng_tsan_min_repro-6bc72839c6f31b66+0xd73ae)
#10 std::thread::local::fast::Key<T>::try_initialize /rustc/4560cb830fce63fcffdc4558f4281aaac6a3a1ba/src/libstd/thread/local.rs:426 (rng_tsan_min_repro-6bc72839c6f31b66+0xde5bd)
#11 std::thread::local::fast::Key<T>::get /rustc/4560cb830fce63fcffdc4558f4281aaac6a3a1ba/src/libstd/thread/local.rs:411 (rng_tsan_min_repro-6bc72839c6f31b66+0xde79c)
#12 rand::rngs::thread::THREAD_RNG_KEY::__getit /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.0/<::std::thread::local::__thread_local_inner macros>:28 (rng_tsan_min_repro-6bc72839c6f31b66+0xde279)
#13 std::thread::local::LocalKey<T>::try_with /rustc/4560cb830fce63fcffdc4558f4281aaac6a3a1ba/src/libstd/thread/local.rs:254 (rng_tsan_min_repro-6bc72839c6f31b66+0xde3a1)
#14 std::thread::local::LocalKey<T>::with /rustc/4560cb830fce63fcffdc4558f4281aaac6a3a1ba/src/libstd/thread/local.rs:234 (rng_tsan_min_repro-6bc72839c6f31b66+0xde2ed)
#15 rand::rngs::thread::thread_rng /home/david/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.7.0/src/rngs/thread.rs:81 (rng_tsan_min_repro-6bc72839c6f31b66+0xddefd)
#16 rng_tsan_min_repro::tests::hammer::{{closure}}::{{closure}} /home/david/src/rng-tsan-min-repo/src/lib.rs:13 (rng_tsan_min_repro-6bc72839c6f31b66+0x20496)
[...]
This can be made to go away, by downgrading the getrandom crate:
cargo update -p getrandom --precise 0.1.6
In #52 (included in 0.1.7), some internal state access is relaxed by replacing lazy_static with custom code? I can only guess, that increased concurrency in getrandom has somehow exposed an issue in rand_chacha?
Downgrading rand_chacha from 0.2.1 to 0.2.0 makes no difference however.
If on the other hand this is a false positive from ThreadSanitizer, then this is an unfortunately broad way to suppress it:
# See https://github.com/dekellum/rng-tsan-min-repro
race:lazy_static::lazy::Lazy<T>::get
This crate requires std::io
code on many platforms to read from special devices, therefore will normally require std
. Ideally we should provide a smooth route to no_std
compatibility however, possibly by allowing users to define extern
functions. (We've discussed using "lang items" but these are restricted to Rust's core libraries; we may or may not integrate this code into std
in the future and use that option, but ideally should have a no_std
option now.)
For some custom x86 targets I am working on (https://github.com/intel/rust-hypervisor-firmware), it would be nice to have a feature that says "just use the on-CPU RNG".
Having a feature for this seems better than adding more targets to the list of targets that use RDRAND. It would also be useful more conventional targets (i.e. Linux) that don't want to use a syscall to get random data (i.e. for performance).
getentropy
in libc uses sysctl
only as a fallback and uses the getrandom
syscall if available.
This crate should check for getrandom
via dlopen
and use it if available.
This is currently blocking #112
The CI error message here actually gives a fairly good description:
Currently the bindgen format is unstable enough that these two version must
exactly match, so it's required that these two version are kept in sync by
either updating the wasm-bindgen dependency or this binary.
The solution here is simple, just always download the latest binary from Github instead of pinning the version.
#106 makes std
optional.
To quote myself (to create an open issue):
I foresee an issue here:
rand_core
has optional dependencies ongetrandom
andstd
, and now needs to depend ongetrandom/std
only if both are enabled. I'm not sure how to do that. See here where the same issue came up recently.
This is really a Cargo issue IMO, but something we may have to find a workaround to.
Currently the listed targets fall back to reading /dev/random
if getrandom
syscall is not present. Maybe it's worth to feature-gate it? (i.e. by default only syscall will be used)
See this comment by @RalfJung. It also should help with rust-random/rand#733.
Open question: do we need to read one byte from /dev/random
to ensure that entropy pool has initialized?
cc @ebarnard
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.