leviathan-crypto 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +86 -443
- package/README.md +198 -65
- package/dist/aes/aes-cbc.d.ts +40 -0
- package/dist/aes/aes-cbc.js +158 -0
- package/dist/aes/aes-ctr.d.ts +50 -0
- package/dist/aes/aes-ctr.js +141 -0
- package/dist/aes/aes-gcm-siv.d.ts +67 -0
- package/dist/aes/aes-gcm-siv.js +217 -0
- package/dist/aes/aes-gcm.d.ts +61 -0
- package/dist/aes/aes-gcm.js +226 -0
- package/dist/aes/cipher-suite.d.ts +21 -0
- package/dist/aes/cipher-suite.js +179 -0
- package/dist/aes/embedded.d.ts +1 -0
- package/dist/aes/embedded.js +26 -0
- package/dist/aes/generator.d.ts +14 -0
- package/dist/aes/generator.js +103 -0
- package/dist/aes/index.d.ts +58 -0
- package/dist/aes/index.js +125 -0
- package/dist/aes/ops.d.ts +60 -0
- package/dist/aes/ops.js +164 -0
- package/dist/aes/pool-worker.d.ts +1 -0
- package/dist/aes/pool-worker.js +92 -0
- package/dist/aes/types.d.ts +1 -0
- package/dist/aes/types.js +23 -0
- package/dist/aes.wasm +0 -0
- package/dist/blake3/embedded.d.ts +1 -0
- package/dist/blake3/embedded.js +26 -0
- package/dist/blake3/index.d.ts +143 -0
- package/dist/blake3/index.js +620 -0
- package/dist/blake3/types.d.ts +102 -0
- package/dist/blake3/types.js +31 -0
- package/dist/blake3/validate.d.ts +29 -0
- package/dist/blake3/validate.js +80 -0
- package/dist/blake3.wasm +0 -0
- package/dist/chacha20/cipher-suite.js +47 -25
- package/dist/chacha20/generator.d.ts +2 -2
- package/dist/chacha20/generator.js +4 -4
- package/dist/chacha20/index.d.ts +16 -15
- package/dist/chacha20/index.js +52 -46
- package/dist/chacha20/ops.d.ts +7 -7
- package/dist/chacha20/ops.js +34 -34
- package/dist/chacha20/pool-worker.js +5 -3
- package/dist/cte-wasm.d.ts +1 -0
- package/dist/cte-wasm.js +3 -0
- package/dist/curve25519.wasm +0 -0
- package/dist/ecdsa/der.d.ts +23 -0
- package/dist/ecdsa/der.js +192 -0
- package/dist/ecdsa/ecprivatekey-der.d.ts +32 -0
- package/dist/ecdsa/ecprivatekey-der.js +230 -0
- package/dist/ecdsa/embedded.d.ts +1 -0
- package/dist/ecdsa/embedded.js +25 -0
- package/dist/ecdsa/index.d.ts +124 -0
- package/dist/ecdsa/index.js +366 -0
- package/dist/ecdsa/types.d.ts +31 -0
- package/dist/ecdsa/types.js +28 -0
- package/dist/ecdsa/validate.d.ts +18 -0
- package/dist/ecdsa/validate.js +92 -0
- package/dist/ed25519/embedded.d.ts +1 -0
- package/dist/ed25519/embedded.js +31 -0
- package/dist/ed25519/index.d.ts +70 -0
- package/dist/ed25519/index.js +308 -0
- package/dist/ed25519/types.d.ts +27 -0
- package/dist/ed25519/types.js +27 -0
- package/dist/ed25519/validate.d.ts +7 -0
- package/dist/ed25519/validate.js +77 -0
- package/dist/embedded/aes-pool-worker.d.ts +1 -0
- package/dist/embedded/aes-pool-worker.js +5 -0
- package/dist/embedded/aes.d.ts +1 -0
- package/dist/embedded/aes.js +3 -0
- package/dist/embedded/blake3.d.ts +1 -0
- package/dist/embedded/blake3.js +3 -0
- package/dist/embedded/chacha20-pool-worker.d.ts +1 -1
- package/dist/embedded/chacha20-pool-worker.js +2 -2
- package/dist/embedded/chacha20.d.ts +1 -1
- package/dist/embedded/chacha20.js +2 -2
- package/dist/embedded/curve25519.d.ts +1 -0
- package/dist/embedded/curve25519.js +3 -0
- package/dist/embedded/mldsa.d.ts +1 -0
- package/dist/embedded/mldsa.js +3 -0
- package/dist/embedded/mlkem.d.ts +1 -0
- package/dist/embedded/mlkem.js +3 -0
- package/dist/embedded/p256.d.ts +1 -0
- package/dist/embedded/p256.js +3 -0
- package/dist/embedded/serpent-pool-worker.d.ts +1 -1
- package/dist/embedded/serpent-pool-worker.js +2 -2
- package/dist/embedded/serpent.d.ts +1 -1
- package/dist/embedded/serpent.js +2 -2
- package/dist/embedded/sha2.d.ts +1 -1
- package/dist/embedded/sha2.js +2 -2
- package/dist/embedded/sha3.d.ts +1 -1
- package/dist/embedded/sha3.js +2 -2
- package/dist/embedded/slhdsa.d.ts +1 -0
- package/dist/embedded/slhdsa.js +3 -0
- package/dist/errors.d.ts +92 -1
- package/dist/errors.js +111 -1
- package/dist/fortuna.d.ts +5 -5
- package/dist/fortuna.js +37 -64
- package/dist/index.d.ts +38 -9
- package/dist/index.js +63 -19
- package/dist/init.d.ts +1 -1
- package/dist/init.js +11 -25
- package/dist/keccak/embedded.js +1 -1
- package/dist/keccak/index.d.ts +2 -0
- package/dist/keccak/index.js +4 -2
- package/dist/loader.d.ts +1 -24
- package/dist/loader.js +13 -16
- package/dist/merkle/blake3-tree.d.ts +35 -0
- package/dist/merkle/blake3-tree.js +187 -0
- package/dist/merkle/checkpoint.d.ts +58 -0
- package/dist/merkle/checkpoint.js +217 -0
- package/dist/merkle/index.d.ts +19 -0
- package/dist/merkle/index.js +37 -0
- package/dist/merkle/merkle-log.d.ts +130 -0
- package/dist/merkle/merkle-log.js +207 -0
- package/dist/merkle/merkle-verifier.d.ts +126 -0
- package/dist/merkle/merkle-verifier.js +296 -0
- package/dist/merkle/proof.d.ts +70 -0
- package/dist/merkle/proof.js +300 -0
- package/dist/merkle/sha256-tree.d.ts +33 -0
- package/dist/merkle/sha256-tree.js +145 -0
- package/dist/merkle/signed-log.d.ts +156 -0
- package/dist/merkle/signed-log.js +356 -0
- package/dist/merkle/signed-note.d.ts +309 -0
- package/dist/merkle/signed-note.js +648 -0
- package/dist/merkle/sth.d.ts +31 -0
- package/dist/merkle/sth.js +31 -0
- package/dist/merkle/storage.d.ts +40 -0
- package/dist/merkle/storage.js +71 -0
- package/dist/merkle/tree.d.ts +68 -0
- package/dist/merkle/tree.js +94 -0
- package/dist/mldsa/embedded.d.ts +1 -0
- package/dist/{kyber → mldsa}/embedded.js +5 -5
- package/dist/mldsa/expand.d.ts +53 -0
- package/dist/mldsa/expand.js +188 -0
- package/dist/mldsa/format.d.ts +16 -0
- package/dist/mldsa/format.js +68 -0
- package/dist/mldsa/hashvariant.d.ts +32 -0
- package/dist/mldsa/hashvariant.js +248 -0
- package/dist/mldsa/index.d.ts +142 -0
- package/dist/mldsa/index.js +463 -0
- package/dist/mldsa/keygen.d.ts +16 -0
- package/dist/mldsa/keygen.js +232 -0
- package/dist/mldsa/params.d.ts +21 -0
- package/dist/mldsa/params.js +55 -0
- package/dist/mldsa/sha3-helpers.d.ts +30 -0
- package/dist/mldsa/sha3-helpers.js +124 -0
- package/dist/mldsa/sign.d.ts +36 -0
- package/dist/mldsa/sign.js +380 -0
- package/dist/mldsa/types.d.ts +91 -0
- package/dist/mldsa/types.js +25 -0
- package/dist/mldsa/validate.d.ts +55 -0
- package/dist/mldsa/validate.js +125 -0
- package/dist/mldsa/verify.d.ts +29 -0
- package/dist/mldsa/verify.js +269 -0
- package/dist/mldsa.wasm +0 -0
- package/dist/mlkem/embedded.d.ts +1 -0
- package/dist/mlkem/embedded.js +27 -0
- package/dist/mlkem/indcpa.d.ts +49 -0
- package/dist/{kyber → mlkem}/indcpa.js +44 -44
- package/dist/mlkem/index.d.ts +37 -0
- package/dist/{kyber → mlkem}/index.js +24 -34
- package/dist/mlkem/kem.d.ts +21 -0
- package/dist/{kyber → mlkem}/kem.js +44 -64
- package/dist/{kyber → mlkem}/params.d.ts +4 -4
- package/dist/{kyber → mlkem}/params.js +2 -2
- package/dist/mlkem/suite.d.ts +12 -0
- package/dist/{kyber → mlkem}/suite.js +17 -12
- package/dist/{kyber → mlkem}/types.d.ts +3 -3
- package/dist/{kyber → mlkem}/types.js +1 -1
- package/dist/{kyber → mlkem}/validate.d.ts +7 -7
- package/dist/{kyber → mlkem}/validate.js +7 -7
- package/dist/{kyber.wasm → mlkem.wasm} +0 -0
- package/dist/p256.wasm +0 -0
- package/dist/ratchet/index.d.ts +2 -0
- package/dist/ratchet/index.js +1 -0
- package/dist/ratchet/kdf-chain.js +3 -3
- package/dist/ratchet/ratchet-keypair.js +2 -2
- package/dist/ratchet/root-kdf.js +7 -7
- package/dist/ratchet/skipped-key-store.js +4 -4
- package/dist/ratchet/types.d.ts +1 -1
- package/dist/serpent/cipher-suite.js +20 -17
- package/dist/serpent/generator.d.ts +1 -1
- package/dist/serpent/generator.js +2 -2
- package/dist/serpent/index.d.ts +8 -7
- package/dist/serpent/index.js +18 -27
- package/dist/serpent/pool-worker.js +7 -5
- package/dist/serpent/serpent-cbc.d.ts +4 -4
- package/dist/serpent/serpent-cbc.js +11 -8
- package/dist/serpent/shared-ops.d.ts +3 -23
- package/dist/serpent/shared-ops.js +50 -85
- package/dist/serpent.wasm +0 -0
- package/dist/sha2/hkdf.js +5 -5
- package/dist/sha2/index.d.ts +21 -1
- package/dist/sha2/index.js +65 -10
- package/dist/sha2/types.d.ts +41 -2
- package/dist/sha2.wasm +0 -0
- package/dist/sha3/index.d.ts +72 -3
- package/dist/sha3/index.js +240 -14
- package/dist/sha3/kmac.d.ts +121 -0
- package/dist/sha3/kmac.js +800 -0
- package/dist/sha3.wasm +0 -0
- package/dist/shared/pkcs7.d.ts +22 -0
- package/dist/shared/pkcs7.js +84 -0
- package/dist/sign/ctx.d.ts +41 -0
- package/dist/sign/ctx.js +102 -0
- package/dist/sign/envelope.d.ts +45 -0
- package/dist/sign/envelope.js +152 -0
- package/dist/sign/hasher.d.ts +9 -0
- package/dist/sign/hasher.js +132 -0
- package/dist/sign/index.d.ts +11 -0
- package/dist/sign/index.js +34 -0
- package/dist/sign/sign-stream.d.ts +25 -0
- package/dist/sign/sign-stream.js +112 -0
- package/dist/sign/suites/ecdsa-p256.d.ts +2 -0
- package/dist/sign/suites/ecdsa-p256.js +120 -0
- package/dist/sign/suites/ed25519.d.ts +3 -0
- package/dist/sign/suites/ed25519.js +165 -0
- package/dist/sign/suites/hybrid-classical.d.ts +23 -0
- package/dist/sign/suites/hybrid-classical.js +526 -0
- package/dist/sign/suites/hybrid-pq.d.ts +4 -0
- package/dist/sign/suites/hybrid-pq.js +234 -0
- package/dist/sign/suites/mldsa.d.ts +7 -0
- package/dist/sign/suites/mldsa.js +161 -0
- package/dist/sign/suites/slhdsa.d.ts +7 -0
- package/dist/sign/suites/slhdsa.js +176 -0
- package/dist/sign/types.d.ts +106 -0
- package/dist/sign/types.js +28 -0
- package/dist/sign/verify-stream.d.ts +30 -0
- package/dist/sign/verify-stream.js +227 -0
- package/dist/slhdsa/embedded.d.ts +1 -0
- package/dist/slhdsa/embedded.js +26 -0
- package/dist/slhdsa/index.d.ts +149 -0
- package/dist/slhdsa/index.js +493 -0
- package/dist/slhdsa/params.d.ts +26 -0
- package/dist/slhdsa/params.js +70 -0
- package/dist/slhdsa/prehash.d.ts +68 -0
- package/dist/slhdsa/prehash.js +307 -0
- package/dist/slhdsa/sign.d.ts +39 -0
- package/dist/slhdsa/sign.js +116 -0
- package/dist/slhdsa/types.d.ts +129 -0
- package/dist/slhdsa/types.js +27 -0
- package/dist/slhdsa/validate.d.ts +60 -0
- package/dist/slhdsa/validate.js +127 -0
- package/dist/slhdsa/verify.d.ts +32 -0
- package/dist/slhdsa/verify.js +107 -0
- package/dist/slhdsa.wasm +0 -0
- package/dist/stream/header.js +3 -3
- package/dist/stream/index.d.ts +1 -0
- package/dist/stream/index.js +1 -0
- package/dist/stream/open-stream.js +31 -10
- package/dist/stream/seal-stream-pool.d.ts +1 -0
- package/dist/stream/seal-stream-pool.js +63 -26
- package/dist/stream/seal-stream.d.ts +1 -1
- package/dist/stream/seal-stream.js +20 -9
- package/dist/stream/seal.js +6 -6
- package/dist/stream/types.d.ts +3 -1
- package/dist/stream/types.js +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +46 -54
- package/dist/wasm-source.d.ts +7 -7
- package/dist/wasm-source.js +1 -1
- package/dist/x25519/embedded.d.ts +1 -0
- package/dist/x25519/embedded.js +31 -0
- package/dist/x25519/index.d.ts +43 -0
- package/dist/x25519/index.js +159 -0
- package/dist/x25519/types.d.ts +25 -0
- package/dist/x25519/types.js +27 -0
- package/dist/x25519/validate.d.ts +2 -0
- package/dist/x25519/validate.js +39 -0
- package/package.json +70 -26
- package/SECURITY.md +0 -163
- package/dist/ct-wasm.d.ts +0 -1
- package/dist/ct-wasm.js +0 -3
- package/dist/docs/aead.md +0 -363
- package/dist/docs/architecture.md +0 -1011
- package/dist/docs/argon2id.md +0 -305
- package/dist/docs/chacha20.md +0 -781
- package/dist/docs/exports.md +0 -277
- package/dist/docs/fortuna.md +0 -530
- package/dist/docs/init.md +0 -301
- package/dist/docs/loader.md +0 -256
- package/dist/docs/serpent.md +0 -617
- package/dist/docs/sha2.md +0 -671
- package/dist/docs/sha3.md +0 -612
- package/dist/docs/types.md +0 -416
- package/dist/docs/utils.md +0 -457
- package/dist/embedded/kyber.d.ts +0 -1
- package/dist/embedded/kyber.js +0 -3
- package/dist/kyber/embedded.d.ts +0 -1
- package/dist/kyber/indcpa.d.ts +0 -49
- package/dist/kyber/index.d.ts +0 -38
- package/dist/kyber/kem.d.ts +0 -21
- package/dist/kyber/suite.d.ts +0 -12
- /package/dist/{ct.wasm → cte.wasm} +0 -0
package/dist/docs/sha3.md
DELETED
|
@@ -1,612 +0,0 @@
|
|
|
1
|
-
<img src="https://github.com/xero/leviathan-crypto/raw/main/docs/logo.svg" alt="logo" width="120" align="left" margin="10">
|
|
2
|
-
|
|
3
|
-
### SHA3 TypeScript API Reference
|
|
4
|
-
|
|
5
|
-
Covers the SHA-3 hash functions (SHA3-224 through SHA3-512) and the SHAKE extendable-output functions (SHAKE128, SHAKE256). See [SHA-3 implementation audit](./sha3_audit.md) for algorithm correctness verifications.
|
|
6
|
-
|
|
7
|
-
> ### Table of Contents
|
|
8
|
-
> - [Overview](#overview)
|
|
9
|
-
> - [Security Notes](#security-notes)
|
|
10
|
-
> - [Module Init](#module-init)
|
|
11
|
-
> - [API Reference](#api-reference)
|
|
12
|
-
> - [Incremental XOF API](#incremental-xof-api-absorb--squeeze--reset)
|
|
13
|
-
> - [SHA3_256Hash](#sha3_256hash)
|
|
14
|
-
> - [Usage Examples](#usage-examples)
|
|
15
|
-
> - [Error Conditions](#error-conditions)
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Overview
|
|
20
|
-
|
|
21
|
-
The SHA-3 family provides six hash functions standardized in **FIPS 202**: four
|
|
22
|
-
fixed-output hash functions (SHA3-224, SHA3-256, SHA3-384, SHA3-512) and two
|
|
23
|
-
extendable-output functions, or XOFs (SHAKE128, SHAKE256). All six are built on
|
|
24
|
-
the **Keccak sponge construction**, a fundamentally different design from the
|
|
25
|
-
Merkle-Damgard structure used by SHA-2.
|
|
26
|
-
|
|
27
|
-
SHA-3 is **not** a replacement for SHA-2. Both are considered secure, and both are
|
|
28
|
-
standardized by NIST. SHA-3 exists to provide **defense-in-depth**: if a flaw is
|
|
29
|
-
ever discovered in SHA-2, SHA-3 is completely unaffected because it uses a different
|
|
30
|
-
mathematical foundation. You may never need that insurance, but if you do, you will be
|
|
31
|
-
very glad it is there.
|
|
32
|
-
|
|
33
|
-
The SHAKE XOFs are particularly flexible. Unlike SHA3-256, which always produces
|
|
34
|
-
exactly 32 bytes, SHAKE128 and SHAKE256 can produce variable-length output. You
|
|
35
|
-
tell them how many bytes you want, making them useful for key derivation, generating
|
|
36
|
-
nonces, or any situation where you need more (or fewer) bytes than a standard hash
|
|
37
|
-
provides.
|
|
38
|
-
|
|
39
|
-
One key advantage of SHA-3 over SHA-2: **SHA-3 is immune to length extension
|
|
40
|
-
attacks.** With SHA-2, if you know `SHA256(secret + message)` but not the secret,
|
|
41
|
-
you can compute `SHA256(secret + message + padding + extra)` without knowing the
|
|
42
|
-
secret. SHA-3's sponge construction makes this impossible.
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## Security Notes
|
|
47
|
-
|
|
48
|
-
> [!IMPORTANT]
|
|
49
|
-
> Read these before using the API. Misusing hash functions is one of the most
|
|
50
|
-
> common sources of security vulnerabilities.
|
|
51
|
-
|
|
52
|
-
- **Length extension immunity.** Unlike SHA-2, the SHA-3 sponge construction does
|
|
53
|
-
not leak enough internal state for length extension attacks. Computing
|
|
54
|
-
`SHA3(secret + message)` does not let an attacker forge `SHA3(secret + message + extra)`.
|
|
55
|
-
That said, **HMAC is still the correct way to build a MAC** — do not use raw
|
|
56
|
-
`SHA3(key + message)` as a MAC construction, even though it is not vulnerable to
|
|
57
|
-
length extension. HMAC provides a formally proven security reduction.
|
|
58
|
-
|
|
59
|
-
- **SHAKE output is unbounded.** SHAKE128 and SHAKE256 are full XOFs — output
|
|
60
|
-
length is unbounded. Request any number of bytes via `hash()`, or drive the
|
|
61
|
-
sponge directly with `absorb()` / `squeeze()`. The only constraint is
|
|
62
|
-
`outputLength >= 1`.
|
|
63
|
-
|
|
64
|
-
- **Not for password hashing.** SHA-3 is a fast hash, which is the opposite of
|
|
65
|
-
what you want for password storage. Passwords must be hashed with a slow,
|
|
66
|
-
memory-hardened algorithm like **Argon2id**. See [argon2id.md](./argon2id.md) for
|
|
67
|
-
usage patterns including passphrase-based encryption with leviathan primitives.
|
|
68
|
-
|
|
69
|
-
- **Call `dispose()` when finished.** Every SHA-3 class wraps a WASM module that
|
|
70
|
-
stores Keccak state in linear memory. Calling `dispose()` zeroes all internal
|
|
71
|
-
state (the 200-byte lane matrix, input buffer, output buffer, and metadata).
|
|
72
|
-
If you skip `dispose()`, key material or intermediate hash state may persist
|
|
73
|
-
in memory.
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## Module Init
|
|
78
|
-
|
|
79
|
-
Each module subpath exports its own init function for consumers who want
|
|
80
|
-
tree-shakeable imports.
|
|
81
|
-
|
|
82
|
-
### `sha3Init(source)`
|
|
83
|
-
|
|
84
|
-
Initializes only the sha3 WASM binary. Equivalent to calling the
|
|
85
|
-
root `init({ sha3: source })` but without pulling the other three
|
|
86
|
-
modules into the bundle.
|
|
87
|
-
|
|
88
|
-
**Signature:**
|
|
89
|
-
|
|
90
|
-
```typescript
|
|
91
|
-
async function sha3Init(source: WasmSource): Promise<void>
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
**Usage:**
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { sha3Init, SHA3_256 } from 'leviathan-crypto/sha3'
|
|
98
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
99
|
-
|
|
100
|
-
await sha3Init(sha3Wasm)
|
|
101
|
-
const sha3 = new SHA3_256()
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### keccakInit() Alias
|
|
105
|
-
|
|
106
|
-
`'keccak'` is an alias for `'sha3'`. Same WASM binary, same instance slot.
|
|
107
|
-
`keccakInit()` and `sha3Init()` are interchangeable.
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
import { keccakInit, SHAKE256, SHA3_256 } from 'leviathan-crypto/keccak'
|
|
111
|
-
import { keccakWasm } from 'leviathan-crypto/keccak/embedded'
|
|
112
|
-
|
|
113
|
-
await keccakInit(keccakWasm)
|
|
114
|
-
// isInitialized('sha3') === true — same slot
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
Use the `keccak` subpath when the consuming context (such as ML-KEM) makes the
|
|
118
|
-
Keccak primitive name semantically clearer. See [init.md](./init.md#keccak-alias-for-ml-kem)
|
|
119
|
-
for full details.
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## API Reference
|
|
124
|
-
|
|
125
|
-
All SHA-3 classes require initialization before use. Either the root `init()`:
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
import { init } from 'leviathan-crypto'
|
|
129
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
130
|
-
|
|
131
|
-
await init({ sha3: sha3Wasm })
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Or the subpath `sha3Init()`:
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
import { sha3Init } from 'leviathan-crypto/sha3'
|
|
138
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
139
|
-
|
|
140
|
-
await sha3Init(sha3Wasm)
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
If you use SHA-3 classes without calling `init()` first, the constructor
|
|
144
|
-
will throw an error.
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
### SHA3_224
|
|
149
|
-
|
|
150
|
-
Fixed-output hash function. Produces a **28-byte** (224-bit) digest.
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
class SHA3_224 {
|
|
154
|
-
constructor()
|
|
155
|
-
hash(msg: Uint8Array): Uint8Array // returns 28 bytes
|
|
156
|
-
dispose(): void
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
### SHA3_256
|
|
163
|
-
|
|
164
|
-
Fixed-output hash function. Produces a **32-byte** (256-bit) digest. This is the
|
|
165
|
-
most commonly used SHA-3 variant; 256-bit security is suitable for most
|
|
166
|
-
applications.
|
|
167
|
-
|
|
168
|
-
```typescript
|
|
169
|
-
class SHA3_256 {
|
|
170
|
-
constructor()
|
|
171
|
-
hash(msg: Uint8Array): Uint8Array // returns 32 bytes
|
|
172
|
-
dispose(): void
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
### SHA3_384
|
|
179
|
-
|
|
180
|
-
Fixed-output hash function. Produces a **48-byte** (384-bit) digest.
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
class SHA3_384 {
|
|
184
|
-
constructor()
|
|
185
|
-
hash(msg: Uint8Array): Uint8Array // returns 48 bytes
|
|
186
|
-
dispose(): void
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
---
|
|
191
|
-
|
|
192
|
-
### SHA3_512
|
|
193
|
-
|
|
194
|
-
Fixed-output hash function. Produces a **64-byte** (512-bit) digest. Use this when
|
|
195
|
-
you need the highest security margin.
|
|
196
|
-
|
|
197
|
-
```typescript
|
|
198
|
-
class SHA3_512 {
|
|
199
|
-
constructor()
|
|
200
|
-
hash(msg: Uint8Array): Uint8Array // returns 64 bytes
|
|
201
|
-
dispose(): void
|
|
202
|
-
}
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
### SHAKE128
|
|
208
|
-
|
|
209
|
-
Extendable-output function (XOF). Produces **variable-length** output — any
|
|
210
|
-
number of bytes you request. 128-bit security level.
|
|
211
|
-
|
|
212
|
-
> [!CAUTION]
|
|
213
|
-
> `SHAKE128` is stateful and holds exclusive access to the `sha3` WASM module
|
|
214
|
-
> for its entire lifetime. Constructing a second SHAKE128/SHAKE256 or any
|
|
215
|
-
> other sha3 class (`SHA3_256`, etc.) while this instance is live throws.
|
|
216
|
-
> Call `dispose()` when done. Pool workers are unaffected.
|
|
217
|
-
|
|
218
|
-
```typescript
|
|
219
|
-
class SHAKE128 {
|
|
220
|
-
constructor()
|
|
221
|
-
hash(msg: Uint8Array, outputLength: number): Uint8Array
|
|
222
|
-
absorb(msg: Uint8Array): this
|
|
223
|
-
squeeze(n: number): Uint8Array
|
|
224
|
-
reset(): this
|
|
225
|
-
dispose(): void
|
|
226
|
-
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
| Method | Description |
|
|
230
|
-
|--------|-------------|
|
|
231
|
-
| `hash(msg, outputLength)` | One-shot: reset, absorb, squeeze. Safe on a dirty instance. |
|
|
232
|
-
| `absorb(msg)` | Feed data into the sponge. Chainable. Throws if called after `squeeze()`. |
|
|
233
|
-
| `squeeze(n)` | Pull `n` bytes of XOF output. Output is contiguous — `squeeze(a)` followed by `squeeze(b)` yields bytes `[0, a)` and `[a, a+b)` of the XOF stream. |
|
|
234
|
-
| `reset()` | Return to a fresh, zeroed state. Chainable. Safe at any point. Does not release the sha3 exclusivity token. |
|
|
235
|
-
| `dispose()` | Zero all WASM state and the TS-side block buffer, release the sha3 exclusivity token. Idempotent. |
|
|
236
|
-
|
|
237
|
-
**`outputLength`** / **`n`** must be `>= 1`. Values below 1 throw a `RangeError`.
|
|
238
|
-
|
|
239
|
-
After `dispose()`, all instance methods (`reset`, `absorb`, `squeeze`, `hash`)
|
|
240
|
-
throw `Error: SHAKE128: instance has been disposed`. Disposal is permanent;
|
|
241
|
-
construct a new instance if you need to continue.
|
|
242
|
-
|
|
243
|
-
---
|
|
244
|
-
|
|
245
|
-
### SHAKE256
|
|
246
|
-
|
|
247
|
-
Extendable-output function (XOF). Produces **variable-length** output — any
|
|
248
|
-
number of bytes you request. 256-bit security level.
|
|
249
|
-
|
|
250
|
-
> [!CAUTION]
|
|
251
|
-
> `SHAKE256` is stateful and holds exclusive access to the `sha3` WASM module
|
|
252
|
-
> for its entire lifetime. Constructing a second SHAKE128/SHAKE256 or any
|
|
253
|
-
> other sha3 class while this instance is live throws. Call `dispose()` when
|
|
254
|
-
> done.
|
|
255
|
-
|
|
256
|
-
```typescript
|
|
257
|
-
class SHAKE256 {
|
|
258
|
-
constructor()
|
|
259
|
-
hash(msg: Uint8Array, outputLength: number): Uint8Array
|
|
260
|
-
absorb(msg: Uint8Array): this
|
|
261
|
-
squeeze(n: number): Uint8Array
|
|
262
|
-
reset(): this
|
|
263
|
-
dispose(): void
|
|
264
|
-
}
|
|
265
|
-
```
|
|
266
|
-
|
|
267
|
-
| Method | Description |
|
|
268
|
-
|--------|-------------|
|
|
269
|
-
| `hash(msg, outputLength)` | One-shot: reset, absorb, squeeze. Safe on a dirty instance. |
|
|
270
|
-
| `absorb(msg)` | Feed data into the sponge. Chainable. Throws if called after `squeeze()`. |
|
|
271
|
-
| `squeeze(n)` | Pull `n` bytes of XOF output. Output is contiguous — `squeeze(a)` followed by `squeeze(b)` yields bytes `[0, a)` and `[a, a+b)` of the XOF stream. |
|
|
272
|
-
| `reset()` | Return to a fresh, zeroed state. Chainable. Safe at any point. Does not release the sha3 exclusivity token. |
|
|
273
|
-
| `dispose()` | Zero all WASM state and the TS-side block buffer, release the sha3 exclusivity token. Idempotent. |
|
|
274
|
-
|
|
275
|
-
**`outputLength`** / **`n`** must be `>= 1`. Values below 1 throw a `RangeError`.
|
|
276
|
-
|
|
277
|
-
After `dispose()`, all instance methods (`reset`, `absorb`, `squeeze`, `hash`)
|
|
278
|
-
throw `Error: SHAKE256: instance has been disposed`. Disposal is permanent;
|
|
279
|
-
construct a new instance if you need to continue.
|
|
280
|
-
|
|
281
|
-
---
|
|
282
|
-
|
|
283
|
-
## Incremental XOF API (`absorb` / `squeeze` / `reset`)
|
|
284
|
-
|
|
285
|
-
For use cases where you need to pull output in multiple steps — key derivation,
|
|
286
|
-
mask generation, protocol-specific domain separation — the SHAKE classes expose
|
|
287
|
-
a streaming interface alongside the one-shot `hash()`.
|
|
288
|
-
|
|
289
|
-
### State machine
|
|
290
|
-
|
|
291
|
-
| State | Valid calls |
|
|
292
|
-
|-------------|---------------------------------|
|
|
293
|
-
| fresh | `absorb()`, `hash()`, `reset()` |
|
|
294
|
-
| absorbing | `absorb()`, `squeeze()`, `hash()`, `reset()` |
|
|
295
|
-
| squeezing | `squeeze()`, `hash()`, `reset()` |
|
|
296
|
-
|
|
297
|
-
Calling `absorb()` while squeezing throws:
|
|
298
|
-
`"SHAKE128: cannot absorb after squeeze — call reset() first"`
|
|
299
|
-
|
|
300
|
-
`hash()` always resets before running — safe to call on a dirty instance.
|
|
301
|
-
|
|
302
|
-
### Example
|
|
303
|
-
|
|
304
|
-
```typescript
|
|
305
|
-
import { init, SHAKE256 } from 'leviathan-crypto'
|
|
306
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
307
|
-
|
|
308
|
-
await init({ sha3: sha3Wasm })
|
|
309
|
-
|
|
310
|
-
const xof = new SHAKE256()
|
|
311
|
-
xof.absorb(ikm) // input key material
|
|
312
|
-
xof.absorb(salt) // additional context
|
|
313
|
-
|
|
314
|
-
const encKey = xof.squeeze(32) // 256-bit encryption key
|
|
315
|
-
const macKey = xof.squeeze(32) // 256-bit MAC key
|
|
316
|
-
const nonce = xof.squeeze(12) // 96-bit nonce
|
|
317
|
-
|
|
318
|
-
xof.dispose()
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
---
|
|
322
|
-
|
|
323
|
-
## SHA3_256Hash
|
|
324
|
-
|
|
325
|
-
Stateless SHA3-256 `HashFn` for Fortuna's accumulator and reseed slots. Plain
|
|
326
|
-
`const` object — no instantiation, no `dispose()`.
|
|
327
|
-
|
|
328
|
-
Requires `init({ sha3: sha3Wasm })` (or the `keccak` alias). See
|
|
329
|
-
[fortuna.md](./fortuna.md) for full usage with `Fortuna.create()`.
|
|
330
|
-
|
|
331
|
-
| Property | Value |
|
|
332
|
-
|----------|-------|
|
|
333
|
-
| `outputSize` | `32` |
|
|
334
|
-
| `wasmModules` | `['sha3']` |
|
|
335
|
-
|
|
336
|
-
### `SHA3_256Hash.digest(msg): Uint8Array`
|
|
337
|
-
|
|
338
|
-
Hashes `msg` and returns a 32-byte SHA3-256 digest. Wipes WASM input/output/sponge
|
|
339
|
-
state scratch before returning.
|
|
340
|
-
|
|
341
|
-
| Parameter | Type | Description |
|
|
342
|
-
|-----------|------|-------------|
|
|
343
|
-
| `msg` | `Uint8Array` | Message to hash (any length) |
|
|
344
|
-
|
|
345
|
-
**Returns** a new `Uint8Array` of 32 bytes.
|
|
346
|
-
|
|
347
|
-
**Throws** `Error` if another stateful instance currently owns the `sha3` WASM module.
|
|
348
|
-
|
|
349
|
-
### Usage with `Fortuna`
|
|
350
|
-
|
|
351
|
-
```typescript
|
|
352
|
-
import { init, Fortuna } from 'leviathan-crypto'
|
|
353
|
-
import { SHA3_256Hash } from 'leviathan-crypto/sha3'
|
|
354
|
-
import { ChaCha20Generator } from 'leviathan-crypto/chacha20'
|
|
355
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
356
|
-
import { chacha20Wasm } from 'leviathan-crypto/chacha20/embedded'
|
|
357
|
-
|
|
358
|
-
await init({ sha3: sha3Wasm, chacha20: chacha20Wasm })
|
|
359
|
-
const rng = await Fortuna.create({ generator: ChaCha20Generator, hash: SHA3_256Hash })
|
|
360
|
-
const bytes = rng.get(32)
|
|
361
|
-
rng.stop()
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## Usage Examples
|
|
367
|
-
|
|
368
|
-
### Example 1: Hash a string with SHA3-256
|
|
369
|
-
|
|
370
|
-
The most common use case: hash some data and get a hex digest.
|
|
371
|
-
|
|
372
|
-
```typescript
|
|
373
|
-
import { init, SHA3_256, bytesToHex, utf8ToBytes } from 'leviathan-crypto'
|
|
374
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
375
|
-
|
|
376
|
-
// Initialize the SHA-3 WASM module (once, at startup)
|
|
377
|
-
await init({ sha3: sha3Wasm })
|
|
378
|
-
|
|
379
|
-
// Create a hasher
|
|
380
|
-
const sha3 = new SHA3_256()
|
|
381
|
-
|
|
382
|
-
// Hash a UTF-8 string
|
|
383
|
-
const message = utf8ToBytes('Hello, world!')
|
|
384
|
-
const digest = sha3.hash(message)
|
|
385
|
-
|
|
386
|
-
console.log(bytesToHex(digest))
|
|
387
|
-
// 32 bytes (64 hex characters) of SHA3-256 output
|
|
388
|
-
|
|
389
|
-
// Clean up -- zeroes all WASM state
|
|
390
|
-
sha3.dispose()
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
---
|
|
394
|
-
|
|
395
|
-
### Example 2: Hash binary data with SHA3-512
|
|
396
|
-
|
|
397
|
-
```typescript
|
|
398
|
-
import { init, SHA3_512, bytesToHex } from 'leviathan-crypto'
|
|
399
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
400
|
-
|
|
401
|
-
await init({ sha3: sha3Wasm })
|
|
402
|
-
|
|
403
|
-
const sha3 = new SHA3_512()
|
|
404
|
-
|
|
405
|
-
// Hash raw bytes (e.g., a file, a key, a nonce)
|
|
406
|
-
const data = new Uint8Array([0x01, 0x02, 0x03, 0x04])
|
|
407
|
-
const digest = sha3.hash(data)
|
|
408
|
-
|
|
409
|
-
console.log(bytesToHex(digest))
|
|
410
|
-
// 64 bytes (128 hex characters) of SHA3-512 output
|
|
411
|
-
|
|
412
|
-
sha3.dispose()
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
---
|
|
416
|
-
|
|
417
|
-
### Example 3: Hash multiple messages
|
|
418
|
-
|
|
419
|
-
Each call to `hash()` is independent; the internal state resets automatically.
|
|
420
|
-
You can reuse the same class instance for multiple hashes.
|
|
421
|
-
|
|
422
|
-
```typescript
|
|
423
|
-
import { init, SHA3_256, bytesToHex, utf8ToBytes } from 'leviathan-crypto'
|
|
424
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
425
|
-
|
|
426
|
-
await init({ sha3: sha3Wasm })
|
|
427
|
-
|
|
428
|
-
const sha3 = new SHA3_256()
|
|
429
|
-
|
|
430
|
-
const hash1 = sha3.hash(utf8ToBytes('first message'))
|
|
431
|
-
const hash2 = sha3.hash(utf8ToBytes('second message'))
|
|
432
|
-
const hash3 = sha3.hash(utf8ToBytes('first message'))
|
|
433
|
-
|
|
434
|
-
// hash1 and hash3 are identical -- same input, same output
|
|
435
|
-
console.log(bytesToHex(hash1) === bytesToHex(hash3)) // true
|
|
436
|
-
|
|
437
|
-
// hash2 is different -- different input
|
|
438
|
-
console.log(bytesToHex(hash1) === bytesToHex(hash2)) // false
|
|
439
|
-
|
|
440
|
-
sha3.dispose()
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
### Example 4: SHAKE128 variable-length output
|
|
446
|
-
|
|
447
|
-
SHAKE lets you choose exactly how many bytes of output you need. This is useful
|
|
448
|
-
for key derivation or generating fixed-size tokens.
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
import { init, SHAKE128, bytesToHex, utf8ToBytes } from 'leviathan-crypto'
|
|
452
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
453
|
-
|
|
454
|
-
await init({ sha3: sha3Wasm })
|
|
455
|
-
|
|
456
|
-
const shake = new SHAKE128()
|
|
457
|
-
|
|
458
|
-
const seed = utf8ToBytes('my-application-seed')
|
|
459
|
-
|
|
460
|
-
// Derive a 16-byte key (128 bits)
|
|
461
|
-
const key128 = shake.hash(seed, 16)
|
|
462
|
-
console.log('16-byte key:', bytesToHex(key128))
|
|
463
|
-
|
|
464
|
-
// Derive a 32-byte key (256 bits) from the same seed
|
|
465
|
-
const key256 = shake.hash(seed, 32)
|
|
466
|
-
console.log('32-byte key:', bytesToHex(key256))
|
|
467
|
-
|
|
468
|
-
// The 16-byte output is NOT a prefix of the 32-byte output --
|
|
469
|
-
// each call resets state, re-absorbs, and squeezes independently.
|
|
470
|
-
// However, for SHAKE, the first 16 bytes of the 32-byte output
|
|
471
|
-
// ARE identical to the 16-byte output (this is how XOFs work).
|
|
472
|
-
|
|
473
|
-
shake.dispose()
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
---
|
|
477
|
-
|
|
478
|
-
### Example 5: SHAKE256 for key derivation
|
|
479
|
-
|
|
480
|
-
```typescript
|
|
481
|
-
import { init, SHAKE256, bytesToHex } from 'leviathan-crypto'
|
|
482
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
483
|
-
|
|
484
|
-
await init({ sha3: sha3Wasm })
|
|
485
|
-
|
|
486
|
-
const shake = new SHAKE256()
|
|
487
|
-
|
|
488
|
-
// Derive a 48-byte key from raw entropy
|
|
489
|
-
const entropy = crypto.getRandomValues(new Uint8Array(32))
|
|
490
|
-
const derivedKey = shake.hash(entropy, 48)
|
|
491
|
-
|
|
492
|
-
console.log('Derived key:', bytesToHex(derivedKey))
|
|
493
|
-
// 48 bytes (96 hex characters) of SHAKE256 output
|
|
494
|
-
|
|
495
|
-
shake.dispose()
|
|
496
|
-
```
|
|
497
|
-
|
|
498
|
-
---
|
|
499
|
-
|
|
500
|
-
### Example 6: SHA-256 vs SHA3-256
|
|
501
|
-
|
|
502
|
-
SHA-256 (from the SHA-2 family) and SHA3-256 are completely different algorithms.
|
|
503
|
-
They produce different output for the same input. Both are secure; SHA3-256 adds defense-in-depth.
|
|
504
|
-
|
|
505
|
-
```typescript
|
|
506
|
-
import { init, SHA256, SHA3_256, bytesToHex, utf8ToBytes } from 'leviathan-crypto'
|
|
507
|
-
import { sha2Wasm } from 'leviathan-crypto/sha2/embedded'
|
|
508
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
509
|
-
|
|
510
|
-
// Initialize both modules
|
|
511
|
-
await init({ sha2: sha2Wasm, sha3: sha3Wasm })
|
|
512
|
-
|
|
513
|
-
const sha2 = new SHA256()
|
|
514
|
-
const sha3 = new SHA3_256()
|
|
515
|
-
|
|
516
|
-
const message = utf8ToBytes('abc')
|
|
517
|
-
|
|
518
|
-
const sha2Digest = sha2.hash(message)
|
|
519
|
-
const sha3Digest = sha3.hash(message)
|
|
520
|
-
|
|
521
|
-
console.log('SHA-256: ', bytesToHex(sha2Digest))
|
|
522
|
-
console.log('SHA3-256: ', bytesToHex(sha3Digest))
|
|
523
|
-
// These are completely different values -- different algorithms
|
|
524
|
-
|
|
525
|
-
sha2.dispose()
|
|
526
|
-
sha3.dispose()
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
---
|
|
530
|
-
|
|
531
|
-
### Example 7: Hashing empty input
|
|
532
|
-
|
|
533
|
-
All hash functions accept empty input. This is well-defined and produces a
|
|
534
|
-
deterministic output.
|
|
535
|
-
|
|
536
|
-
```typescript
|
|
537
|
-
import { init, SHA3_256, bytesToHex } from 'leviathan-crypto'
|
|
538
|
-
import { sha3Wasm } from 'leviathan-crypto/sha3/embedded'
|
|
539
|
-
|
|
540
|
-
await init({ sha3: sha3Wasm })
|
|
541
|
-
|
|
542
|
-
const sha3 = new SHA3_256()
|
|
543
|
-
const digest = sha3.hash(new Uint8Array(0))
|
|
544
|
-
|
|
545
|
-
console.log(bytesToHex(digest))
|
|
546
|
-
// The SHA3-256 hash of empty input -- a fixed, known value
|
|
547
|
-
|
|
548
|
-
sha3.dispose()
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
---
|
|
552
|
-
|
|
553
|
-
## Error Conditions
|
|
554
|
-
|
|
555
|
-
### SHA-3 module not initialized
|
|
556
|
-
|
|
557
|
-
If you construct a SHA-3 class before initializing the module, the constructor
|
|
558
|
-
throws immediately:
|
|
559
|
-
|
|
560
|
-
```
|
|
561
|
-
Error: leviathan-crypto: call init({ sha3: ... }) before using this class
|
|
562
|
-
```
|
|
563
|
-
|
|
564
|
-
**Fix:** Call `await init({ sha3: sha3Wasm })` once at application startup, before creating
|
|
565
|
-
any SHA-3 class instances.
|
|
566
|
-
|
|
567
|
-
---
|
|
568
|
-
|
|
569
|
-
### SHAKE output length out of range
|
|
570
|
-
|
|
571
|
-
SHAKE128 and SHAKE256 require `outputLength >= 1`. Passing 0 or a negative number
|
|
572
|
-
throws a `RangeError`:
|
|
573
|
-
|
|
574
|
-
```
|
|
575
|
-
RangeError: outputLength must be >= 1 (got 0)
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
**Fix:** Request at least 1 byte.
|
|
579
|
-
|
|
580
|
-
---
|
|
581
|
-
|
|
582
|
-
### SHAKE absorb after squeeze
|
|
583
|
-
|
|
584
|
-
Calling `absorb()` after `squeeze()` has been called throws an `Error`. The sponge
|
|
585
|
-
has been padded and finalized — further absorption is not meaningful.
|
|
586
|
-
|
|
587
|
-
```
|
|
588
|
-
Error: SHAKE128: cannot absorb after squeeze — call reset() first
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
**Fix:** Call `reset()` to return the instance to a fresh state before absorbing
|
|
592
|
-
new data.
|
|
593
|
-
|
|
594
|
-
---
|
|
595
|
-
|
|
596
|
-
### Empty input
|
|
597
|
-
|
|
598
|
-
Passing an empty `Uint8Array` (length 0) is **not** an error. All SHA-3 and SHAKE
|
|
599
|
-
functions produce valid, deterministic output for empty input. The sponge simply
|
|
600
|
-
absorbs zero bytes and then squeezes.
|
|
601
|
-
|
|
602
|
-
---
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
## Cross-References
|
|
606
|
-
|
|
607
|
-
| Document | Description |
|
|
608
|
-
| -------- | ----------- |
|
|
609
|
-
| [index](./README.md) | Project Documentation index |
|
|
610
|
-
| [architecture](./architecture.md) | architecture overview, module relationships, buffer layouts, and build pipeline |
|
|
611
|
-
| [sha3_audit.md](./sha3_audit.md) | SHA-3 / Keccak implementation audit |
|
|
612
|
-
|