toiljs 0.0.115 → 0.0.117
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/CHANGELOG.md +10 -0
- package/README.md +16 -7
- package/TYPESCRIPT_LAW.md +1946 -2073
- package/build/backend/.tsbuildinfo +1 -1
- package/build/cli/.tsbuildinfo +1 -1
- package/build/cli/index.js +2375 -258
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/dev/devtools.js +1 -1
- package/build/client/dev/error-overlay.js +1 -1
- package/build/client/routing/mount.js +1 -1
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/auth-emails.js +7 -3
- package/build/compiler/emails.js +1 -1
- package/build/compiler/index.d.ts +1 -0
- package/build/compiler/index.js +25 -4
- package/build/compiler/pages.js +2 -3
- package/build/compiler/prerender.d.ts +3 -8
- package/build/compiler/prerender.js +88 -127
- package/build/compiler/ssg.js +3 -4
- package/build/compiler/template-build.js +3 -4
- package/build/compiler/toil-docs.generated.js +6 -5
- package/build/compiler/vite.js +3 -6
- package/build/devserver/.tsbuildinfo +1 -1
- package/build/devserver/db/database.js +7 -3
- package/build/devserver/db/types.js +1 -1
- package/build/devserver/production.js +4 -3
- package/build/devserver/runtime/crypto.d.ts +1 -1
- package/build/io/.tsbuildinfo +1 -1
- package/build/logger/.tsbuildinfo +1 -1
- package/build/shared/.tsbuildinfo +1 -1
- package/examples/basic/client/routes/analytics.tsx +7 -5
- package/examples/basic/server/tsconfig.json +1 -3
- package/package.json +45 -44
- package/presets/no-uint8array-tostring.js +120 -153
- package/presets/oxlint.d.ts +5 -0
- package/presets/oxlint.js +224 -0
- package/server/runtime/tsconfig.json +1 -3
- package/tsconfig.json +2 -11
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -90
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -43
- package/.github/changelog-config.json +0 -45
- package/.github/dependabot.yml +0 -27
- package/.github/workflows/ci.yml +0 -222
- package/.vscode/settings.json +0 -10
- package/docs/README.md +0 -107
- package/docs/auth/README.md +0 -104
- package/docs/auth/configuration.md +0 -105
- package/docs/auth/emails.md +0 -92
- package/docs/auth/extending.md +0 -202
- package/docs/auth/how-it-works.md +0 -138
- package/docs/auth/usage.md +0 -188
- package/docs/backend/README.md +0 -143
- package/docs/backend/data.md +0 -351
- package/docs/backend/rest.md +0 -402
- package/docs/backend/rpc.md +0 -226
- package/docs/background/README.md +0 -114
- package/docs/background/daemons.md +0 -276
- package/docs/background/derive.md +0 -179
- package/docs/cli/README.md +0 -379
- package/docs/concepts/ai-guide.md +0 -132
- package/docs/concepts/config.md +0 -416
- package/docs/concepts/decorators.md +0 -127
- package/docs/concepts/security.md +0 -108
- package/docs/concepts/tiers.md +0 -166
- package/docs/concepts/types.md +0 -216
- package/docs/database/README.md +0 -143
- package/docs/database/capacity.md +0 -350
- package/docs/database/counters.md +0 -174
- package/docs/database/documents.md +0 -277
- package/docs/database/events.md +0 -307
- package/docs/database/membership.md +0 -246
- package/docs/database/setup.md +0 -155
- package/docs/database/unique.md +0 -216
- package/docs/database/views.md +0 -246
- package/docs/frontend/README.md +0 -104
- package/docs/frontend/components.md +0 -286
- package/docs/frontend/data-fetching.md +0 -260
- package/docs/frontend/images.md +0 -148
- package/docs/frontend/metadata.md +0 -344
- package/docs/frontend/navigation.md +0 -296
- package/docs/frontend/rendering.md +0 -236
- package/docs/frontend/routing.md +0 -346
- package/docs/frontend/scripts.md +0 -118
- package/docs/frontend/search.md +0 -191
- package/docs/frontend/styling.md +0 -147
- package/docs/frontend/toil-global.md +0 -216
- package/docs/getting-started/README.md +0 -81
- package/docs/getting-started/create-project.md +0 -131
- package/docs/getting-started/deploy.md +0 -101
- package/docs/getting-started/first-app.md +0 -215
- package/docs/getting-started/installation.md +0 -124
- package/docs/getting-started/migrating.md +0 -125
- package/docs/getting-started/project-structure.md +0 -163
- package/docs/introduction/README.md +0 -66
- package/docs/introduction/design-principles.md +0 -81
- package/docs/introduction/distributed.md +0 -91
- package/docs/introduction/how-it-works.md +0 -121
- package/docs/introduction/hyperscale.md +0 -70
- package/docs/introduction/modern-stack.md +0 -85
- package/docs/introduction/vs-other-frameworks.md +0 -64
- package/docs/introduction/why-toil.md +0 -99
- package/docs/llms.txt +0 -95
- package/docs/realtime/README.md +0 -102
- package/docs/realtime/channels.md +0 -211
- package/docs/realtime/streams.md +0 -369
- package/docs/services/README.md +0 -60
- package/docs/services/analytics.md +0 -279
- package/docs/services/caching.md +0 -175
- package/docs/services/cookies.md +0 -235
- package/docs/services/crypto.md +0 -209
- package/docs/services/email.md +0 -289
- package/docs/services/environment.md +0 -141
- package/docs/services/ratelimit.md +0 -174
- package/docs/services/time.md +0 -85
- package/eslint.config.js +0 -57
- package/examples/basic/client/routes/docs/[...slug].tsx +0 -12
- package/presets/eslint.js +0 -88
- package/src/backend/index.ts +0 -204
- package/src/cli/configure.ts +0 -363
- package/src/cli/create.ts +0 -924
- package/src/cli/db.ts +0 -158
- package/src/cli/diagnostics.ts +0 -665
- package/src/cli/doctor.ts +0 -982
- package/src/cli/features.ts +0 -170
- package/src/cli/index.ts +0 -326
- package/src/cli/notify.ts +0 -120
- package/src/cli/proc.ts +0 -56
- package/src/cli/ui.ts +0 -169
- package/src/cli/update.ts +0 -248
- package/src/cli/updates.ts +0 -92
- package/src/cli/validate.ts +0 -31
- package/src/cli/version-check.ts +0 -125
- package/src/client/auth.ts +0 -869
- package/src/client/channel/channel.ts +0 -146
- package/src/client/components/Form.tsx +0 -65
- package/src/client/components/Image.tsx +0 -160
- package/src/client/components/Script.tsx +0 -113
- package/src/client/components/Slot.tsx +0 -21
- package/src/client/dev/devtools.tsx +0 -1089
- package/src/client/dev/error-overlay.tsx +0 -225
- package/src/client/errors.ts +0 -11
- package/src/client/head/head.ts +0 -182
- package/src/client/head/metadata.ts +0 -110
- package/src/client/index.ts +0 -130
- package/src/client/navigation/Link.tsx +0 -108
- package/src/client/navigation/NavLink.tsx +0 -86
- package/src/client/navigation/navigation.ts +0 -235
- package/src/client/navigation/prefetch.ts +0 -169
- package/src/client/navigation/scroll.ts +0 -53
- package/src/client/routing/Router.tsx +0 -216
- package/src/client/routing/action.ts +0 -122
- package/src/client/routing/error-boundary.tsx +0 -43
- package/src/client/routing/hooks.ts +0 -140
- package/src/client/routing/lazy.ts +0 -77
- package/src/client/routing/loader.ts +0 -381
- package/src/client/routing/match.ts +0 -47
- package/src/client/routing/mount.tsx +0 -90
- package/src/client/routing/params-context.ts +0 -10
- package/src/client/routing/slot-context.ts +0 -7
- package/src/client/rpc.ts +0 -97
- package/src/client/search/search.ts +0 -189
- package/src/client/search/use-page-search.ts +0 -73
- package/src/client/ssr/markers.tsx +0 -172
- package/src/client/stream/client.ts +0 -237
- package/src/client/types.ts +0 -73
- package/src/compiler/auth-emails.ts +0 -312
- package/src/compiler/config.ts +0 -369
- package/src/compiler/docs.ts +0 -127
- package/src/compiler/email-preview.ts +0 -314
- package/src/compiler/emails.ts +0 -404
- package/src/compiler/fonts.ts +0 -89
- package/src/compiler/generate.ts +0 -471
- package/src/compiler/image-blur.ts +0 -42
- package/src/compiler/image-report.ts +0 -88
- package/src/compiler/index.ts +0 -1362
- package/src/compiler/pages.ts +0 -49
- package/src/compiler/plugin.ts +0 -391
- package/src/compiler/prerender.ts +0 -263
- package/src/compiler/routes.ts +0 -170
- package/src/compiler/seo.ts +0 -415
- package/src/compiler/sri.ts +0 -144
- package/src/compiler/ssg.ts +0 -177
- package/src/compiler/ssr-codegen.ts +0 -85
- package/src/compiler/template-build.ts +0 -676
- package/src/compiler/template.ts +0 -262
- package/src/compiler/toil-docs.generated.ts +0 -77
- package/src/compiler/vite.ts +0 -245
- package/src/devserver/analytics/index.ts +0 -317
- package/src/devserver/config/dotenv.ts +0 -102
- package/src/devserver/config/env.ts +0 -30
- package/src/devserver/config/ratelimit.ts +0 -123
- package/src/devserver/daemon/catalog.ts +0 -120
- package/src/devserver/daemon/cron.ts +0 -87
- package/src/devserver/daemon/host.ts +0 -134
- package/src/devserver/daemon/index.ts +0 -369
- package/src/devserver/daemon/runtime.ts +0 -48
- package/src/devserver/db/catalog.ts +0 -109
- package/src/devserver/db/database.ts +0 -1834
- package/src/devserver/db/derives.ts +0 -121
- package/src/devserver/db/index.ts +0 -20
- package/src/devserver/db/routeKinds.ts +0 -191
- package/src/devserver/db/types.ts +0 -168
- package/src/devserver/email/caps.ts +0 -0
- package/src/devserver/email/config.ts +0 -141
- package/src/devserver/email/console.ts +0 -348
- package/src/devserver/email/index.ts +0 -155
- package/src/devserver/email/providers.ts +0 -131
- package/src/devserver/email/status.ts +0 -23
- package/src/devserver/email/validate.ts +0 -37
- package/src/devserver/email/wire.ts +0 -55
- package/src/devserver/http/cache.ts +0 -0
- package/src/devserver/http/envelope.ts +0 -157
- package/src/devserver/http/proxy.ts +0 -172
- package/src/devserver/http/runtime.ts +0 -387
- package/src/devserver/index.ts +0 -43
- package/src/devserver/production-ipc.ts +0 -63
- package/src/devserver/production-worker.ts +0 -83
- package/src/devserver/production.ts +0 -718
- package/src/devserver/runtime/crypto.ts +0 -587
- package/src/devserver/runtime/host.ts +0 -427
- package/src/devserver/runtime/module.ts +0 -442
- package/src/devserver/server.ts +0 -251
- package/src/devserver/ssr.ts +0 -208
- package/src/devserver/stream/catalog.ts +0 -106
- package/src/devserver/stream/host.ts +0 -42
- package/src/devserver/stream/index.ts +0 -301
- package/src/devserver/stream/manager.ts +0 -167
- package/src/devserver/stream/router.ts +0 -101
- package/src/devserver/stream/wire.ts +0 -58
- package/src/devserver/stream/ws.ts +0 -78
- package/src/devserver/wasm/sections.ts +0 -59
- package/src/devserver/wasm/surface.ts +0 -115
- package/src/io/FastMap.ts +0 -151
- package/src/io/FastSet.ts +0 -113
- package/src/io/codec.ts +0 -362
- package/src/io/index.ts +0 -10
- package/src/io/lengths.ts +0 -14
- package/src/io/types.ts +0 -19
- package/src/logger/index.ts +0 -22
- package/src/shared/index.ts +0 -46
- package/test/analytics-dev.test.ts +0 -113
- package/test/assembly/aspect-shim.ts +0 -33
- package/test/assembly/cookie.spec.ts +0 -303
- package/test/assembly/example.spec.ts +0 -22
- package/test/assembly/ssr.spec.ts +0 -95
- package/test/assembly.test.ts +0 -59
- package/test/auth-emails.test.ts +0 -118
- package/test/built-ssr.test.ts +0 -148
- package/test/channel.test.ts +0 -21
- package/test/config-host-port.test.ts +0 -59
- package/test/configure.test.ts +0 -94
- package/test/daemon-build.test.ts +0 -278
- package/test/daemon-catalog.test.ts +0 -349
- package/test/daemon-emulation.test.ts +0 -256
- package/test/db.test.ts +0 -0
- package/test/devserver-database.test.ts +0 -1102
- package/test/devserver-email.test.ts +0 -306
- package/test/devserver-pqauth.test.ts +0 -93
- package/test/devserver-secrets.test.ts +0 -63
- package/test/devserver.test.ts +0 -259
- package/test/doctor.test.ts +0 -298
- package/test/dom/Image.test.tsx +0 -144
- package/test/dom/Link.test.tsx +0 -67
- package/test/dom/NavLink.test.tsx +0 -37
- package/test/dom/Script.test.tsx +0 -48
- package/test/dom/action.test.tsx +0 -146
- package/test/dom/error-overlay.test.tsx +0 -44
- package/test/dom/loader.test.tsx +0 -121
- package/test/dom/navigation.test.ts +0 -59
- package/test/dom/revalidate.test.tsx +0 -38
- package/test/dom/route-head.test.tsx +0 -56
- package/test/dom/router-loading.test.tsx +0 -44
- package/test/dom/scroll.test.ts +0 -56
- package/test/dom/slot.test.tsx +0 -131
- package/test/dom/use-metadata.test.tsx +0 -58
- package/test/dom/view-transitions.test.tsx +0 -53
- package/test/dynamic-routing.test.ts +0 -132
- package/test/email-console.test.ts +0 -86
- package/test/email-preview.test.ts +0 -73
- package/test/emails.test.ts +0 -58
- package/test/errors.test.ts +0 -21
- package/test/example-guestbook.test.ts +0 -123
- package/test/features.test.ts +0 -149
- package/test/fixtures/bignum-wire/spec.ts +0 -25
- package/test/fixtures/daemon-app.ts +0 -65
- package/test/fixtures/stream-echo.ts +0 -26
- package/test/fixtures/stream-gate.ts +0 -28
- package/test/fixtures/stream-trap.ts +0 -18
- package/test/fixtures/stream-typed.ts +0 -41
- package/test/fonts.test.ts +0 -28
- package/test/global-setup.ts +0 -17
- package/test/head.test.ts +0 -42
- package/test/image-blur.test.ts +0 -50
- package/test/io.test.ts +0 -117
- package/test/metadata.test.ts +0 -40
- package/test/navlink.test.ts +0 -28
- package/test/pages.test.ts +0 -105
- package/test/placeholder.test.ts +0 -9
- package/test/pqauth-e2e.test.ts +0 -216
- package/test/pqauth-email.test.ts +0 -801
- package/test/prerender.test.ts +0 -116
- package/test/prettier-plugin.test.ts +0 -46
- package/test/routes.test.ts +0 -76
- package/test/rpc-bignum-wire.test.ts +0 -164
- package/test/rpc-dispatch.test.ts +0 -132
- package/test/rpc-kinds.test.ts +0 -18
- package/test/rpc.test.ts +0 -66
- package/test/search.test.ts +0 -114
- package/test/seo.test.ts +0 -175
- package/test/slot-layouts.test.ts +0 -69
- package/test/sri.test.ts +0 -129
- package/test/ssg.test.ts +0 -36
- package/test/ssr-hydration.test.tsx +0 -122
- package/test/ssr-render.test.ts +0 -197
- package/test/ssr-template.test.tsx +0 -482
- package/test/stream-emulation.test.ts +0 -479
- package/test/ui.test.ts +0 -40
- package/test/update.test.ts +0 -58
- package/test/validate.test.ts +0 -42
- package/test/version-check.test.ts +0 -130
- package/tests/data-parity/generated-parity.ts +0 -99
- package/tests/data-parity/parity.ts +0 -80
- package/tests/data-parity/spec.ts +0 -46
|
@@ -1,587 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dev-server mock of the `env.crypto.*` host functions, mirroring the
|
|
3
|
-
* production edge (`toil-backend/src/wasm/host/import_functions/crypto`) and the
|
|
4
|
-
* toilscript std ABI (`std/assembly/crypto/algorithms.ts`). Backed by Node's
|
|
5
|
-
* `crypto`. The dev server intentionally skips the edge's metering, so these
|
|
6
|
-
* charge nothing; results must still be byte-identical to the edge for the
|
|
7
|
-
* common algorithms.
|
|
8
|
-
*
|
|
9
|
-
* Variable-length results use the same two-step pull as the edge: the op
|
|
10
|
-
* returns the length and stashes the bytes; the guest then calls `take_result`.
|
|
11
|
-
*
|
|
12
|
-
* Dev-only limitations: raw-format import of asymmetric keys (EC/Ed25519/
|
|
13
|
-
* X25519) returns the "unsupported" code (-3) here because Node can't import a
|
|
14
|
-
* bare key without DER; use pkcs8/spki in the dev server. The production edge
|
|
15
|
-
* supports raw too. These are catchable guest-side errors, never crashes.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import * as nodeCrypto from 'node:crypto';
|
|
19
|
-
|
|
20
|
-
import { ml_dsa44 } from '@dacely/noble-post-quantum/ml-dsa.js';
|
|
21
|
-
import { ml_kem768 } from '@dacely/noble-post-quantum/ml-kem.js';
|
|
22
|
-
import { ristretto255_oprf } from '@noble/curves/ed25519.js';
|
|
23
|
-
|
|
24
|
-
import type { MemoryRef } from './host.js';
|
|
25
|
-
|
|
26
|
-
// --- ABI id tables (must match the std + Rust backend) ----------------------
|
|
27
|
-
const ALG = {
|
|
28
|
-
SHA1: 1,
|
|
29
|
-
SHA256: 2,
|
|
30
|
-
SHA384: 3,
|
|
31
|
-
SHA512: 4,
|
|
32
|
-
SHA3_256: 5,
|
|
33
|
-
SHA3_384: 6,
|
|
34
|
-
SHA3_512: 7,
|
|
35
|
-
AES_GCM: 10,
|
|
36
|
-
AES_CBC: 11,
|
|
37
|
-
AES_CTR: 12,
|
|
38
|
-
AES_KW: 13,
|
|
39
|
-
HMAC: 20,
|
|
40
|
-
ECDSA: 32,
|
|
41
|
-
ED25519: 33,
|
|
42
|
-
ECDH: 50,
|
|
43
|
-
X25519: 51,
|
|
44
|
-
HKDF: 52,
|
|
45
|
-
PBKDF2: 53,
|
|
46
|
-
} as const;
|
|
47
|
-
const FMT = { RAW: 0, PKCS8: 1, SPKI: 2, JWK: 3 } as const;
|
|
48
|
-
|
|
49
|
-
// Recoverable error codes (negative returns).
|
|
50
|
-
const ERR_GENERIC = -1;
|
|
51
|
-
const ERR_UNSUPPORTED = -3;
|
|
52
|
-
const ERR_INVALID_PARAMS = -4;
|
|
53
|
-
const ERR_OPERATION_FAILED = -5;
|
|
54
|
-
const ERR_NOT_EXTRACTABLE = -7;
|
|
55
|
-
|
|
56
|
-
const MAX_OUTPUT = 1024 * 1024;
|
|
57
|
-
|
|
58
|
-
interface KeyEntry {
|
|
59
|
-
/** Raw bytes for symmetric/MAC/KDF keys. */
|
|
60
|
-
raw: Buffer | null;
|
|
61
|
-
/** Node KeyObject for asymmetric keys. */
|
|
62
|
-
keyObject: nodeCrypto.KeyObject | null;
|
|
63
|
-
alg: number;
|
|
64
|
-
hash: number;
|
|
65
|
-
extractable: boolean;
|
|
66
|
-
isPrivate: boolean;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface CryptoState {
|
|
70
|
-
keys: Map<number, KeyEntry>;
|
|
71
|
-
nextHandle: number;
|
|
72
|
-
lastResult: Buffer | null;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function freshCryptoState(): CryptoState {
|
|
76
|
-
return { keys: new Map(), nextHandle: 1, lastResult: null };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function memBuf(ref: MemoryRef): Buffer {
|
|
80
|
-
if (!ref.memory) throw new Error('crypto host import called before memory was bound');
|
|
81
|
-
return Buffer.from(ref.memory.buffer);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function readBytes(ref: MemoryRef, ptr: number, len: number): Buffer {
|
|
85
|
-
const m = memBuf(ref);
|
|
86
|
-
if (ptr < 0 || len < 0 || ptr + len > m.length)
|
|
87
|
-
throw new Error(`crypto read out of bounds: ptr=${String(ptr)} len=${String(len)}`);
|
|
88
|
-
// Copy out so later writes/grows can't alias the input.
|
|
89
|
-
return Buffer.from(m.subarray(ptr, ptr + len));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function writeBytes(ref: MemoryRef, ptr: number, bytes: Buffer | Uint8Array): void {
|
|
93
|
-
const m = memBuf(ref);
|
|
94
|
-
if (ptr < 0 || ptr + bytes.length > m.length)
|
|
95
|
-
throw new Error(
|
|
96
|
-
`crypto write out of bounds: ptr=${String(ptr)} len=${String(bytes.length)}`,
|
|
97
|
-
);
|
|
98
|
-
m.set(bytes, ptr);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/** Little-endian reader over a packed params buffer (mirrors the Rust ParamReader). */
|
|
102
|
-
class ParamReader {
|
|
103
|
-
private pos = 0;
|
|
104
|
-
constructor(private readonly buf: Buffer) {}
|
|
105
|
-
|
|
106
|
-
readI32(): number {
|
|
107
|
-
this.need(4);
|
|
108
|
-
const v = this.buf.readInt32LE(this.pos);
|
|
109
|
-
this.pos += 4;
|
|
110
|
-
return v;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
readU32(): number {
|
|
114
|
-
this.need(4);
|
|
115
|
-
const v = this.buf.readUInt32LE(this.pos);
|
|
116
|
-
this.pos += 4;
|
|
117
|
-
return v;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
readBlob(): Buffer {
|
|
121
|
-
const n = this.readU32();
|
|
122
|
-
this.need(n);
|
|
123
|
-
const s = Buffer.from(this.buf.subarray(this.pos, this.pos + n));
|
|
124
|
-
this.pos += n;
|
|
125
|
-
return s;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** Bounds-check before a read so a malformed buffer throws a controlled
|
|
129
|
-
* error (trap-equivalent, caught by the dispatcher) rather than a raw
|
|
130
|
-
* Node RangeError. */
|
|
131
|
-
private need(n: number): void {
|
|
132
|
-
if (n < 0 || this.pos + n > this.buf.length)
|
|
133
|
-
throw new Error('crypto: malformed params buffer (truncated)');
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function hashName(id: number): string {
|
|
138
|
-
switch (id) {
|
|
139
|
-
case ALG.SHA1:
|
|
140
|
-
return 'sha1';
|
|
141
|
-
case ALG.SHA256:
|
|
142
|
-
return 'sha256';
|
|
143
|
-
case ALG.SHA384:
|
|
144
|
-
return 'sha384';
|
|
145
|
-
case ALG.SHA512:
|
|
146
|
-
return 'sha512';
|
|
147
|
-
case ALG.SHA3_256:
|
|
148
|
-
return 'sha3-256';
|
|
149
|
-
case ALG.SHA3_384:
|
|
150
|
-
return 'sha3-384';
|
|
151
|
-
case ALG.SHA3_512:
|
|
152
|
-
return 'sha3-512';
|
|
153
|
-
default:
|
|
154
|
-
throw new Error(`crypto: bad hash id ${String(id)}`);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function stash(state: CryptoState, bytes: Buffer): number {
|
|
159
|
-
state.lastResult = bytes;
|
|
160
|
-
return bytes.length;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Build the `env.crypto.*` import functions. `state.crypto` holds the per-
|
|
165
|
-
* dispatch keystore + result scratch.
|
|
166
|
-
*/
|
|
167
|
-
export function buildCryptoImports(
|
|
168
|
-
ref: MemoryRef,
|
|
169
|
-
cs: CryptoState,
|
|
170
|
-
): Record<string, (...args: number[]) => number | void> {
|
|
171
|
-
return {
|
|
172
|
-
'crypto.fill_random': (outPtr: number, len: number): void => {
|
|
173
|
-
if (len < 0 || len > MAX_OUTPUT) throw new Error('crypto.fill_random: bad length');
|
|
174
|
-
writeBytes(ref, outPtr, nodeCrypto.randomBytes(len));
|
|
175
|
-
},
|
|
176
|
-
|
|
177
|
-
'crypto.random_uuid': (outPtr: number): void => {
|
|
178
|
-
writeBytes(ref, outPtr, nodeCrypto.randomBytes(16));
|
|
179
|
-
},
|
|
180
|
-
|
|
181
|
-
'crypto.take_result': (outPtr: number, outLen: number): number => {
|
|
182
|
-
const r = cs.lastResult;
|
|
183
|
-
if (!r || r.length !== outLen) throw new Error('crypto.take_result: length mismatch');
|
|
184
|
-
writeBytes(ref, outPtr, r);
|
|
185
|
-
cs.lastResult = null;
|
|
186
|
-
return r.length;
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
'crypto.digest': (alg: number, dataPtr: number, dataLen: number): number => {
|
|
190
|
-
const data = readBytes(ref, dataPtr, dataLen);
|
|
191
|
-
try {
|
|
192
|
-
return stash(cs, nodeCrypto.createHash(hashName(alg)).update(data).digest());
|
|
193
|
-
} catch {
|
|
194
|
-
return ERR_UNSUPPORTED;
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
'crypto.import_key': (
|
|
199
|
-
format: number,
|
|
200
|
-
keyPtr: number,
|
|
201
|
-
keyLen: number,
|
|
202
|
-
paramsPtr: number,
|
|
203
|
-
paramsLen: number,
|
|
204
|
-
extractable: number,
|
|
205
|
-
_usages: number,
|
|
206
|
-
): number => {
|
|
207
|
-
const key = readBytes(ref, keyPtr, keyLen);
|
|
208
|
-
const pr = new ParamReader(readBytes(ref, paramsPtr, paramsLen));
|
|
209
|
-
const alg = pr.readI32();
|
|
210
|
-
const hash = pr.readI32();
|
|
211
|
-
return importKey(cs, format, alg, hash, pr, key, extractable !== 0);
|
|
212
|
-
},
|
|
213
|
-
|
|
214
|
-
'crypto.export_key': (format: number, handle: number): number => {
|
|
215
|
-
const e = cs.keys.get(handle);
|
|
216
|
-
if (!e) throw new Error('crypto.export_key: invalid handle');
|
|
217
|
-
if (!e.extractable) return ERR_NOT_EXTRACTABLE;
|
|
218
|
-
try {
|
|
219
|
-
if (e.raw && format === FMT.RAW) return stash(cs, e.raw);
|
|
220
|
-
if (e.keyObject) {
|
|
221
|
-
if (format === FMT.PKCS8 && e.isPrivate)
|
|
222
|
-
return stash(
|
|
223
|
-
cs,
|
|
224
|
-
e.keyObject.export({ format: 'der', type: 'pkcs8' }) as Buffer,
|
|
225
|
-
);
|
|
226
|
-
if (format === FMT.SPKI && !e.isPrivate)
|
|
227
|
-
return stash(
|
|
228
|
-
cs,
|
|
229
|
-
e.keyObject.export({ format: 'der', type: 'spki' }) as Buffer,
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
return ERR_UNSUPPORTED;
|
|
233
|
-
} catch {
|
|
234
|
-
return ERR_OPERATION_FAILED;
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
|
|
238
|
-
'crypto.encrypt': (h: number, pp: number, pl: number, dp: number, dl: number): number =>
|
|
239
|
-
aesOp(cs, ref, true, h, pp, pl, dp, dl),
|
|
240
|
-
'crypto.decrypt': (h: number, pp: number, pl: number, dp: number, dl: number): number =>
|
|
241
|
-
aesOp(cs, ref, false, h, pp, pl, dp, dl),
|
|
242
|
-
|
|
243
|
-
'crypto.sign': (h: number, pp: number, pl: number, dp: number, dl: number): number =>
|
|
244
|
-
signOp(cs, ref, h, pp, pl, dp, dl),
|
|
245
|
-
|
|
246
|
-
'crypto.verify': (
|
|
247
|
-
h: number,
|
|
248
|
-
pp: number,
|
|
249
|
-
pl: number,
|
|
250
|
-
sp: number,
|
|
251
|
-
sl: number,
|
|
252
|
-
dp: number,
|
|
253
|
-
dl: number,
|
|
254
|
-
): number => verifyOp(cs, ref, h, pp, pl, sp, sl, dp, dl),
|
|
255
|
-
|
|
256
|
-
'crypto.derive_bits': (h: number, pp: number, pl: number, lengthBits: number): number =>
|
|
257
|
-
deriveBitsOp(cs, ref, h, pp, pl, lengthBits),
|
|
258
|
-
|
|
259
|
-
// ML-DSA-44 (FIPS 204) verify for the auth primitive. Mirrors the edge
|
|
260
|
-
// host (`mldsa_verify_import.rs`): same size asserts, 1/0/neg result.
|
|
261
|
-
// Backed by the same noble lib the client signs with, so dev == prod.
|
|
262
|
-
'crypto.mldsa_verify': (
|
|
263
|
-
pkPtr: number,
|
|
264
|
-
pkLen: number,
|
|
265
|
-
msgPtr: number,
|
|
266
|
-
msgLen: number,
|
|
267
|
-
sigPtr: number,
|
|
268
|
-
sigLen: number,
|
|
269
|
-
ctxPtr: number,
|
|
270
|
-
ctxLen: number,
|
|
271
|
-
): number => {
|
|
272
|
-
if (pkLen !== 1312 || sigLen !== 2420 || ctxLen > 255) return -4;
|
|
273
|
-
try {
|
|
274
|
-
const pk = new Uint8Array(readBytes(ref, pkPtr, pkLen));
|
|
275
|
-
const msg = new Uint8Array(readBytes(ref, msgPtr, msgLen));
|
|
276
|
-
const sig = new Uint8Array(readBytes(ref, sigPtr, sigLen));
|
|
277
|
-
const ctx = new Uint8Array(readBytes(ref, ctxPtr, ctxLen));
|
|
278
|
-
return ml_dsa44.verify(sig, msg, pk, { context: ctx }) ? 1 : 0;
|
|
279
|
-
} catch {
|
|
280
|
-
return -1;
|
|
281
|
-
}
|
|
282
|
-
},
|
|
283
|
-
|
|
284
|
-
// ML-KEM-768 (FIPS 203) decapsulation for the mutual-auth + session-key
|
|
285
|
-
// layer. Mirrors the edge host (`mlkem_decapsulate_import.rs` / fips203):
|
|
286
|
-
// recover the 32-byte shared secret from the client's ciphertext using
|
|
287
|
-
// the server's static secret key, write it to `outPtr`, return 0 / neg.
|
|
288
|
-
// Backed by the same noble lib the client encapsulates with (dev == prod).
|
|
289
|
-
'crypto.mlkem_decapsulate': (
|
|
290
|
-
ctPtr: number,
|
|
291
|
-
ctLen: number,
|
|
292
|
-
skPtr: number,
|
|
293
|
-
skLen: number,
|
|
294
|
-
outPtr: number,
|
|
295
|
-
): number => {
|
|
296
|
-
if (ctLen !== 1088 || skLen !== 2400) return -4;
|
|
297
|
-
try {
|
|
298
|
-
const ct = new Uint8Array(readBytes(ref, ctPtr, ctLen));
|
|
299
|
-
const sk = new Uint8Array(readBytes(ref, skPtr, skLen));
|
|
300
|
-
const ss = ml_kem768.decapsulate(ct, sk); // 32 bytes; implicit rejection on bad ct
|
|
301
|
-
writeBytes(ref, outPtr, Buffer.from(ss));
|
|
302
|
-
return 0;
|
|
303
|
-
} catch {
|
|
304
|
-
return -5;
|
|
305
|
-
}
|
|
306
|
-
},
|
|
307
|
-
|
|
308
|
-
// RFC 9497 OPRF (mode 0x00, ristretto255-SHA512) server evaluation for
|
|
309
|
-
// the keyed-salt OPRF. Mirrors the edge host
|
|
310
|
-
// (`voprf_evaluate_import.rs` / the `voprf` crate): derive the per-user
|
|
311
|
-
// key from (seed, info=username) and blind-evaluate the client's blinded
|
|
312
|
-
// element, writing the 32-byte evaluated element to `outPtr`. Backed by
|
|
313
|
-
// `@noble/curves` ristretto255_oprf, which matches the edge byte-for-byte
|
|
314
|
-
// (both RFC 9497), so dev == prod.
|
|
315
|
-
'crypto.voprf_evaluate': (
|
|
316
|
-
seedPtr: number,
|
|
317
|
-
seedLen: number,
|
|
318
|
-
infoPtr: number,
|
|
319
|
-
infoLen: number,
|
|
320
|
-
blindedPtr: number,
|
|
321
|
-
blindedLen: number,
|
|
322
|
-
outPtr: number,
|
|
323
|
-
): number => {
|
|
324
|
-
// seedLen MUST be exactly 32 (RFC 9497 Ns; noble deriveKeyPair rejects
|
|
325
|
-
// other lengths) -- matching the edge so dev and prod never diverge.
|
|
326
|
-
if (blindedLen !== 32 || seedLen !== 32 || infoLen > 512) return -4;
|
|
327
|
-
try {
|
|
328
|
-
const seed = new Uint8Array(readBytes(ref, seedPtr, seedLen));
|
|
329
|
-
const info = new Uint8Array(readBytes(ref, infoPtr, infoLen));
|
|
330
|
-
const blinded = new Uint8Array(readBytes(ref, blindedPtr, blindedLen));
|
|
331
|
-
const oprf = ristretto255_oprf.oprf;
|
|
332
|
-
const kp = oprf.deriveKeyPair(seed, info);
|
|
333
|
-
const evaluated = oprf.blindEvaluate(kp.secretKey, blinded); // 32-byte element
|
|
334
|
-
writeBytes(ref, outPtr, Buffer.from(evaluated));
|
|
335
|
-
return 0;
|
|
336
|
-
} catch {
|
|
337
|
-
return -5;
|
|
338
|
-
}
|
|
339
|
-
},
|
|
340
|
-
};
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
function importKey(
|
|
344
|
-
cs: CryptoState,
|
|
345
|
-
format: number,
|
|
346
|
-
alg: number,
|
|
347
|
-
hash: number,
|
|
348
|
-
pr: ParamReader,
|
|
349
|
-
key: Buffer,
|
|
350
|
-
extractable: boolean,
|
|
351
|
-
): number {
|
|
352
|
-
const newEntry = (e: Omit<KeyEntry, 'extractable'>): number => {
|
|
353
|
-
const handle = cs.nextHandle++;
|
|
354
|
-
cs.keys.set(handle, { ...e, extractable });
|
|
355
|
-
return handle;
|
|
356
|
-
};
|
|
357
|
-
|
|
358
|
-
try {
|
|
359
|
-
// Symmetric / MAC / KDF: raw bytes.
|
|
360
|
-
if (
|
|
361
|
-
alg === ALG.AES_GCM ||
|
|
362
|
-
alg === ALG.AES_CBC ||
|
|
363
|
-
alg === ALG.AES_CTR ||
|
|
364
|
-
alg === ALG.AES_KW ||
|
|
365
|
-
alg === ALG.HMAC ||
|
|
366
|
-
alg === ALG.PBKDF2 ||
|
|
367
|
-
alg === ALG.HKDF
|
|
368
|
-
) {
|
|
369
|
-
if (format !== FMT.RAW) return ERR_UNSUPPORTED;
|
|
370
|
-
return newEntry({ raw: key, keyObject: null, alg, hash, isPrivate: false });
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Asymmetric: pkcs8 (private) / spki (public). raw not supported in dev.
|
|
374
|
-
const isPrivate = format === FMT.PKCS8;
|
|
375
|
-
if (format === FMT.PKCS8) {
|
|
376
|
-
const ko = nodeCrypto.createPrivateKey({ key, format: 'der', type: 'pkcs8' });
|
|
377
|
-
return newEntry({ raw: null, keyObject: ko, alg, hash, isPrivate });
|
|
378
|
-
}
|
|
379
|
-
if (format === FMT.SPKI) {
|
|
380
|
-
const ko = nodeCrypto.createPublicKey({ key, format: 'der', type: 'spki' });
|
|
381
|
-
return newEntry({ raw: null, keyObject: ko, alg, hash, isPrivate });
|
|
382
|
-
}
|
|
383
|
-
return ERR_UNSUPPORTED;
|
|
384
|
-
} catch {
|
|
385
|
-
return ERR_INVALID_PARAMS;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
function aesAlgName(keyLen: number, mode: 'gcm' | 'cbc' | 'ctr'): string {
|
|
390
|
-
const bits = keyLen === 16 ? 128 : keyLen === 32 ? 256 : 0;
|
|
391
|
-
if (!bits) throw new Error('crypto: bad AES key length');
|
|
392
|
-
return `aes-${String(bits)}-${mode}`;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
function aesOp(
|
|
396
|
-
cs: CryptoState,
|
|
397
|
-
ref: MemoryRef,
|
|
398
|
-
encrypt: boolean,
|
|
399
|
-
handle: number,
|
|
400
|
-
pp: number,
|
|
401
|
-
pl: number,
|
|
402
|
-
dp: number,
|
|
403
|
-
dl: number,
|
|
404
|
-
): number {
|
|
405
|
-
const e = cs.keys.get(handle);
|
|
406
|
-
if (!e || !e.raw) throw new Error('crypto: invalid AES key handle');
|
|
407
|
-
const pr = new ParamReader(readBytes(ref, pp, pl));
|
|
408
|
-
const alg = pr.readI32();
|
|
409
|
-
pr.readI32(); // hash (unused)
|
|
410
|
-
const data = readBytes(ref, dp, dl);
|
|
411
|
-
try {
|
|
412
|
-
if (alg === ALG.AES_GCM) {
|
|
413
|
-
const iv = pr.readBlob();
|
|
414
|
-
const tagBits = pr.readI32();
|
|
415
|
-
const aad = pr.readBlob();
|
|
416
|
-
if (tagBits !== 0 && tagBits !== 128) return ERR_INVALID_PARAMS;
|
|
417
|
-
if (encrypt) {
|
|
418
|
-
const c = nodeCrypto.createCipheriv(
|
|
419
|
-
aesAlgName(e.raw.length, 'gcm'),
|
|
420
|
-
e.raw,
|
|
421
|
-
iv,
|
|
422
|
-
) as nodeCrypto.CipherGCM;
|
|
423
|
-
if (aad.length) c.setAAD(aad);
|
|
424
|
-
const ct = Buffer.concat([c.update(data), c.final()]);
|
|
425
|
-
return stash(cs, Buffer.concat([ct, c.getAuthTag()]));
|
|
426
|
-
}
|
|
427
|
-
// Ciphertext must be at least the 16-byte tag; shorter input can
|
|
428
|
-
// never authenticate.
|
|
429
|
-
if (data.length < 16) return ERR_OPERATION_FAILED;
|
|
430
|
-
const d = nodeCrypto.createDecipheriv(
|
|
431
|
-
aesAlgName(e.raw.length, 'gcm'),
|
|
432
|
-
e.raw,
|
|
433
|
-
iv,
|
|
434
|
-
) as nodeCrypto.DecipherGCM;
|
|
435
|
-
if (aad.length) d.setAAD(aad);
|
|
436
|
-
const tag = data.subarray(data.length - 16);
|
|
437
|
-
const ct = data.subarray(0, data.length - 16);
|
|
438
|
-
d.setAuthTag(tag);
|
|
439
|
-
return stash(cs, Buffer.concat([d.update(ct), d.final()]));
|
|
440
|
-
}
|
|
441
|
-
if (alg === ALG.AES_CBC) {
|
|
442
|
-
const iv = pr.readBlob();
|
|
443
|
-
const c = encrypt
|
|
444
|
-
? nodeCrypto.createCipheriv(aesAlgName(e.raw.length, 'cbc'), e.raw, iv)
|
|
445
|
-
: nodeCrypto.createDecipheriv(aesAlgName(e.raw.length, 'cbc'), e.raw, iv);
|
|
446
|
-
return stash(cs, Buffer.concat([c.update(data), c.final()]));
|
|
447
|
-
}
|
|
448
|
-
if (alg === ALG.AES_CTR) {
|
|
449
|
-
const counter = pr.readBlob();
|
|
450
|
-
const c = encrypt
|
|
451
|
-
? nodeCrypto.createCipheriv(aesAlgName(e.raw.length, 'ctr'), e.raw, counter)
|
|
452
|
-
: nodeCrypto.createDecipheriv(aesAlgName(e.raw.length, 'ctr'), e.raw, counter);
|
|
453
|
-
return stash(cs, Buffer.concat([c.update(data), c.final()]));
|
|
454
|
-
}
|
|
455
|
-
return ERR_UNSUPPORTED;
|
|
456
|
-
} catch {
|
|
457
|
-
return ERR_OPERATION_FAILED;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
function signOp(
|
|
462
|
-
cs: CryptoState,
|
|
463
|
-
ref: MemoryRef,
|
|
464
|
-
handle: number,
|
|
465
|
-
pp: number,
|
|
466
|
-
pl: number,
|
|
467
|
-
dp: number,
|
|
468
|
-
dl: number,
|
|
469
|
-
): number {
|
|
470
|
-
const e = cs.keys.get(handle);
|
|
471
|
-
if (!e) throw new Error('crypto.sign: invalid handle');
|
|
472
|
-
const pr = new ParamReader(readBytes(ref, pp, pl));
|
|
473
|
-
const alg = pr.readI32();
|
|
474
|
-
const hash = pr.readI32();
|
|
475
|
-
const data = readBytes(ref, dp, dl);
|
|
476
|
-
try {
|
|
477
|
-
if (e.alg === ALG.HMAC && e.raw) {
|
|
478
|
-
return stash(cs, nodeCrypto.createHmac(hashName(e.hash), e.raw).update(data).digest());
|
|
479
|
-
}
|
|
480
|
-
if (e.alg === ALG.ECDSA && e.keyObject) {
|
|
481
|
-
const sig = nodeCrypto.sign(hashName(hash), data, {
|
|
482
|
-
key: e.keyObject,
|
|
483
|
-
dsaEncoding: 'ieee-p1363',
|
|
484
|
-
});
|
|
485
|
-
return stash(cs, sig);
|
|
486
|
-
}
|
|
487
|
-
if (e.alg === ALG.ED25519 && e.keyObject) {
|
|
488
|
-
return stash(cs, nodeCrypto.sign(null, data, e.keyObject));
|
|
489
|
-
}
|
|
490
|
-
void alg;
|
|
491
|
-
return ERR_UNSUPPORTED;
|
|
492
|
-
} catch {
|
|
493
|
-
return ERR_OPERATION_FAILED;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
function verifyOp(
|
|
498
|
-
cs: CryptoState,
|
|
499
|
-
ref: MemoryRef,
|
|
500
|
-
handle: number,
|
|
501
|
-
pp: number,
|
|
502
|
-
pl: number,
|
|
503
|
-
sp: number,
|
|
504
|
-
sl: number,
|
|
505
|
-
dp: number,
|
|
506
|
-
dl: number,
|
|
507
|
-
): number {
|
|
508
|
-
const e = cs.keys.get(handle);
|
|
509
|
-
if (!e) throw new Error('crypto.verify: invalid handle');
|
|
510
|
-
const pr = new ParamReader(readBytes(ref, pp, pl));
|
|
511
|
-
pr.readI32(); // alg
|
|
512
|
-
const hash = pr.readI32();
|
|
513
|
-
const sig = readBytes(ref, sp, sl);
|
|
514
|
-
const data = readBytes(ref, dp, dl);
|
|
515
|
-
try {
|
|
516
|
-
if (e.alg === ALG.HMAC && e.raw) {
|
|
517
|
-
const mac = nodeCrypto.createHmac(hashName(e.hash), e.raw).update(data).digest();
|
|
518
|
-
return mac.length === sig.length && nodeCrypto.timingSafeEqual(mac, sig) ? 1 : 0;
|
|
519
|
-
}
|
|
520
|
-
if (e.alg === ALG.ECDSA && e.keyObject) {
|
|
521
|
-
const ok = nodeCrypto.verify(
|
|
522
|
-
hashName(hash),
|
|
523
|
-
data,
|
|
524
|
-
{
|
|
525
|
-
key: e.keyObject,
|
|
526
|
-
dsaEncoding: 'ieee-p1363',
|
|
527
|
-
},
|
|
528
|
-
sig,
|
|
529
|
-
);
|
|
530
|
-
return ok ? 1 : 0;
|
|
531
|
-
}
|
|
532
|
-
if (e.alg === ALG.ED25519 && e.keyObject) {
|
|
533
|
-
return nodeCrypto.verify(null, data, e.keyObject, sig) ? 1 : 0;
|
|
534
|
-
}
|
|
535
|
-
return ERR_UNSUPPORTED;
|
|
536
|
-
} catch {
|
|
537
|
-
return ERR_GENERIC;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
function deriveBitsOp(
|
|
542
|
-
cs: CryptoState,
|
|
543
|
-
ref: MemoryRef,
|
|
544
|
-
handle: number,
|
|
545
|
-
pp: number,
|
|
546
|
-
pl: number,
|
|
547
|
-
lengthBits: number,
|
|
548
|
-
): number {
|
|
549
|
-
if (lengthBits < 0 || lengthBits % 8 !== 0) return ERR_INVALID_PARAMS;
|
|
550
|
-
const outLen = lengthBits / 8;
|
|
551
|
-
if (outLen > MAX_OUTPUT) return ERR_INVALID_PARAMS;
|
|
552
|
-
const e = cs.keys.get(handle);
|
|
553
|
-
if (!e) throw new Error('crypto.derive_bits: invalid handle');
|
|
554
|
-
const pr = new ParamReader(readBytes(ref, pp, pl));
|
|
555
|
-
const alg = pr.readI32();
|
|
556
|
-
const hash = pr.readI32();
|
|
557
|
-
try {
|
|
558
|
-
if (alg === ALG.PBKDF2 && e.raw) {
|
|
559
|
-
const iterations = pr.readU32();
|
|
560
|
-
const salt = pr.readBlob();
|
|
561
|
-
return stash(
|
|
562
|
-
cs,
|
|
563
|
-
nodeCrypto.pbkdf2Sync(e.raw, salt, iterations, outLen, hashName(hash)),
|
|
564
|
-
);
|
|
565
|
-
}
|
|
566
|
-
if (alg === ALG.HKDF && e.raw) {
|
|
567
|
-
const salt = pr.readBlob();
|
|
568
|
-
const info = pr.readBlob();
|
|
569
|
-
const okm = nodeCrypto.hkdfSync(hashName(hash), e.raw, salt, info, outLen);
|
|
570
|
-
return stash(cs, Buffer.from(okm));
|
|
571
|
-
}
|
|
572
|
-
if ((alg === ALG.ECDH || alg === ALG.X25519) && e.keyObject) {
|
|
573
|
-
const peerHandle = pr.readI32();
|
|
574
|
-
const peer = cs.keys.get(peerHandle);
|
|
575
|
-
if (!peer || !peer.keyObject)
|
|
576
|
-
throw new Error('crypto.derive_bits: invalid peer handle');
|
|
577
|
-
const shared = nodeCrypto.diffieHellman({
|
|
578
|
-
privateKey: e.keyObject,
|
|
579
|
-
publicKey: peer.keyObject,
|
|
580
|
-
});
|
|
581
|
-
return stash(cs, Buffer.from(shared.subarray(0, Math.min(outLen, shared.length))));
|
|
582
|
-
}
|
|
583
|
-
return ERR_UNSUPPORTED;
|
|
584
|
-
} catch {
|
|
585
|
-
return ERR_OPERATION_FAILED;
|
|
586
|
-
}
|
|
587
|
-
}
|