Skip to content

Commit 34e61cd

Browse files
authored
feat: add SHA-3 and cSHAKE support to subtle.digest() (#942)
1 parent e040d63 commit 34e61cd

10 files changed

Lines changed: 200 additions & 40 deletions

File tree

.claude/agents/orchestrator.md

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ description: MUST BE USED for all multi-file operations (3+ files) or cross-doma
2020
## When to Activate
2121

2222
Use orchestrator for:
23+
2324
- Tasks touching 3+ files
2425
- Cross-language operations (e.g., TypeScript + C++)
2526
- New feature development with multiple components
@@ -31,16 +32,19 @@ Use orchestrator for:
3132
When you receive a request:
3233

3334
1. **Map all dependencies**
35+
3436
- Which layers are affected? (JS, C++, native bridging)
3537
- What are the data flows?
3638
- Are there shared types or interfaces?
3739

3840
2. **Identify parallelization opportunities**
41+
3942
- Which tasks are independent?
4043
- What can run concurrently?
4144
- What must be sequential?
4245

4346
3. **Create explicit task boundaries**
47+
4448
- Each specialist gets a clear, focused scope
4549
- Define success criteria
4650
- Specify interfaces/contracts between tasks
@@ -54,6 +58,7 @@ When you receive a request:
5458
## Orchestration Examples
5559

5660
### Example 1: New Crypto Feature (WebCrypto API)
61+
5762
```
5863
User Request: "Implement subtle.encrypt/decrypt for AES-GCM"
5964
@@ -76,6 +81,7 @@ Wave 3 (Validation):
7681
```
7782

7883
### Example 2: Refactoring to Modern C++
84+
7985
```
8086
User Request: "Migrate hash functions from OpenSSL 1.1.1 to 3.6+"
8187
@@ -90,13 +96,14 @@ Wave 1 (Research):
9096
9197
Wave 2 (Migration):
9298
- cpp-specialist: Update to EVP_* APIs, modernize C++ patterns
93-
99+
94100
Wave 3 (Validation):
95101
- crypto-specialist: Ensure cryptographic correctness maintained
96102
- testing-specialist: Verify no regressions
97103
```
98104

99105
### Example 3: Node.js Polyfill Feature
106+
100107
```
101108
User Request: "Add support for crypto.pbkdf2"
102109
@@ -121,13 +128,17 @@ Wave 3 (Compatibility):
121128
## Communication Protocol
122129

123130
### Input Format
131+
124132
You receive tasks in natural language. Extract:
133+
125134
- Goal (what needs to be accomplished)
126135
- Constraints (compatibility, performance, security)
127136
- Context (related code, dependencies)
128137

129138
### Output Format
139+
130140
Provide:
141+
131142
1. **Task Analysis**: What needs to be done and why
132143
2. **Dependency Map**: What depends on what
133144
3. **Wave Plan**: Sequential waves of parallel tasks
@@ -137,12 +148,13 @@ Provide:
137148

138149
## Rules You Must Follow
139150

140-
1. **Never write code yourself** - always delegate to specialists
141-
2. **Always parallelize independent tasks** - maximize efficiency
142-
3. **Enforce architectural rules** from `.claude/rules/*.xml`
143-
4. **Track all metrics** - token usage, timing, cost estimates
144-
5. **Validate completeness** - ensure all requirements met before marking done
145-
6. **Report clearly** - synthesize specialist work into coherent summary
151+
1. **Never commit to main** - always create a feature branch (`feat/<name>`, `fix/<name>`, `refactor/<name>`) before the first commit
152+
2. **Never write code yourself** - always delegate to specialists
153+
3. **Always parallelize independent tasks** - maximize efficiency
154+
4. **Enforce architectural rules** from `.claude/rules/*.xml`
155+
5. **Track all metrics** - token usage, timing, cost estimates
156+
6. **Validate completeness** - ensure all requirements met before marking done
157+
7. **Report clearly** - synthesize specialist work into coherent summary
146158

147159
## Available Specialists
148160

@@ -173,6 +185,7 @@ if (task spans multiple domains):
173185
## Success Metrics
174186

175187
Track and report:
188+
176189
- Total tokens used across all specialists
177190
- Time elapsed (wall clock)
178191
- Estimated cost (if applicable)

.docs/implementation-coverage.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ These algorithms provide quantum-resistant cryptography.
105105
-`x509.validFrom`
106106
-`x509.validTo`
107107
-`x509.verify(publicKey)`
108-
- 🚧 node:crypto module methods and properties
108+
- node:crypto module methods and properties
109109
-`crypto.argon2(algorithm, parameters, callback)`
110110
-`crypto.argon2Sync(algorithm, parameters)`
111111
-`crypto.checkPrime(candidate[, options], callback)`
@@ -277,7 +277,7 @@ These ciphers are **not available in Node.js** but are provided by RNQC via libs
277277
-`subtle.decrypt(algorithm, key, data)`
278278
-`subtle.deriveBits(algorithm, baseKey, length)`
279279
-`subtle.deriveKey(algorithm, baseKey, derivedKeyAlgorithm, extractable, keyUsages)`
280-
- 🚧 `subtle.digest(algorithm, data)`
280+
- `subtle.digest(algorithm, data)`
281281
-`subtle.encapsulateBits(encapsulationAlgorithm, encapsulationKey)`
282282
-`subtle.encapsulateKey(encapsulationAlgorithm, encapsulationKey, sharedKeyAlgorithm, extractable, usages)`
283283
- 🚧 `subtle.encrypt(algorithm, key, data)`
@@ -331,15 +331,17 @@ These ciphers are **not available in Node.js** but are provided by RNQC via libs
331331

332332
| Algorithm | Status |
333333
| ----------- | :----: |
334-
| `cSHAKE128` | |
335-
| `cSHAKE256` | |
334+
| `cSHAKE128` | |
335+
| `cSHAKE256` | |
336336
| `SHA-1` ||
337337
| `SHA-256` ||
338338
| `SHA-384` ||
339339
| `SHA-512` ||
340-
| `SHA3-256` ||
341-
| `SHA3-384` ||
342-
| `SHA3-512` ||
340+
| `SHA3-256` ||
341+
| `SHA3-384` ||
342+
| `SHA3-512` ||
343+
344+
> **Note:** `cSHAKE128` and `cSHAKE256` provide SHAKE128/SHAKE256 (XOF) functionality with empty customization, matching Node.js behavior. The `length` parameter (in bytes, must be a multiple of 8) is required to specify the output length.
343345
344346
## `subtle.encrypt`
345347

CLAUDE.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ This project uses the **4-Layer Orchestra Architecture** for efficient multi-age
1212
## Critical Principles
1313

1414
### 1. API Priority Order (NON-NEGOTIABLE)
15+
1516
When implementing features, favor in this order:
17+
1618
1. **WebCrypto API** - Modern standard, best for `subtle.*` methods
1719
2. **Node.js Implementation** - Use `$REPOS/node/deps/ncrypto` as reference
1820
3. **ncrypto** - submodule code reference at `$REPOS/ncrypto` (do work w/ OpenSSL)
1921

2022
**Always check Node.js `deps/ncrypto` before implementing new features.**
2123

2224
### 2. Modern Stack Required
25+
2326
- **React Native** - Mobile framework
2427
- **TypeScript** - Type system (strict mode, no `any`)
2528
- **Nitro Modules** - Native bridging
@@ -28,12 +31,21 @@ When implementing features, favor in this order:
2831
- **Bun 1.3+** - TypeScript package manager
2932

3033
### 3. Code Philosophy
34+
3135
- Minimize code rather than add more
3236
- Prefer iteration and modularization over duplication
3337
- No comments unless code is sufficiently complex
3438
- Code should be self-documenting
3539

36-
### 4. Security is Critical
40+
### 4. Never Commit to Main
41+
42+
- **ALWAYS** create a feature branch before the first commit
43+
- Branch naming: `feat/<name>`, `fix/<name>`, `refactor/<name>`
44+
- All changes go through PRs — never push directly to main
45+
- If you find yourself on main, create a branch before committing
46+
47+
### 5. Security is Critical
48+
3749
- Constant-time comparisons for authentication tags
3850
- Cryptographically secure randomness (RAND_bytes)
3951
- AEAD modes preferred (AES-GCM)
@@ -45,6 +57,7 @@ When implementing features, favor in this order:
4557
For full details, see `.claude/rules/*.xml`:
4658

4759
### architecture.xml
60+
4861
- Project context and goals
4962
- API priority order (WebCrypto → Node.js → ncrypto)
5063
- Tech stack requirements
@@ -53,6 +66,7 @@ For full details, see `.claude/rules/*.xml`:
5366
- Local codebase references
5467

5568
### code-typescript.xml
69+
5670
- No `any` or `unknown` casts
5771
- Interfaces over types
5872
- Named exports only (no default)
@@ -62,6 +76,7 @@ For full details, see `.claude/rules/*.xml`:
6276
- React best practices (minimal useEffect)
6377

6478
### code-cpp.xml
79+
6580
- C++20 minimum with modern features
6681
- Smart pointers for all ownership
6782
- OpenSSL 3.6+ EVP APIs only (no deprecated)
@@ -70,6 +85,7 @@ For full details, see `.claude/rules/*.xml`:
7085
- Memory safety (no leaks, no raw ownership)
7186

7287
### crypto-security.xml
88+
7389
- Cryptographic correctness (match specs)
7490
- No timing attacks (CRYPTO_memcmp)
7591
- Secure RNG (RAND_bytes)
@@ -79,6 +95,7 @@ For full details, see `.claude/rules/*.xml`:
7995
- No key material in errors
8096

8197
### ci-caching.xml
98+
8299
- iOS Pods/DerivedData cache consistency (exact-match Pods, no restore-keys)
83100
- Cache key design (no version suffixes, use hashFiles)
84101
- Android Maestro patterns (don't launch app before Maestro)
@@ -87,12 +104,14 @@ For full details, see `.claude/rules/*.xml`:
87104
## When to Use Orchestration
88105

89106
### Use Orchestrator For:
107+
90108
- ✅ Tasks touching 3+ files
91109
- ✅ Cross-language changes (TypeScript + C++)
92110
- ✅ New crypto features (API + implementation)
93111
- ✅ Complex refactoring
94112

95113
### Work Directly For:
114+
96115
- ✅ Single file changes
97116
- ✅ Simple bug fixes
98117
- ✅ Type updates
@@ -111,14 +130,17 @@ For full details, see `.claude/rules/*.xml`:
111130
Use these instead of web searches:
112131

113132
- **Node.js**: `$REPOS/node`
133+
114134
- `deps/ncrypto` - Use as bible for crypto operations
115135
- May need updating to OpenSSL 3.6+ patterns
116136

117137
- **ncrypto**: `$REPOS/ncrypto`
138+
118139
- separate crypto lib broken out from Node.js
119140
- Patterns and tools to access OpenSSL
120141

121142
- **Nitro**: `$REPOS/nitro`
143+
122144
- iOS CI caching patterns (super-fast builds)
123145
- Nitro Modules bridging examples
124146

@@ -128,7 +150,7 @@ Use these instead of web searches:
128150

129151
## Testing
130152

131-
Tests run in the React Native example app environment, not standard Node.js test runners.
153+
Tests run in the React Native example app environment, not standard Node.js test runners.
132154

133155
Don't ask to run tests - they must be executed in the example React Native application.
134156

@@ -139,6 +161,7 @@ Metro output is tee'd to `/tmp/rnqc-metro.log`. When debugging test failures, re
139161
## Quality Checks
140162

141163
Before committing:
164+
142165
- [ ] Type safety (no `any`, proper interfaces)
143166
- [ ] Memory safety (smart pointers, RAII)
144167
- [ ] Cryptographic correctness (test vectors)

docs/data/coverage.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,15 +349,15 @@ export const COVERAGE_DATA: CoverageCategory[] = [
349349
{
350350
name: 'crypto.subtle.digest',
351351
subItems: [
352-
{ name: 'cSHAKE128', status: 'missing' },
353-
{ name: 'cSHAKE256', status: 'missing' },
352+
{ name: 'cSHAKE128', status: 'implemented' },
353+
{ name: 'cSHAKE256', status: 'implemented' },
354354
{ name: 'SHA-1', status: 'implemented' },
355355
{ name: 'SHA-256', status: 'implemented' },
356356
{ name: 'SHA-384', status: 'implemented' },
357357
{ name: 'SHA-512', status: 'implemented' },
358-
{ name: 'SHA3-256', status: 'missing' },
359-
{ name: 'SHA3-384', status: 'missing' },
360-
{ name: 'SHA3-512', status: 'missing' },
358+
{ name: 'SHA3-256', status: 'implemented' },
359+
{ name: 'SHA3-384', status: 'implemented' },
360+
{ name: 'SHA3-512', status: 'implemented' },
361361
],
362362
},
363363
{

example/src/tests/subtle/digest.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ const kTests: Test[] = [
2121
['SHA-256', 'sha256', 256],
2222
['SHA-384', 'sha384', 384],
2323
['SHA-512', 'sha512', 512],
24+
['SHA3-256', 'sha3-256', 256],
25+
['SHA3-384', 'sha3-384', 384],
26+
['SHA3-512', 'sha3-512', 512],
2427
];
2528

2629
const kData = toArrayBuffer(Buffer.from('hello'));
@@ -46,3 +49,32 @@ kTests.forEach(([algorithm, legacyName, bitLength]) => {
4649
});
4750
});
4851
});
52+
53+
// cSHAKE tests (XOF - extendable output functions)
54+
test(SUITE, 'hash: cSHAKE128', async () => {
55+
const outputLength = 32;
56+
const checkValue = createHash('shake128', { outputLength })
57+
.update(kData)
58+
.digest()
59+
.toString('hex');
60+
61+
const result = await subtle.digest(
62+
{ name: 'cSHAKE128', length: outputLength },
63+
kData,
64+
);
65+
expect(ab2str(result)).to.equal(checkValue);
66+
});
67+
68+
test(SUITE, 'hash: cSHAKE256', async () => {
69+
const outputLength = 64;
70+
const checkValue = createHash('shake256', { outputLength })
71+
.update(kData)
72+
.digest()
73+
.toString('hex');
74+
75+
const result = await subtle.digest(
76+
{ name: 'cSHAKE256', length: outputLength },
77+
kData,
78+
);
79+
expect(ab2str(result)).to.equal(checkValue);
80+
});

0 commit comments

Comments
 (0)