{"_id":"@awasm/noble","_rev":"4-df9904987b33ea275b76eccca473ebf8","name":"@awasm/noble","dist-tags":{"latest":"0.1.4"},"versions":{"0.1.0":{"name":"@awasm/noble","version":"0.1.0","keywords":["wasm","awasm","cryptography","sha","sha2","sha3","blake","blake3","pbkdf2","scrypt","sha256","salsa20","chacha","aes","keccak","kdf","hash","security","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"@awasm/noble@0.1.0","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://paulmillr.com/awasm/","bugs":{"url":"https://github.com/paulmillr/awasm-noble/issues"},"dist":{"shasum":"32ecf2284a3b8fdfe93a288d51ceed35a0ce7842","tarball":"https://registry.npmjs.org/@awasm/noble/-/noble-0.1.0.tgz","fileCount":638,"integrity":"sha512-MIdfOIZZaxRomykyaOkrZgwgnR01oLiqy/f6pZdFlxXg4W5jDpP3P69YwSXpSnWaB4Acf63Qiko2idu3WympJg==","signatures":[{"sig":"MEUCIATfkr9CHLSRQEQEHSiS85AV/KO6PpidFQBj7v9msOivAiEAh6bZBrZek0cyu9KezvlrSQDDbPZaeWSJofxnYLCQ5OM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":14752199},"main":"./index.js","type":"module","types":"./index.d.ts","module":"./index.js","engines":{"node":">= 22.22.0"},"exports":{".":"./index.js","./js.js":"./js.js","./kdf.js":"./kdf.js","./hkdf.js":"./hkdf.js","./hmac.js":"./hmac.js","./stub.js":"./stub.js","./wasm.js":"./wasm.js","./utils.js":"./utils.js","./runtime.js":"./runtime.js","./workers.js":"./workers.js","./webcrypto.js":"./webcrypto.js","./wasm_threads.js":"./wasm_threads.js"},"funding":"https://paulmillr.com/funding/","gitHead":"cf9b93810bcb4c7d06f0e73c78a158e6b57a8456","scripts":{"test":"node test/index.ts","bench":"node benchmark/1-hashes-ciphers.ts; node benchmark/2-parallel.ts","build":"npm run build:targets && tsc && npm run format","format":"prettier --write --no-error-on-unmatched-pattern '*.js' '*.d.ts' 'src/**/*.{js,ts}' 'modules/**/*.{js,ts}' 'targets/**/*.{js,ts}' 'test/*.ts' 'test/ciphers/*.ts' 'test/hashes/*.ts'","build:clean":"rm -rf src/targets targets modules *.js *.js.map *.d.ts *.d.ts.map 2> /dev/null","test:zeroize":"CHECK_ZEROIZE=1 node test/index.ts","build:targets":"node scripts/build-targets.ts"},"_npmUser":{"name":"paulmillr","email":"paul@paulmillr.com"},"repository":{"url":"git+https://github.com/paulmillr/awasm-noble.git","type":"git"},"_npmVersion":"11.12.1","description":"Auditable WASM implementation of cryptographic hashes & ciphers","directories":{},"sideEffects":false,"_nodeVersion":"25.9.0","_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","fast-check":"4.5.3","typescript":"5.9.2","@scure/base":"2.0.0","@noble/hashes":"~2.2.0","@noble/ciphers":"~2.2.0","@awasm/compiler":"0.1.0","@paulmillr/jsbt":"0.5.0"},"_npmOperationalInternal":{"tmp":"tmp/noble_0.1.0_1776422990903_0.07054501126907176","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@awasm/noble","version":"0.1.1","keywords":["wasm","awasm","cryptography","sha","sha2","sha3","blake","blake3","pbkdf2","scrypt","sha256","salsa20","chacha","aes","keccak","kdf","hash","security","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"@awasm/noble@0.1.1","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://paulmillr.com/awasm/","bugs":{"url":"https://github.com/paulmillr/awasm-noble/issues"},"dist":{"shasum":"f47be599b928d7045345076e221027413a041727","tarball":"https://registry.npmjs.org/@awasm/noble/-/noble-0.1.1.tgz","fileCount":638,"integrity":"sha512-WTAFJq3ShNt/ABL++b1PgnmR8W4rgQ6O49FGI5vUNlFehatf0M4yloEEosqgnvYkZPNyRMz6wCPyRI2JMU3kmQ==","signatures":[{"sig":"MEQCIBpgJi4/3r1puiHMs51g7+F1TT2OgWP3gs1nbVVnI6jvAiB7Gcc/mHnpRxndsxRjOUwJbWcyiuxkSkWPevRwyq+8KA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@awasm%2fnoble@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":14785449},"main":"./index.js","type":"module","types":"./index.d.ts","module":"./index.js","engines":{"node":">= 22.22.0"},"exports":{".":"./index.js","./js.js":"./js.js","./kdf.js":"./kdf.js","./hkdf.js":"./hkdf.js","./hmac.js":"./hmac.js","./stub.js":"./stub.js","./wasm.js":"./wasm.js","./utils.js":"./utils.js","./runtime.js":"./runtime.js","./workers.js":"./workers.js","./webcrypto.js":"./webcrypto.js","./wasm_threads.js":"./wasm_threads.js"},"funding":"https://paulmillr.com/funding/","gitHead":"17b6bd986e17be776edf40a034dc95fa7a4e5d50","scripts":{"test":"node test/index.ts","bench":"node benchmark/1-hashes-ciphers.ts; node benchmark/2-parallel.ts","build":"npm run build:targets && tsc && npm run format","format":"prettier --write --no-error-on-unmatched-pattern '*.js' '*.d.ts' 'src/**/*.{js,ts}' 'modules/**/*.{js,ts}' 'targets/**/*.{js,ts}' 'test/*.ts' 'test/ciphers/*.ts' 'test/hashes/*.ts'","build:clean":"rm -rf src/targets targets modules *.js *.js.map *.d.ts *.d.ts.map 2> /dev/null","test:zeroize":"CHECK_ZEROIZE=1 node test/index.ts","build:targets":"node scripts/build-targets.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b19a8e4a-963b-4671-bd48-b1fed4d52042"}},"repository":{"url":"git+https://github.com/paulmillr/awasm-noble.git","type":"git"},"_npmVersion":"11.6.1","description":"Auditable WASM implementation of cryptographic hashes & ciphers","directories":{},"sideEffects":false,"_nodeVersion":"24.11.0","_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","fast-check":"4.5.3","typescript":"5.9.2","@scure/base":"2.0.0","@noble/hashes":"~2.2.0","@noble/ciphers":"~2.2.0","@awasm/compiler":"0.1.1","@paulmillr/jsbt":"0.5.0"},"_npmOperationalInternal":{"tmp":"tmp/noble_0.1.1_1776725368559_0.8330913828557898","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@awasm/noble","version":"0.1.2","keywords":["wasm","awasm","cryptography","sha","sha2","sha3","blake","blake3","pbkdf2","scrypt","sha256","salsa20","chacha","aes","keccak","kdf","hash","security","noble"],"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","_id":"@awasm/noble@0.1.2","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"homepage":"https://paulmillr.com/awasm/","bugs":{"url":"https://github.com/paulmillr/awasm-noble/issues"},"dist":{"shasum":"56bc1bea1d08de0a02c70d6cd6ff1a5b00b775c7","tarball":"https://registry.npmjs.org/@awasm/noble/-/noble-0.1.2.tgz","fileCount":638,"integrity":"sha512-eA9cvKsw0xgMFXHkBzCs+hQ2mNbNWi8ZBQJKUavcxHtJRNaVkf/ZBic2nLFVu5py3Y4aLD3a4I87LzmC7Gn/+Q==","signatures":[{"sig":"MEUCIQCWQkLT3q94VefUYsp0nT6p+EFO2OJlh9QF/gTZxCrcqQIgRAX70rIayluzOjhRiIe9XXn74lrw0Se1hJA2B5IVVrQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@awasm%2fnoble@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":14272412},"main":"./index.js","type":"module","types":"./index.d.ts","module":"./index.js","engines":{"node":">= 22.22.0"},"exports":{".":"./index.js","./js.js":"./js.js","./kdf.js":"./kdf.js","./hkdf.js":"./hkdf.js","./hmac.js":"./hmac.js","./stub.js":"./stub.js","./wasm.js":"./wasm.js","./utils.js":"./utils.js","./runtime.js":"./runtime.js","./workers.js":"./workers.js","./webcrypto.js":"./webcrypto.js","./wasm_threads.js":"./wasm_threads.js"},"funding":"https://paulmillr.com/funding/","gitHead":"9dc032cfdf91383e1bec3b3a2d68de3d460c6210","scripts":{"test":"node test/index.ts","bench":"node benchmark/1-hashes-ciphers.ts; node benchmark/2-parallel.ts","build":"npm run build:targets && tsc && npm run format","check":"npx --no @paulmillr/jsbt check package.json","format":"prettier --write --no-error-on-unmatched-pattern '*.js' '*.d.ts' 'src/**/*.{js,ts}' 'modules/**/*.{js,ts}' 'targets/**/*.{js,ts}' 'test/*.ts' 'test/ciphers/*.ts' 'test/hashes/*.ts'","test:slow":"node test/slow.ts","build:clean":"rm -rf src/targets targets modules *.js *.js.map *.d.ts *.d.ts.map 2> /dev/null","test:zeroize":"CHECK_ZEROIZE=1 node test/index.ts","build:targets":"node scripts/build-targets.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:b19a8e4a-963b-4671-bd48-b1fed4d52042"}},"repository":{"url":"git+https://github.com/paulmillr/awasm-noble.git","type":"git"},"_npmVersion":"11.6.1","description":"Auditable WASM implementation of cryptographic hashes & ciphers","directories":{},"sideEffects":false,"_nodeVersion":"24.11.0","_hasShrinkwrap":false,"devDependencies":{"prettier":"3.6.2","fast-check":"4.5.3","typescript":"5.9.2","@scure/base":"2.0.0","@noble/hashes":"~2.2.0","@noble/ciphers":"~2.2.0","@awasm/compiler":"0.1.2","@paulmillr/jsbt":"0.5.0"},"peerDependencies":{"@awasm/compiler":"0.1.2"},"peerDependenciesMeta":{"@awasm/compiler":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/noble_0.1.2_1777373703856_0.005634697741859984","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"_id":"@awasm/noble@0.1.4","bugs":{"url":"https://github.com/paulmillr/awasm-noble/issues"},"dist":{"shasum":"5c7bf08b9232cee3d98121572c2408725053342f","tarball":"https://registry.npmjs.org/@awasm/noble/-/noble-0.1.4.tgz","integrity":"sha512-LFkAq7VnGc8Hum4x12yxBsyoQYq9mWDf02j1lltzXaeZ14qcXwEYnOl5ByJ49xiBk1L7h6m3vkKkInvtDUIvOg==","fileCount":642,"unpackedSize":14575649,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@awasm%2fnoble@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCH3CcwWc+i4TIuBpwiNCH0qrCmCm7hClG/gVVtxCfi4wCIQCYK+YdnkZ6DDPF1QoDOOljiXfbT6xmIRh3G8eGy+Q8DA=="}]},"main":"./index.js","name":"@awasm/noble","type":"module","types":"./index.d.ts","author":{"url":"https://paulmillr.com","name":"Paul Miller"},"module":"./index.js","engines":{"node":">= 22.22.0"},"exports":{".":"./index.js","./js.js":"./js.js","./kdf.js":"./kdf.js","./hkdf.js":"./hkdf.js","./hmac.js":"./hmac.js","./stub.js":"./stub.js","./wasm.js":"./wasm.js","./noble.js":"./noble.js","./utils.js":"./utils.js","./runtime.js":"./runtime.js","./workers.js":"./workers.js","./webcrypto.js":"./webcrypto.js","./wasm_threads.js":"./wasm_threads.js"},"funding":"https://paulmillr.com/funding/","gitHead":"b53c0b173e5b77fed94a234edc4276dc6d99592e","license":"MIT","scripts":{"test":"node test/index.ts","bench":"node benchmark/1-hashes-ciphers.ts; node benchmark/2-parallel.ts","build":"npm run build:targets && tsc && npm run format","check":"npx --no @paulmillr/jsbt check package.json","format":"prettier --write --no-error-on-unmatched-pattern '*.js' '*.d.ts' 'src/**/*.{js,ts}' 'modules/**/*.{js,ts}' 'targets/**/*.{js,ts}' 'test/*.ts' 'test/ciphers/*.ts' 'test/hashes/*.ts'","test:slow":"node test/slow.ts","build:clean":"rm -rf src/targets targets modules *.js *.js.map *.d.ts *.d.ts.map 2> /dev/null","test:zeroize":"CHECK_ZEROIZE=1 node test/index.ts","build:targets":"node scripts/build-targets.ts"},"version":"0.1.4","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:7f8ec2b4-2990-4570-92b4-37a58d021961"},"approver":{"name":"paulmillr","email":"paul@paulmillr.com"}},"homepage":"https://paulmillr.com/awasm/","keywords":["wasm","awasm","cryptography","sha","sha2","sha3","blake","blake3","pbkdf2","scrypt","sha256","salsa20","chacha","aes","keccak","kdf","hash","security","noble"],"repository":{"url":"git+https://github.com/paulmillr/awasm-noble.git","type":"git"},"_npmVersion":"11.15.0","description":"Auditable WASM implementation of cryptographic hashes & ciphers","directories":{},"maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"sideEffects":false,"_nodeVersion":"24.15.0","devDependencies":{"prettier":"3.6.2","fast-check":"4.2.0","typescript":"6.0.2","@scure/base":"2.2.0","@types/node":"25.9.0","@noble/hashes":"~2.2.0","@noble/ciphers":"~2.2.0","@awasm/compiler":"0.1.3","@paulmillr/jsbt":"0.5.0"},"peerDependencies":{"@noble/hashes":"~2.2.0","@noble/ciphers":"~2.2.0","@awasm/compiler":"0.1.3"},"peerDependenciesMeta":{"@noble/hashes":{"optional":true},"@noble/ciphers":{"optional":true},"@awasm/compiler":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/noble_0.1.4_1780432122630_0.04809115853417012"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-17T10:49:50.841Z","modified":"2026-06-02T20:28:43.141Z","0.1.0":"2026-04-17T10:49:51.209Z","0.1.1":"2026-04-20T22:49:28.826Z","0.1.2":"2026-04-28T10:55:04.147Z","0.1.4":"2026-06-02T20:28:42.829Z"},"bugs":{"url":"https://github.com/paulmillr/awasm-noble/issues"},"author":{"url":"https://paulmillr.com","name":"Paul Miller"},"license":"MIT","homepage":"https://paulmillr.com/awasm/","keywords":["wasm","awasm","cryptography","sha","sha2","sha3","blake","blake3","pbkdf2","scrypt","sha256","salsa20","chacha","aes","keccak","kdf","hash","security","noble"],"repository":{"url":"git+https://github.com/paulmillr/awasm-noble.git","type":"git"},"description":"Auditable WASM implementation of cryptographic hashes & ciphers","maintainers":[{"name":"paulmillr","email":"paul@paulmillr.com"}],"readme":"# AWASM noble\n\n> WASM, but paranoia-friendly\n\nAuditable WASM implementation of cryptographic hashes & ciphers.\n\n- 🔒 Auditable: reproducible binaries produced from JS source code\n- 🔻 Tree-shakeable: unused code is excluded from your builds\n- 🏎 Fast: [6-10 GB/s for BLAKE3](#speed), 6.4 GB/s for ChaCha20\n- 🔍 Reliable: tests from noble packages, zeroization tests\n- 4️⃣ Different backends: wasm (SIMD), threaded wasm (web workers), JS, runtime\n- 🎫 Stubs: switch between backends based on app needs\n- 🔗 Synchronous by default, with optional async methods\n- 🦘 Includes SHA, RIPEMD, BLAKE, PBKDF, Scrypt, Argon2, Salsa, ChaCha, AES\n- 🪶 Lightweight\n\n### This library belongs to _awasm_\n\n> **awasm** — high-security, auditable WASM packages\n\n- **Reproducible builds:** deterministic cross-platform builds\n- **Auditable compiler:** reasonably small JS-to-WASM compiler\n- **Synchronous execution:** with optional async variant\n- Minimal deps, PGP-signed releases and transparent NPM builds\n- All libraries:\n  [awasm-noble](https://github.com/paulmillr/awasm-noble),\n  [awasm-compiler](https://github.com/paulmillr/awasm-compiler)\n- [Check out the homepage](https://paulmillr.com/awasm/) for motivation behind the project\n\n## Usage\n\n> `npm install @awasm/noble`\n\n> `deno add jsr:@awasm/noble`\n\n```ts\nimport { sha224, sha256, sha384, sha512, sha512_224, sha512_256 } from '@awasm/noble';\nimport { md5, ripemd160, sha1 } from '@awasm/noble';\nimport { blake224, blake256, blake384, blake512,\n         blake2b, blake2s, blake3 } from '@awasm/noble';\nimport { keccak_224, keccak_256, keccak_384, keccak_512,\n  sha3_224, sha3_256, sha3_384, sha3_512,\n  shake128, shake128_32, shake256, shake256_64 } from '@awasm/noble';\nimport { argon2d, argon2i, argon2id, scrypt } from '@awasm/noble';\nimport { pbkdf2 } from '@awasm/noble/kdf.js';\nimport { hmac } from '@awasm/noble/hmac.js';\nimport { hkdf } from '@awasm/noble/hkdf.js';\nimport {\n  chacha20poly1305, xchacha20poly1305, xsalsa20poly1305, gcm, gcmsiv,\n  aessiv, ctr, cbc, cfb, ofb, ecb, aeskw, aeskwp,\n  cmac, chacha20, xchacha20, salsa20, xsalsa20, chacha8, ghash, polyval, poly1305,\n} from '@awasm/noble';\n\nblake3(new Uint8Array([0xca, 0xfe]));\n```\n\n<!-- TOC start -->\n\n* [Usage](#usage)\n  + [Interface](#interface)\n  + [Backends: wasm, wasm_threads, js, noble, webcrypto, runtime](#backends-wasm-wasm_threads-js-noble-webcrypto-runtime)\n  + [Noble platform](#noble-platform)\n  + [Stubs](#stubs)\n  + [Threads](#threads)\n  + [Streaming](#streaming)\n  + [Async](#async)\n  + [Zero-allocation](#zero-allocation)\n* [Examples](#examples)\n  + [Encrypt with XChaCha20Poly1305](#encrypt-with-xchacha20poly1305)\n  + [Encrypt with AES](#encrypt-with-aes)\n  + [Auto-managed nonce](#auto-managed-nonce)\n  + [Async ciphers with progress](#async-ciphers-with-progress)\n  + [Streaming ciphers](#streaming-ciphers)\n  + [Scrypt, Argon, PBKDF](#scrypt-argon-pbkdf)\n  + [MACs](#macs)\n  + [WebCrypto Hashes + KDF/MAC](#webcrypto-hashes--kdfmac)\n  + [WebCrypto Ciphers](#webcrypto-ciphers)\n* [Internals](#internals)\n  + [Why one package for hashes & ciphers?](#why-one-package-for-hashes--ciphers)\n  + [Differences from noble](#differences-from-noble)\n  + [Deno and Web Workers](#deno-and-web-workers)\n  + [Contributing](#contributing)\n* [Speed](#speed)\n  + [wasm_threads](#wasm_threads)\n  + [wasm (no threads)](#wasm-no-threads)\n* [License](#license)\n\n<!-- TOC end -->\n\n### Interface\n\nHashes can be called in the following ways:\n\n```js\nimport { blake3 } from '@awasm/noble';\n\nconst msg = new Uint8Array(64);\nconst msg1 = msg;\nconst msg2 = msg;\nconst opts = {};\n\nblake3(msg);\nblake3(msg, opts);\nawait blake3.async(msg);\nblake3.chunks([msg.slice(0, 32), msg.slice(32, 64)]);\nblake3.parallel([msg1, msg2]);\nblake3.create().update(msg1).update(msg2).digest();\n```\n\nCiphers have following interfaces:\n\n```js\nimport { chacha20poly1305 } from '@awasm/noble';\n\nconst key = new Uint8Array(32);\nconst nonce = new Uint8Array(12);\nconst data = new Uint8Array([1, 2, 3]);\nconst cipher = chacha20poly1305(key, nonce /*, ...optionalArgs */);\nconst encrypted = cipher.encrypt(data); // sync\ncipher.decrypt(encrypted);\n\nawait chacha20poly1305(key, nonce).encrypt.async(data); // async\nawait chacha20poly1305(key, nonce).decrypt.async(encrypted);\n\nconst enc = chacha20poly1305(key, nonce).encrypt.create();\nenc.update(data);\nconst streamed = enc.finish(); // streaming\nconst dec = chacha20poly1305(key, nonce).decrypt.create();\ndec.update(streamed.data);\ndec.finish(streamed.tag);\n```\n\nMACs (`poly1305` / `ghash` / `polyval` / `cmac`) are hash-like, with extra `key` option:\n`mac(msg, key|{ key })`, `mac.chunks(...)`, `mac.parallel(...)`, `mac.create(...)`.\n\nKDFs are `kdf(password, salt, opts?)` and `kdf.async(...)`.\n\n### Backends: wasm, wasm_threads, js, noble, webcrypto, runtime\n\n```ts\nimport { sha256 } from '@awasm/noble'; // wasm\nimport { sha256 as sha256wasm_threads } from '@awasm/noble/wasm_threads.js';\nimport { sha256 as sha256js } from '@awasm/noble/js.js';\nimport { sha256 as sha256noble } from '@awasm/noble/noble.js';\nimport { sha256 as sha256wc } from '@awasm/noble/webcrypto.js';\nimport { sha256 as sha256rn } from '@awasm/noble/runtime.js';\n\nfor (const hash of [sha256, sha256wasm_threads, sha256js, sha256noble, sha256rn]) {\n  console.log(hash(new Uint8Array([1, 2, 3])));\n}\nfor (const hash of [sha256wc]) {\n  console.log(await hash.async(new Uint8Array([1, 2, 3])));\n}\n```\n\n4 backends are produced from 1 source code, by awasm-compiler:\n\n1. **wasm:** JS files containing wasm binaries in base64 strings. Requires `wasm-unsafe-eval` CORS policy to work.\n    - Check out [`examples`](./examples) for node.js & vercel example of proper headers\n2. **wasm_threads:** identical to wasm, but faster due to web workers. Requires `Cross-Origin-Opener-Policy: same-origin` & `Cross-Origin-Embedder-Policy: require-corp` CORS policies to work.\n    - Check out [`examples`](./examples) for node.js & vercel example of proper headers\n3. **js:** JS files without WASM. Extra optimizations (like loop unrolling) are auto-applied, to make everything fast.\n4. **runtime:** slowly executes source code in-place. Tiny bundle size, useful for debugging. Depends on `@awasm/compiler`\n\nAdditionally, **noble** wraps `@noble/hashes` and `@noble/ciphers`, and **webcrypto** wraps built-in `WebCrypto` methods. WebCrypto is async-only.\n\n### Noble platform\n\nThe `@awasm/noble/noble.js` platform is a static wrapper around `@noble/hashes`\nand `@noble/ciphers`. Those libraries are battle-tested and independently\naudited. The wrapper gives them the same awasm API as the compiled backends,\nincluding `.chunks(...)`, `.parallel(...)`, `out`, `outPos`, and stubs.\n\n`@awasm/noble` keeps `@noble/hashes` and `@noble/ciphers` as optional peer\ndependencies, so installing `@awasm/noble` alone does not pull them in. Install\nthem only when you import the noble platform:\n\n```sh\nnpm install @awasm/noble @noble/hashes @noble/ciphers\n```\n\n```ts\nimport { sha256 } from '@awasm/noble/noble.js';\n\nconst msgs = [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])];\nconsole.log(sha256.parallel(msgs));\n```\n\nThis is useful for libraries that want awasm's API without forcing WASM on\nusers. A library can export stubs, install noble as the default, and still allow\napplications to switch to faster wasm/js/wasm_threads platforms when\nperformance matters.\n\n```json\n{\n  \"dependencies\": {\n    \"@awasm/noble\": \"^0.1.2\"\n  },\n  \"peerDependencies\": {\n    \"@noble/ciphers\": \"~2.2.0\",\n    \"@noble/hashes\": \"~2.2.0\"\n  }\n}\n```\n\n```ts\n// inside a library\nimport { sha256, chacha20poly1305 } from '@awasm/noble/stub.js';\nimport { sha256 as nobleSha256, chacha20poly1305 as nobleChaCha } from '@awasm/noble/noble.js';\n\nsha256.install(nobleSha256, { onlyMissing: true });\nchacha20poly1305.install(nobleChaCha, { onlyMissing: true });\n\nexport { sha256, chacha20poly1305 };\n```\n\n```ts\n// inside an application that wants a faster backend\nimport { sha256 } from 'my-library';\nimport { sha256 as wasmSha256 } from '@awasm/noble/wasm_threads.js';\n\nsha256.install(wasmSha256);\nconsole.log(sha256.parallel([new Uint8Array([1, 2, 3])]));\n```\n\n### Stubs\n\nStubs allow using one high-level function call, while switching the internal backend\nas needed.\n\nImagine you have a high-level library (\"awasm-react\"). It's not the best idea to use\nwasm methods there, because users of the library may not want wasm.\n\nInstead, you use stub, with (default) wasm inside. User then is able to switch the env any time\nto JS, WebCrypto, or other backend.\n\n```ts\nimport { sha256 } from '@awasm/noble/stub.js';\nfunction hash() {\n  console.log(sha256(new Uint8Array([1, 2, 3]))); // generic\n}\n\n// Switch to WASM\nimport { sha256 as sha256wasm } from '@awasm/noble';\nsha256.install(sha256wasm);\nhash();\n\n// Switch to JS\nimport { sha256 as sha256js } from '@awasm/noble/js.js';\nsha256.install(sha256js);\nhash();\n\n// Switch to WebCrypto\nimport { sha256 as sha256Web } from '@awasm/noble/webcrypto.js';\nif (await sha256Web.isSupported()) {\n  sha256.install(sha256Web);\n  console.log(await sha256.async(new Uint8Array([1, 2, 3]))); // generic\n}\n```\n\n`install(impl, { onlyMissing: true })` installs only when the stub is empty.\nThis is intended for libraries that install a default backend, while preserving\nan implementation already chosen by the app.\n\n### Threads\n\n```ts\nimport { blake3 } from '@awasm/noble/wasm_threads.js';\nimport { xchacha20poly1305 } from '@awasm/noble/wasm_threads.js';\nimport { sha256 } from '@awasm/noble/wasm_threads.js';\nimport { deepStrictEqual } from 'node:assert';\n\nblake3(new Uint8Array(1024 * 1024 * 1024)); // 1gb\n\ndeepStrictEqual(sha256.parallel([new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])]), [\n  sha256(new Uint8Array([1, 2, 3])),\n  sha256(new Uint8Array([4, 5, 6])),\n]);\n```\n\n```ts\n// Benchmark blake3\nimport { blake3 } from '@awasm/noble/wasm_threads.js';\nasync function main() {\n  function hex(bytes) {\n    return Array.from(bytes).map(byte => byte.toString(16).padStart(2, '0')).join('');\n  }\n  // warm-up JIT\n  for (let i = 0; i < 20; i++) {\n    blake3.parallel([new Uint8Array(1024 * 1024)]);\n    await Promise.resolve();\n  }\n  // benchmark\n  for (let i = 0; i < 5; i++) {\n    const input = new Uint8Array(1024 * 1024 * 1024).fill(i); // 1GB of 0x00, 0x01, 0x02...\n    const start = Date.now();\n    const res = blake3(input); // or blake3.create().update().digest()\n    console.log('hashed 1gb in', Date.now() - start, 'ms, result:', hex(res));\n  }\n}\nmain();\n```\n\nDefault backend (WASM) uses SIMD for parallel execution.\n\n`wasm_threads` also use web worker based threads.\nIt requires `Cross-Origin-Opener-Policy: same-origin` & `Cross-Origin-Embedder-Policy: require-corp`\nCORS policies to work.\nCheck out [`examples`](./examples) for node.js & vercel example of proper headers.\n\nBLAKE3 & most ciphers run very fast in threaded mode. Others\n(e.g. SHA256, AES-CBC) can't parallelize one large input using threads,\nbut they still do it for multiple inputs, using `hash.parallel(input)`.\n\n### Streaming\n\n```ts\nimport { sha256 } from '@awasm/noble';\n\nsha256\n  .create()\n  .update(new Uint8Array([1, 2, 3]))\n  .update(new Uint8Array([4, 5, 6]))\n  .digest();\n\nsha256.chunks([new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])]);\n```\n\nFor best performance: use chunks for <1kb messages. Use streaming for 1kb+ messages.\n\n### Async\n\n```ts\nimport { sha256 } from '@awasm/noble';\nimport { deepStrictEqual } from 'node:assert';\n\ndeepStrictEqual(sha256(new Uint8Array([1, 2, 3])), await sha256.async(new Uint8Array([1, 2, 3])));\ndeepStrictEqual(\n  sha256.parallel([new Uint8Array([1, 2, 3])]),\n  await sha256.parallel.async([new Uint8Array([1, 2, 3])])\n);\ndeepStrictEqual(\n  sha256.chunks([new Uint8Array([1, 2, 3])]),\n  await sha256.chunks.async([new Uint8Array([1, 2, 3])])\n);\n```\n\n### Zero-allocation\n\n```ts\nimport { sha256 } from '@awasm/noble';\nimport { deepStrictEqual } from 'node:assert';\n\nconst out = new Uint8Array(sha256.outputLen);\nsha256(new Uint8Array([1, 2, 3]), { out });\ndeepStrictEqual(out, sha256(new Uint8Array([1, 2, 3])));\n```\n\n```ts\nimport { ctr } from '@awasm/noble';\nimport { deepStrictEqual } from 'node:assert';\n\nconst key = new Uint8Array(32).fill(1);\nconst nonce = new Uint8Array(16).fill(2);\nconst msg = new Uint8Array(64).fill(7);\nconst c = ctr(key, nonce);\n\nconst encOut = new Uint8Array(msg.length);\nc.encrypt(msg, encOut);\nconst decOut = new Uint8Array(msg.length);\nc.decrypt(encOut, decOut);\ndeepStrictEqual(decOut, msg);\n```\n\nSome ciphers (GCM, GCM-SIV) don't support zero-alloc mode.\n\n## Examples\n\n### Encrypt with XChaCha20Poly1305\n\n```ts\nimport { xchacha20poly1305 } from '@awasm/noble';\n\nconst key = new Uint8Array(32).fill(7);\nconst nonce = new Uint8Array(24).fill(9);\nconst data = new TextEncoder().encode('hello noble');\nconst chacha = xchacha20poly1305(key, nonce);\nconst ciphertext = chacha.encrypt(data);\nconst data_ = chacha.decrypt(ciphertext);\n```\n\n### Encrypt with AES\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport { gcm, gcmsiv, aessiv, ctr, cfb, cbc, ecb, aeskw, aeskwp } from '@awasm/noble';\n\nconst plaintext = new Uint8Array(32).fill(16);\nconst key = new Uint8Array(32).fill(1);\nconst nonce12 = new Uint8Array(12).fill(2);\nconst nonce16 = new Uint8Array(16).fill(3);\nfor (const cipher of [gcm, gcmsiv, aessiv]) {\n  const ct = cipher(key, nonce12).encrypt(plaintext);\n  deepStrictEqual(cipher(key, nonce12).decrypt(ct), plaintext);\n}\nfor (const cipher of [ctr, cbc, cfb]) {\n  const ct = cipher(key, nonce16).encrypt(plaintext);\n  deepStrictEqual(cipher(key, nonce16).decrypt(ct), plaintext);\n}\nconst wrapped = aeskw(key.subarray(0, 16)).encrypt(key.subarray(0, 16));\ndeepStrictEqual(aeskw(key.subarray(0, 16)).decrypt(wrapped), key.subarray(0, 16));\nconst wrappedP = aeskwp(key.subarray(0, 16)).encrypt(key.subarray(0, 16));\ndeepStrictEqual(aeskwp(key.subarray(0, 16)).decrypt(wrappedP), key.subarray(0, 16));\ndeepStrictEqual(ecb(key).decrypt(ecb(key).encrypt(plaintext)), plaintext);\n```\n\n### Auto-managed nonce\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport { xchacha20poly1305 } from '@awasm/noble';\nimport { managedNonce } from '@awasm/noble/utils.js';\n\nconst key = new Uint8Array(32).fill(4);\nconst chacha = managedNonce(xchacha20poly1305)(key);\nconst data = new TextEncoder().encode('hello noble');\nconst ciphertext = chacha.encrypt(data);\ndeepStrictEqual(chacha.decrypt(ciphertext), data);\n```\n\n### Async ciphers with progress\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport { ctr, gcm } from '@awasm/noble';\n\nconst msg = Uint8Array.from({ length: 8192 }, (_, i) => i & 0xff);\nconst key = new Uint8Array(32).fill(8);\nconst nonce16 = new Uint8Array(16).fill(9);\nconst nonce12 = new Uint8Array(12).fill(10);\nconst aad = new Uint8Array(33).fill(11);\n\nconst ctrSync = ctr(key, nonce16).encrypt(msg);\nconst ctrAsync = await ctr(key, nonce16).encrypt.async(msg, undefined, { asyncTick: 0 });\ndeepStrictEqual(ctrAsync, ctrSync);\ndeepStrictEqual(await ctr(key, nonce16).decrypt.async(ctrAsync, undefined, { asyncTick: 0 }), msg);\n\nconst gcmSync = gcm(key, nonce12, aad).encrypt(msg);\nconst gcmAsync = await gcm(key, nonce12, aad).encrypt.async(msg, undefined, { asyncTick: 0 });\ndeepStrictEqual(gcmAsync, gcmSync);\ndeepStrictEqual(await gcm(key, nonce12, aad).decrypt.async(gcmAsync, undefined, { asyncTick: 0 }), msg);\n```\n\n### Streaming ciphers\n\n```ts\nimport { ctr } from '@awasm/noble';\n\nconst key = new Uint8Array(32).fill(5);\nconst nonce = new Uint8Array(16).fill(6);\nconst msg = new Uint8Array(1024).fill(7);\n\nconst enc = ctr(key, nonce).encrypt.create();\nconst c1 = enc.update(msg.subarray(0, 256));\nconst c2 = enc.update(msg.subarray(256, 1024));\nconst tail = enc.finish().data;\n\nconst dec = ctr(key, nonce).decrypt.create();\nconst p1 = dec.update(c1);\nconst p2 = dec.update(c2);\nconst end = dec.finish().data;\n```\n\n### Scrypt, Argon, PBKDF\n\n```ts\nimport { scrypt } from '@awasm/noble';\nconst scr1 = scrypt('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });\nconst scr2 = await scrypt.async('password', 'salt', { N: 2 ** 16, r: 8, p: 1, dkLen: 32 });\n\nimport { argon2d, argon2i, argon2id } from '@awasm/noble';\nconst arg1 = argon2id('password', 'saltsalt', { t: 2, m: 65536, p: 1, maxmem: 2 ** 32 - 1 });\nconst arg2 = argon2d('password', 'saltsalt', { t: 2, m: 65536, p: 1, maxmem: 2 ** 32 - 1 });\nconst arg3 = argon2i('password', 'saltsalt', { t: 2, m: 65536, p: 1, maxmem: 2 ** 32 - 1 });\nconst arg4 = await argon2i.async('password', 'saltsalt', {\n  t: 2,\n  m: 65536,\n  p: 1,\n  maxmem: 2 ** 32 - 1,\n});\n\nimport { sha256 } from '@awasm/noble';\nimport { pbkdf2 } from '@awasm/noble/kdf.js';\nconst pbkey1 = pbkdf2(sha256)('password', 'salt', { c: 524288, dkLen: 32 });\nconst pbkey2 = pbkdf2(sha256).async('password', 'salt', { c: 524288, dkLen: 32 });\n```\n\nAll KDFs support onProgress callback (even in sync version, which allows display progress bar in CLI scripts).\nAlso, we now support overriding `nextTick` function which used to return control, which means it could be replaced with\n`sleep` or other implementation when desired (https://github.com/paulmillr/noble-hashes/issues/113)\n\n```ts\nimport { scrypt } from '@awasm/noble';\n\nconst scr3 = await scrypt.async(Uint8Array.from([1, 2, 3]), Uint8Array.from([4, 5, 6]), {\n  N: 2 ** 17,\n  r: 8,\n  p: 1,\n  dkLen: 32,\n  asyncTick: 10, // return control after this amount of ms\n  onProgress(percentage) {\n    console.log('progress', percentage);\n  },\n  nextTick: async () => {},\n  maxmem: 2 ** 32 + 128 * 8 * 1, // N * r * p * 128 + (128*r*p)\n});\n```\n\n### MACs\n\n```ts\nimport { deepStrictEqual } from 'node:assert';\nimport { cmac } from '@awasm/noble';\nimport { poly1305 } from '@awasm/noble';\nimport { ghash } from '@awasm/noble';\n\nconst msg = new Uint8Array([1, 2, 3, 4]);\nconst key32 = new Uint8Array(32).fill(12);\nconst key16 = new Uint8Array(16).fill(13);\n\nconst p = poly1305(msg, key32);\nconst g = ghash(msg, key16);\nconst c = cmac(msg, key16); // note order: (message, key)\ndeepStrictEqual(poly1305.parallel([msg, msg], key32), [p, p]);\n```\n\n### WebCrypto Hashes + KDF/MAC\n\n```ts\nimport { deepStrictEqual, throws } from 'node:assert';\nimport { sha256, hmac, hkdf, pbkdf2 } from '@awasm/noble/webcrypto.js';\nimport { sha256 as sha256wasm } from '@awasm/noble';\n\nconst msg = new Uint8Array([1, 2, 3]);\nconst key = new Uint8Array([7, 8, 9]);\nconst salt = new Uint8Array([4, 5, 6]);\n\nif (await sha256.isSupported()) {\n  deepStrictEqual(await sha256.async(msg), sha256wasm(msg));\n  await hmac(sha256, key, msg);\n  await hkdf(sha256, key, salt, msg, 32);\n  await pbkdf2(sha256).async(key, salt, { c: 10, dkLen: 32 });\n}\nthrows(() => pbkdf2(sha256)(key, salt, { c: 10, dkLen: 32 })); // sync is not supported\nthrows(() => sha256(msg)); // sync is not supported\n```\n\n### WebCrypto Ciphers\n\n```ts\nimport { cbc, ctr, gcm } from '@awasm/noble/webcrypto.js';\n\nconst key = new Uint8Array(32).fill(1);\nconst iv16 = new Uint8Array(16).fill(2);\nconst iv12 = new Uint8Array(12).fill(3);\nconst aad = new Uint8Array(8).fill(4);\nconst plaintext = new Uint8Array(64).fill(5);\n\nif (await cbc.isSupported()) await cbc(key, iv16).encrypt.async(plaintext);\nif (await ctr.isSupported()) await ctr(key, iv16).encrypt.async(plaintext);\nif (await gcm.isSupported()) await gcm(key, iv12, aad).encrypt.async(plaintext);\n```\n\n## Internals\n\nTo set up the repository:\n\n```sh\ngit submodule update --init --recursive\nnpm install\nnpm run build\nnpm test\n```\n\nContribution is easy!\n\n### What is the build process?\n\n1. `node scripts/build-targets.ts` script compiles `src/modules` into `src/targets`.\n    - The script is using [awasm-compiler](https://github.com/paulmillr/awasm-compiler)\n    - Some lines are included into generated files, check out the script for details\n2. Typescript compiles `src` directory into root\n\n### Why one package for hashes & ciphers?\n\n- There should always be ONE worker pool, not two, for optimal performance.\n  Using two packages would create two worker pools\n- The important components are reused across both parts. This would increase\n  bundle size and especially size of runtime backend\n\n### Differences from noble\n\nAsync methods are named as `hash.async`, not `hashAsync`.\nSome functionality is not available in awasm-noble. Use noble packages for:\nkeccakprg, rngAesCtr, rngChacha, kmac, cshake, turboshake, kt128, ff1.\n\n- raw xor stream ciphers (chacha20/salsa20) use same object API as other ciphers: `cipher(key, nonce).encrypt/decrypt`.\n  - in noble-ciphers they had separate xor-stream style API, while `ctr` had `encrypt/decrypt`, which was inconsistent\n  - `@awasm/noble` keeps one shape for ctr/chacha/salsa to make switching modes simpler\n- `ofb` is available in `@awasm/noble` (`@awasm/noble/*/aes.js`), and is not present in noble-ciphers exports.\n- cmac also uses `(msg, key)` (instead of noble-ciphers `(key, msg)`) to unify with ghash/polyval/poly1305.\n- ciphers do not currently expose hash-like `.parallel(...)` API.\n  - instead, `wasm_threads` backend uses internal block batching/threading where mode allows it\n  - sequential modes (like CBC and similar dependency-chained paths) cannot be parallelized the same way\n  - many AEAD modes still get strong speedups from parallelized encryption path, even when authentication path is sequential (GCM was just one example; same idea applies to SIV / XSalsa20-Poly1305 / others)\n- poly1305/ghash/polyval/cmac are separate MACs with hash-like API:\n  - direct: `mac(message, key)` or `mac(message, { key })`\n  - chunks: `mac.chunks([part1, part2], key)` or `mac.chunks([part1, part2], { key })`\n  - parallel: `mac.parallel([msg1, msg2], key)` or `mac.parallel([msg1, msg2], { key })`\n  - streaming: `mac.create(key).update(...).digest()` or `mac.create({ key }).update(...).digest()`\n- `secretbox` is alias to `xsalsa20poly1305` (for libsodium / nacl-style API naming), with `seal/open` methods.\n\n### Deno and Web Workers\n\nWhile Node & Bun work properly, Deno requires manual stopping of web workers in wasm_threads\nbecause it doesn't have `unref`:\n\n```ts\nimport { sha256 } from '@awasm/noble/wasm_threads.js';\n\nsha256(new Uint8Array([1, 2, 3]));\n// will pause in Deno until this called:\nimport { WP } from '@awasm/noble/workers.js';\nWP.stop();\n```\n\n## Speed\n\n> `npm run bench`\n\nBenchmarks measured on Apple M4.\n\nPrefer `.chunks()` for multiple <1mb inputs. Prefer streaming api `.update()` for >=1mb inputs.\n\nOnline benchmark (BLAKE3 checksum calculator) is available on [the demo website hosted on Vercel](https://b3sum.vercel.app).\n\n### wasm_threads\n\n```\n# hashes, input: 32x1mb, +threads\nsha256 x 6,687 mb/sec\nsha512 x 6,272 mb/sec\nsha3_256 x 6,976 mb/sec\nsha3_512 x 4,224 mb/sec\nblake2b x 9,065 mb/sec\nblake2s x 9,610 mb/sec\nblake3 48x1mb x 11,058 mb/sec\nblake3 1x100mb x 6,564 mb/sec\nripemd160 x 6,588 mb/sec\nmd5 x 9,078 mb/sec\nsha1 x 11,413 mb/sec\n\n# ciphers, input: 1gb +threads\nchacha20poly1305 x 2,318 mb/sec\nchacha20 x 6,530 mb/sec\naes-gcm-256 x 1,015 mb/sec\naes-gcm-siv-256 x 927 mb/sec\naes-ecb-256 x 2,185 mb/sec\naes-cbc-256 x 268 mb/sec\naes-ctr-256 x 2,105 mb/sec\n```\n\n### wasm (no threads)\n\n```\nsha256 x 553 mb/sec\nsha512 x 834 mb/sec\nsha3_256 x 899 mb/sec\nsha3_512 x 502 mb/sec\nblake2b x 1,342 mb/sec\nblake2s x 812 mb/sec\nblake3 x 1,940 mb/sec\nripemd160 x 503 mb/sec\nmd5 x 857 mb/sec\nsha1 x 1,294 mb/sec\nchacha20poly1305 x 1,196 mb/sec\naes-gcm-256 x 234 mb/sec\naes-gcm-siv-256 x 236 mb/sec\nchacha20 x 1,672 mb/sec\naes-ecb-256 x 277 mb/sec\naes-cbc-256 x 262 mb/sec\naes-ctr-256 x 272 mb/sec\n# KDF\npbkdf2(sha256, c: 2 ** 18) x 2 ops/sec @ 351ms/op\npbkdf2(sha512, c: 2 ** 18) x 1 ops/sec @ 503ms/op\nscrypt(n: 2 ** 19, r: 8, p: 1) x 1 ops/sec @ 597ms/op\nargon2id(t: 1, m: 128MB, p: 1) x 14 ops/sec @ 69ms/op\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2026 Paul Miller [(https://paulmillr.com)](https://paulmillr.com)\n\nSee LICENSE file.\n","readmeFilename":"README.md"}