Skip to content

Commit 90d0f4d

Browse files
authored
chore: audit implementation coverage and fix ECDH deriveBits (#910)
1 parent a0453cf commit 90d0f4d

10 files changed

Lines changed: 394 additions & 46 deletions

File tree

.claude/commands/commit.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Commit Changes
2+
3+
Stage and commit the current changes with a well-crafted message.
4+
5+
## Instructions
6+
7+
When activated, commit the current working tree changes:
8+
9+
1. **Sync with remote**:
10+
- Run `git fetch origin main` to get latest upstream
11+
- Run `git log HEAD..origin/main --oneline` to check if main has moved ahead
12+
- If it has, warn the user but don't rebase automatically
13+
14+
2. **Ensure we're not on main**:
15+
- Run `git branch --show-current`
16+
- If on `main`, create a new feature branch:
17+
- Look at the staged/unstaged changes to infer a branch name
18+
- Run `git checkout -b feat/<descriptive-name>`
19+
- Inform the user of the new branch name
20+
21+
3. **Review changes**:
22+
- Run `git diff --stat` and `git diff --staged --stat` to see what's changed
23+
- If nothing is staged, run `git add -A` to stage everything
24+
- Run `git diff --staged --stat` to confirm what will be committed
25+
26+
4. **Generate commit message**:
27+
- Use conventional commit format: `type: short description`
28+
- Types: `feat`, `fix`, `refactor`, `chore`, `docs`, `test`
29+
- If the change is substantial, add a body paragraph separated by a blank line
30+
- Body should explain **what** changed and **why**, not how (the diff shows how)
31+
- Keep the subject line under 72 characters
32+
33+
5. **Commit**:
34+
```bash
35+
git commit -m "<message>"
36+
```
37+
38+
6. **Report** the commit hash and summary to the user
39+
40+
If the user provides arguments (e.g., `/commit "fix: resolve race condition"`), use that as the commit message instead of generating one.

.claude/plans/quick-wins.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Quick Implementation Wins
2+
3+
Items identified during the implementation-coverage audit (#907) that should be
4+
straightforward to implement.
5+
6+
## crypto.hash() oneshot function
7+
- Node.js v21.7.0+ `crypto.hash(algorithm, data[, outputEncoding])`
8+
- Simply wraps createHash/update/digest in one call
9+
- Trivial to implement — just a convenience function
10+
- Reference: `crypto.createHash(algorithm).update(data).digest(outputEncoding)`
11+
12+
## subtle.deriveKey with ECDH
13+
- `subtle.deriveBits` already supports ECDH via `ecDeriveBits()`
14+
- `subtle.deriveKey` is missing the ECDH case in its switch statement
15+
- Fix: add `case 'ECDH':` to the deriveKey switch that calls deriveBits (same pattern as X25519/X448)
16+
17+
## crypto.getCurves()
18+
- Similar to existing `getCiphers()` and `getHashes()`
19+
- Returns list of supported EC curve names
20+
- OpenSSL has APIs to enumerate curves
21+
22+
## Ed25519/Ed448 JWK export/import
23+
- spki/pkcs8/raw formats already work
24+
- JWK is the remaining gap
25+
- Node.js and WebCrypto both support JWK for Ed25519/Ed448
26+
- Closes #653 (subtle.importKey with Ed25519)
27+
28+
## KeyObject.equals()
29+
- Compare two KeyObjects for equality
30+
- Should be straightforward with exported key comparison
31+
32+
## KeyObject.symmetricKeySize
33+
- Return the size of a symmetric key in bytes
34+
- Simple property accessor
35+
36+
## createDiffieHellmanGroup alias
37+
- Node.js exports `createDiffieHellmanGroup` as an alias for `getDiffieHellman`
38+
- `getDiffieHellman` already exists and works
39+
- Just add a re-export: `export { getDiffieHellman as createDiffieHellmanGroup }`
40+
41+
## diffieHellman.verifyError
42+
- DiffieHellman class is fully implemented except this property
43+
- Returns verification errors from DH parameter checking

.docs/implementation-coverage.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ These algorithms provide quantum-resistant cryptography.
121121
*`crypto.createSign(algorithm[, options])`
122122
*`crypto.createVerify(algorithm[, options])`
123123
*`crypto.decapsulate(key, ciphertext[, callback])`
124-
* `crypto.diffieHellman(options[, callback])`
124+
* `crypto.diffieHellman(options[, callback])`
125125
*`crypto.encapsulate(key[, callback])`
126126
*`crypto.fips` deprecated
127127
*`crypto.generateKey(type, options, callback)`
@@ -290,7 +290,7 @@ These ciphers are **not available in Node.js** but are provided by RNQC via libs
290290
## `subtle.deriveBits`
291291
| Algorithm | Status |
292292
| --------- | :----: |
293-
| `ECDH` | |
293+
| `ECDH` | |
294294
| `X25519` ||
295295
| `X448` ||
296296
| `HKDF` ||
@@ -336,11 +336,11 @@ These ciphers are **not available in Node.js** but are provided by RNQC via libs
336336
| `AES-GCM` | | |||| | |
337337
| `AES-KW` | | |||| | |
338338
| `AES-OCB` | | || || | |
339-
| `ChaCha20-Poly1305` | | | | | | | |
339+
| `ChaCha20-Poly1305` | | | | | | | |
340340
| `ECDH` ||||| || |
341341
| `ECDSA` ||||| || |
342-
| `Ed25519` |||| | || |
343-
| `Ed448` |||| | || |
342+
| `Ed25519` |||| | || |
343+
| `Ed448` |||| | || |
344344
| `HMAC` | | |||| | |
345345
| `ML-DSA-44` |||| | |||
346346
| `ML-DSA-65` |||| | |||
@@ -374,18 +374,18 @@ These ciphers are **not available in Node.js** but are provided by RNQC via libs
374374
| `RSA-OAEP` ||
375375
| `RSA-PSS` ||
376376
| `RSASSA-PKCS1-v1_5` ||
377-
| `X25519` | |
378-
| `X448` | |
377+
| `X25519` | |
378+
| `X448` | |
379379

380380
### `CryptoKey` algorithms
381381
| Algorithm | Status |
382382
| --------- | :----: |
383383
| `AES-CTR` ||
384384
| `AES-CBC` ||
385385
| `AES-GCM` ||
386-
| `AES-KW` | |
386+
| `AES-KW` | |
387387
| `AES-OCB` ||
388-
| `ChaCha20-Poly1305` | |
388+
| `ChaCha20-Poly1305` | |
389389
| `HMAC` ||
390390

391391
## `subtle.importKey`
@@ -396,7 +396,7 @@ These ciphers are **not available in Node.js** but are provided by RNQC via libs
396396
| `AES-GCM` | | |||| | |
397397
| `AES-KW` | | |||| | |
398398
| `AES-OCB` | | || || | |
399-
| `ChaCha20-Poly1305` | | | | | | | |
399+
| `ChaCha20-Poly1305` | | | | | | | |
400400
| `ECDH` ||||| || |
401401
| `ECDSA` ||||| || |
402402
| `Ed25519` ||||| || |

docs/data/coverage.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,9 @@ export const COVERAGE_DATA: CoverageCategory[] = [
135135
{ name: 'constants', status: 'implemented' },
136136
{ name: 'createCipheriv', status: 'implemented' },
137137
{ name: 'createDecipheriv', status: 'implemented' },
138-
{ name: 'createDiffieHellman', status: 'missing' },
138+
{ name: 'createDiffieHellman', status: 'implemented' },
139139
{ name: 'createDiffieHellmanGroup', status: 'missing' },
140-
{ name: 'createECDH', status: 'missing' },
140+
{ name: 'createECDH', status: 'implemented' },
141141
{ name: 'createHash', status: 'implemented' },
142142
{ name: 'createHmac', status: 'implemented' },
143143
{ name: 'createPrivateKey', status: 'implemented' },
@@ -205,7 +205,7 @@ export const COVERAGE_DATA: CoverageCategory[] = [
205205
{ name: 'getCipherInfo', status: 'missing' },
206206
{ name: 'getCiphers', status: 'implemented' },
207207
{ name: 'getCurves', status: 'missing' },
208-
{ name: 'getDiffieHellman', status: 'missing' },
208+
{ name: 'getDiffieHellman', status: 'implemented' },
209209
{ name: 'getFips', status: 'missing' },
210210
{ name: 'getHashes', status: 'implemented' },
211211
{ name: 'getRandomValues', status: 'implemented' },
@@ -274,7 +274,7 @@ export const COVERAGE_DATA: CoverageCategory[] = [
274274
{
275275
name: 'crypto.subtle.deriveBits',
276276
subItems: [
277-
{ name: 'ECDH', status: 'missing' },
277+
{ name: 'ECDH', status: 'implemented' },
278278
{ name: 'X25519', status: 'implemented' },
279279
{ name: 'X448', status: 'implemented' },
280280
{ name: 'HKDF', status: 'implemented' },
@@ -326,8 +326,8 @@ export const COVERAGE_DATA: CoverageCategory[] = [
326326
{ name: 'AES-OCB', status: 'missing', note: 'Not implemented' },
327327
{
328328
name: 'ChaCha20-Poly1305',
329-
status: 'missing',
330-
note: 'Not implemented',
329+
status: 'partial',
330+
note: 'jwk, raw',
331331
},
332332
{
333333
name: 'ECDH',
@@ -339,8 +339,8 @@ export const COVERAGE_DATA: CoverageCategory[] = [
339339
status: 'partial',
340340
note: 'spki, pkcs8, jwk, raw, raw-public',
341341
},
342-
{ name: 'Ed25519', status: 'partial', note: 'spki, pkcs8' },
343-
{ name: 'Ed448', status: 'partial', note: 'spki, pkcs8' },
342+
{ name: 'Ed25519', status: 'partial', note: 'spki, pkcs8, raw' },
343+
{ name: 'Ed448', status: 'partial', note: 'spki, pkcs8, raw' },
344344
{ name: 'HMAC', status: 'partial', note: 'jwk, raw, raw-secret' },
345345
{
346346
name: 'ML-DSA-44',
@@ -385,14 +385,14 @@ export const COVERAGE_DATA: CoverageCategory[] = [
385385
{ name: 'RSA-OAEP', status: 'implemented' },
386386
{ name: 'RSA-PSS', status: 'implemented' },
387387
{ name: 'RSASSA-PKCS1-v1_5', status: 'implemented' },
388-
{ name: 'X25519', status: 'missing' },
389-
{ name: 'X448', status: 'missing' },
388+
{ name: 'X25519', status: 'implemented' },
389+
{ name: 'X448', status: 'implemented' },
390390
{ name: 'AES-CTR', status: 'implemented' },
391391
{ name: 'AES-CBC', status: 'implemented' },
392392
{ name: 'AES-GCM', status: 'implemented' },
393-
{ name: 'AES-KW', status: 'missing' },
393+
{ name: 'AES-KW', status: 'implemented' },
394394
{ name: 'AES-OCB', status: 'missing' },
395-
{ name: 'ChaCha20-Poly1305', status: 'missing' },
395+
{ name: 'ChaCha20-Poly1305', status: 'implemented' },
396396
{ name: 'HMAC', status: 'implemented' },
397397
],
398398
},
@@ -404,7 +404,7 @@ export const COVERAGE_DATA: CoverageCategory[] = [
404404
{ name: 'AES-GCM', status: 'partial', note: 'jwk, raw, raw-secret' },
405405
{ name: 'AES-KW', status: 'partial', note: 'jwk, raw, raw-secret' },
406406
{ name: 'AES-OCB', status: 'missing' },
407-
{ name: 'ChaCha20-Poly1305', status: 'missing' },
407+
{ name: 'ChaCha20-Poly1305', status: 'partial', note: 'jwk, raw' },
408408
{
409409
name: 'ECDH',
410410
status: 'partial',

example/ios/Podfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2811,7 +2811,7 @@ SPEC CHECKSUMS:
28112811
MMKVCore: f2dd4c9befea04277a55e84e7812f930537993df
28122812
NitroMmkv: afbc5b2fbf963be567c6c545aa1efcf6a9cec68e
28132813
NitroModules: 11bba9d065af151eae51e38a6425e04c3b223ff3
2814-
QuickCrypto: 9e46baaa4fea5a22fdf23c3aae184b983c948b23
2814+
QuickCrypto: ac4d2eead1de738bcf06f565c4ab31db817f88c1
28152815
RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
28162816
RCTDeprecation: c4b9e2fd0ab200e3af72b013ed6113187c607077
28172817
RCTRequired: e97dd5dafc1db8094e63bc5031e0371f092ae92a

0 commit comments

Comments
 (0)