From b93c309d5bcb800a7adfc78fa72760227c02a90d Mon Sep 17 00:00:00 2001 From: UneBaguette <28904802+UneBaguette@users.noreply.github.com> Date: Sat, 18 Apr 2026 13:41:33 +0200 Subject: [PATCH] inital commit! --- .cargo/config.toml | 2 + .gitignore | 3 + Cargo.lock | 184 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 16 ++++ LICENSE | 22 ++++++ README.md | 63 ++++++++++++++++ src/lib.rs | 65 ++++++++++++++++ 7 files changed, 355 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 src/lib.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..2d159d1 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.wasm32-unknown-unknown] +rustflags = ["-C", "target-feature=+simd128"] \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66fa33c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +pkg/ +.idea/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..277891a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,184 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "blake3" +version = "1.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d2d5991425dfd0785aed03aedcf0b321d61975c9b5b3689c774a2610ae0b51e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures", +] + +[[package]] +name = "blake3-wasm" +version = "0.0.1" +dependencies = [ + "blake3", + "wasm-bindgen", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "cc" +version = "1.2.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "libc" +version = "0.2.185" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "wasm-bindgen" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +dependencies = [ + "unicode-ident", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..28935c8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "blake3-wasm" +version = "0.0.1" +edition = "2024" +license = "MIT" +repository = "https://github.com/UneBaguette/blake3.wasm" +description = "Simple blake3 to wasm project" +keywords = ["blake3", "wasm", "hash", "cryptography", "wasm-bindgen"] +categories = ["cryptography", "wasm"] + +[lib] +crate-type = ["cdylib"] + +[dependencies] +blake3 = { version = "1.8.4", features = ["wasm32_simd"] } +wasm-bindgen = "0.2.118" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a70fb94 --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2026 UneBaguette + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/README.md b/README.md new file mode 100644 index 0000000..4a7ea4a --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# blake3 to wasm + +**blake3.wasm** is a WebAssembly port of the BLAKE3 cryptographic hash function written in **Rust**. It enables fast and secure hashing right inside **browsers** and **Node.js**. + +## build + +```sh +# lets build it! + +# For NodeJS +wasm-pack build --target nodejs --release + +# For the web! +wasm-pack build --target web --release +``` + +SIMD is enabled via `wasm32_simd` feature in `Cargo.toml` and requires: +```toml +# .cargo/config.toml +[target.wasm32-unknown-unknown] +rustflags = ["-C", "target-feature=+simd128"] +``` + +## Usage + +```js +import { hash, hashXof, keyedHash, deriveKey, Hasher } from './pkg/blake3_wasm.js' + +const data = new TextEncoder().encode('hello world') +const key = new Uint8Array(32).fill(1) + +// One-shot hashing +hash(data) +hashXof(data, 64) // variable output length + +// MAC and key derivation +keyedHash(data, key) +deriveKey('my context', key) + +// Streaming +const h = new Hasher() +h.update(data.slice(0, 5)) +h.update(data.slice(5)) +h.finalize() +``` + +## Benchmarks + +Tested on **Ryzen 7 5800X**, Node.js v24. + +| Size | @noble/hashes | awasm-noble | blake3-wasm | +|-------|---------------|-------------|-------------| +| 32 B | 11 MB/s | 34 MB/s | 81 MB/s | +| 1 KB | 60 MB/s | 360 MB/s | 781 MB/s | +| 64 KB | 49 MB/s | 1,518 MB/s | 2,004 MB/s | +| 1 MB | 51 MB/s | 1,671 MB/s | 1,893 MB/s | +| 10 MB | 51 MB/s | 1,572 MB/s | 1,812 MB/s | + +## See also + +- [@noble/hashes](https://github.com/paulmillr/noble-hashes) | pure JS implementation +- [awasm-noble](https://github.com/paulmillr/awasm-noble) | auditable WASM implementation +- [blake3-napi](https://github.com/UneBaguette/blake3-napi) | native Node.js addon, faster for large inputs \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..23d468c --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,65 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +pub fn hash(value: &[u8]) -> Vec { + blake3::hash(value).as_bytes().to_vec() +} + +#[wasm_bindgen] +pub fn hash_xof(data: &[u8], out_len: usize) -> Vec { + let mut out = vec![0u8; out_len]; + let mut reader = blake3::Hasher::new().update(data).finalize_xof(); + + reader.fill(&mut out); + + out +} + +#[wasm_bindgen] +pub fn keyed_hash(data: &[u8], key: &[u8]) -> Result, JsError> { + let key: &[u8; 32] = key + .try_into() + .map_err(|_| JsError::new("key must be exactly 32 bytes"))?; + Ok(blake3::keyed_hash(key, data).as_bytes().to_vec()) +} + +#[wasm_bindgen] +pub fn derive_key(context: &str, key_material: &[u8]) -> Vec { + blake3::derive_key(context, key_material).to_vec() +} + +#[wasm_bindgen] +pub struct Hasher(blake3::Hasher); + +#[wasm_bindgen] +impl Hasher { + #[wasm_bindgen(constructor)] + pub fn new() -> Self { + Hasher(blake3::Hasher::new()) + } + + pub fn new_keyed(key: &[u8]) -> Result { + let key: &[u8; 32] = key + .try_into() + .map_err(|_| JsError::new("key must be exactly 32 bytes"))?; + Ok(Hasher(blake3::Hasher::new_keyed(key))) + } + + pub fn update(&mut self, data: &[u8]) { + self.0.update(data); + } + + pub fn finalize(&self) -> Vec { + self.0.finalize().as_bytes().to_vec() + } + + pub fn finalize_xof(&self, out_len: usize) -> Vec { + let mut out = vec![0u8; out_len]; + self.0.finalize_xof().fill(&mut out); + out + } + + pub fn reset(&mut self) { + self.0.reset(); + } +} \ No newline at end of file