@pawmaskrelease/psecure 1.1.0 → 1.1.1
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 +51 -0
- package/README.md +122 -19
- package/dist/adapters/desktop.js +1 -1
- package/dist/adapters/index.js +1 -1
- package/dist/adapters/mobile-bridge.js +1 -1
- package/dist/adapters/react-native.js +1 -1
- package/dist/adapters/web-shield.js +1 -1
- package/dist/adapters/web-vault.js +1 -1
- package/dist/cli/doctor.js +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/psecure-client.js +1 -1
- package/dist/crypto/block-ciphers.js +1 -1
- package/dist/crypto/chacha-cfb.js +1 -1
- package/dist/crypto/index.js +1 -1
- package/dist/crypto/mba.js +1 -1
- package/dist/crypto/primitives.js +1 -1
- package/dist/crypto/threefish.js +1 -1
- package/dist/crypto/wasm-coprocessor.js +1 -1
- package/dist/crypto/whitebox-aes.js +1 -1
- package/dist/dist-manifest.json +64 -64
- package/dist/errors.js +1 -1
- package/dist/fetch/index.js +12 -11
- package/dist/fetch/load-client.js +1 -1
- package/dist/index.js +1 -1
- package/dist/protocol/canonical.js +1 -1
- package/dist/protocol/codecs.js +1 -1
- package/dist/protocol/constants.js +1 -1
- package/dist/protocol/dvp-probes.js +1 -1
- package/dist/protocol/ed25519.js +1 -1
- package/dist/protocol/index.js +1 -1
- package/dist/protocol/types.js +1 -1
- package/dist/protocol/wire.js +1 -1
- package/dist/rasp/auto-collector.js +1 -1
- package/dist/rasp/behavior-stream.js +1 -1
- package/dist/rasp/dvp-consistency.js +1 -1
- package/dist/rasp/hardware-binding.js +1 -1
- package/dist/rasp/index.js +1 -1
- package/dist/rasp/klepto-seal.js +1 -1
- package/dist/rasp/mobile-native-probes.js +1 -1
- package/dist/rasp/probes.js +1 -1
- package/dist/rasp/web-integrity-probes.js +43 -44
- package/dist/server/authority-types.js +1 -1
- package/dist/server/edge.d.ts +3 -3
- package/dist/server/edge.js +2 -2
- package/dist/server/express.d.ts +4 -3
- package/dist/server/express.js +8 -8
- package/dist/server/fastify.d.ts +13 -4
- package/dist/server/fastify.js +11 -12
- package/dist/server/guard.d.ts +8 -5
- package/dist/server/guard.js +62 -56
- package/dist/server/index.js +1 -1
- package/dist/server/middleware.js +1 -1
- package/dist/server/remote-authority-client.js +1 -1
- package/dist/server/verdicts.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/dynamic-ob.js +1 -1
- package/dist/vm/env-key.js +1 -1
- package/dist/vm/iabc-isa.js +1 -1
- package/dist/vm/index.js +1 -1
- package/dist/vm/psecure-vm.js +1 -1
- package/dist/web/psecure-polymorphic-loader.obf.js +1 -1
- package/dist/web/psecure-vm-kernel.js +1 -1
- package/dist/web/psecure-web-shield.bundle.js +1 -1
- package/package.json +7 -1
- package/types/fastify-augment.d.ts +14 -0
- package/types/fastify-augment.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog: `@pawmaskrelease/psecure`
|
|
2
2
|
|
|
3
|
+
## 1.1.1
|
|
4
|
+
|
|
5
|
+
Fixes from a first production integration of 1.1.0. Backward compatible with 1.1.0.
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Every real browser was reported as tampered (critical, all web clients ≤ 1.1.0).** The `env_stub_dom_traps`
|
|
10
|
+
RASP probe treated a configurable `document.all[0]` descriptor as a polyfill, but WebIDL makes it configurable in
|
|
11
|
+
every genuine browser (verified on Edge/Chrome 157). Each sealed request carried a RASP bit, the authority counted a
|
|
12
|
+
strike, and the third request banned the account and device for 24 h. The check is removed. The authority (1.1.1)
|
|
13
|
+
also no longer counts strikes for apps in Monitor, so a false positive can never ban users there.
|
|
14
|
+
- **`clientIp` option (Fastify, Express)** to pass the end-user IP when `request.ip` is a proxy hop (e.g. Cloudflare
|
|
15
|
+
Tunnel → Traefik). Use a resolver that only trusts headers your edge sets.
|
|
16
|
+
- **Fastify typing.** `app.register(psecureFastify, { onDecision, blockedResponse })` left the callback parameters
|
|
17
|
+
implicitly `any` under `strict` (the plugin's optional options parameter made Fastify infer `Record<string, any>`).
|
|
18
|
+
`psecureFastify` is now typed `PSecureFastifyPlugin` with a required options parameter; Fastify always passes one,
|
|
19
|
+
and `app.register(psecureFastify)` without options still works.
|
|
20
|
+
- **`createPSecureFetch().ready()` / `status()`** reported `ready` after a background lease refresh failed
|
|
21
|
+
(`lease acquisition failed`), and `ready()` called right after a request resolved before the queued refresh began.
|
|
22
|
+
A failed acquisition now sets `failed` (the previous client keeps sealing until its lease expires), `ready()` waits
|
|
23
|
+
for a queued refresh, and the next successful lease returns to `ready` and clears `lastError()`.
|
|
24
|
+
- README: the backend verification section said the console Monitor/Block switch does not change verdicts. It now
|
|
25
|
+
describes 1.1: the adapters follow it in `auto`, verifier callers read `verdict.appMode`, pre-1.1 middlewares ignore
|
|
26
|
+
it.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- `@pawmaskrelease/psecure/fastify/augment` (types only): types `request.psecure` (`PSecureDecision | null`) and route
|
|
31
|
+
config `{ psecure?: boolean; psecureAppKey?: string }`. Also exported: `PSecureFastifyRequestDecoration`,
|
|
32
|
+
`PSecureFastifyRouteConfig`, `PSecureFastifyPlugin`. `request.psecure` is now decorated in every mode (`null` in
|
|
33
|
+
`off`).
|
|
34
|
+
- `createPSecureAuditThrottle` and its types (`PSecureGuardAuditEvent`, `PSecureAuditSink`,
|
|
35
|
+
`PSecureAuditThrottleOptions`, `PSecureAuditThrottle`) from `/fastify`, `/express` and `/edge`, not only `/server`.
|
|
36
|
+
`flush()` and `close()` now return a promise that settles once the sink finished (a failing sink never rejects);
|
|
37
|
+
`close()` flushes, is idempotent and ignores later decisions.
|
|
38
|
+
- `modeFallback` / `PSECURE_MODE_FALLBACK` (`monitor` | `enforce`, default `monitor`): the mode `auto` applies while
|
|
39
|
+
the console mode is unknown (restart during an authority outage, cached mode expired). A verdict carrying the
|
|
40
|
+
console mode always wins.
|
|
41
|
+
- Docs: app pinning and `appMode` trust, testing with a stubbed authority, `blockedResponse` status for reissued
|
|
42
|
+
leases, per-route opt-in (`protect: []` + route config), audit events, dynamic import of `/fetch`, web setup
|
|
43
|
+
(`setAccount`, `enabled`, lazy loading, CSP `connect-src`), the cold-start caveat of `auto`.
|
|
44
|
+
- `SERVER_KEY_IS_APP_KEY` (an app key `psec_app_…` in `PSECURE_SERVER_KEY`) now names both key kinds in its message.
|
|
45
|
+
|
|
46
|
+
### Same release, outside the npm package
|
|
47
|
+
|
|
48
|
+
- Console: new applications no longer get made-up figures (SDK version, p95 latency, device count); stored
|
|
49
|
+
placeholders are cleared on load and the Console shows "No data yet". "Apps in use" is counted from the
|
|
50
|
+
organization's applications (console, admin, app-limit check) instead of a stored counter that drifted.
|
|
51
|
+
- Docs: a "Go to production" checklist (secrets on hosting, real client IP behind proxies, browser checks, Monitor to
|
|
52
|
+
Block), troubleshooting for denials right after a deploy and a leaked server key runbook.
|
|
53
|
+
|
|
3
54
|
## 1.1.0
|
|
4
55
|
|
|
5
56
|
Integrations in under an hour: framework adapters, a sealing `fetch`, actionable errors and a `doctor` CLI.
|
package/README.md
CHANGED
|
@@ -354,11 +354,20 @@ const handler = createPSecureRemoteFetchEdgeMiddleware(
|
|
|
354
354
|
export default { fetch: handler };
|
|
355
355
|
```
|
|
356
356
|
|
|
357
|
-
Roll out in two phases
|
|
358
|
-
through
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
357
|
+
Roll out in two phases: **Monitor** first (verify every request and record the verdicts, let denied requests
|
|
358
|
+
through), **Block** once the reports look clean. The console Monitor/Block switch of the app drives this:
|
|
359
|
+
|
|
360
|
+
- **1.1 adapters** (`psecureFastify`, `psecure()`, `withPSecure`, `createPSecureGuard`) in the default mode `auto`
|
|
361
|
+
follow the switch on the next request, no redeploy (see [Monitor / Block](#monitor--block-mode-auto)).
|
|
362
|
+
- **This lower-level verifier** returns the verdict only; the decision to refuse is your code. The authority (>= 1.1)
|
|
363
|
+
reports the switch on every verdict as `verdict.appMode` (`'monitor' | 'block'`, with `verdict.appKey`): branch on
|
|
364
|
+
it, e.g. refuse when `!verdict.allowed && verdict.appMode === 'block'`.
|
|
365
|
+
- **Pre-1.1 middlewares** (`createPSecureExpressMiddleware`, `createPSecureRemoteFetchEdgeMiddleware`) ignore
|
|
366
|
+
`appMode`: they refuse every denied request whatever the switch says. Upgrade to the 1.1 adapters to follow it.
|
|
367
|
+
|
|
368
|
+
The verdict itself (`allowed`, `action`, `reason`) does not depend on the switch. `verdict.shadowWouldHaveAction` is
|
|
369
|
+
set only when the authority deployment itself runs in shadow mode. See
|
|
370
|
+
https://psecure.pawmask.com/docs/backend/rollout.
|
|
362
371
|
|
|
363
372
|
The HTTP contract of the authority (including `POST /v1/request/verify`) is published as OpenAPI 3.1 in
|
|
364
373
|
`server/api/openapi.json` of the repository.
|
|
@@ -380,17 +389,44 @@ arguments.
|
|
|
380
389
|
| `mode` | `PSECURE_MODE` | `'auto'` | `auto` follows the console switch; `monitor` / `enforce` / `off` override it. |
|
|
381
390
|
| `authorityUrl` | `PSECURE_AUTHORITY_URL` | `https://psecure-api.pawmask.com` | https only (http for loopback). |
|
|
382
391
|
| `timeoutMs` | `PSECURE_TIMEOUT_MS` | `1500` | Authority call timeout. |
|
|
392
|
+
| `modeFallback` | `PSECURE_MODE_FALLBACK` | `'monitor'` | Mode `auto` applies while the console mode is unknown (cold start, cached mode expired). `'enforce'` for apps in Block: see [Monitor / Block](#monitor--block-mode-auto). |
|
|
383
393
|
| `appKey` | `PSECURE_APP_KEY` | none | **Recommended.** The app this backend serves: sent as `expectedAppKey`, so the authority refuses leases of any other app (`app_mismatch`) and the console mode is only taken for this app. Also scopes the mode cache. Per request: `appKey` on the request (Fastify route config `psecureAppKey`). |
|
|
384
|
-
| `protect` | | `'all'` | Routes that fail closed (see below). Matchers: `'/pay'`, `'/api/*'`, `'/orders/:id'`, `'POST /pay'`, `RegExp`, `(info) => boolean`. |
|
|
394
|
+
| `protect` | | `'all'` | Routes that fail closed (see below). Default: **every** guarded route; for per-route opt-in pass `protect: []` and mark routes (Fastify route config `{ psecure: true }`, or matchers). Matchers: `'/pay'`, `'/api/*'`, `'/orders/:id'`, `'POST /pay'`, `RegExp`, `(info) => boolean`. |
|
|
385
395
|
| `skip` | | `[]` | Routes never checked (health checks, webhooks). `OPTIONS` is always skipped. |
|
|
386
|
-
| `onDecision` | | | `(decision, { method, path, route, ip }) => void` for metrics / audit. `createPSecureAuditThrottle({ sink })` turns it into deduplicated audit events. |
|
|
396
|
+
| `onDecision` | | | `(decision, { method, path, route, ip }) => void` for metrics / audit. `createPSecureAuditThrottle({ sink })` turns it into deduplicated audit events (see [Audit events](#audit-events)). |
|
|
387
397
|
| `logger` | | console | pino-compatible `{ info, warn, debug? }` (Fastify uses `app.log`); `false` disables. |
|
|
388
|
-
| `blockedResponse` | | `403 { error: 'PSECURE_REJECTED' }` |
|
|
398
|
+
| `blockedResponse` | | `403 { error: 'PSECURE_REJECTED' }` | `(decision) => ({ status?, body })`: your API's error shape for refused requests. Without `status` the SDK's status is kept: **401** for a reissued lease (the client needs it to adopt the lease and retry), else 403. Keep `error: 'PSECURE_REJECTED'` in the body if you use `createPSecureFetch`: it refreshes the lease on that answer. |
|
|
389
399
|
|
|
390
|
-
Fastify extras: route config `{ psecure: true }` protects a route, `{ psecure: false }` skips it
|
|
400
|
+
Fastify extras: route config `{ psecure: true }` protects a route, `{ psecure: false }` skips it, `{ psecureAppKey }`
|
|
401
|
+
pins the route to another app. Express extras:
|
|
391
402
|
`maxBodyBytes` (default 1 MiB). Edge extras: `maxBodyBytes`, `clientIp(request)`; `options` may be a function of the
|
|
392
403
|
handler's extra arguments (Cloudflare Workers `env`).
|
|
393
404
|
|
|
405
|
+
**Per-route opt-in.** By default every guarded route is fail-closed in Block. To protect only some routes:
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
await app.register(psecureFastify, { protect: [] }); // nothing fails closed by default…
|
|
409
|
+
app.post('/v1/pay', { config: { psecure: true } }, handler); // …except the routes you mark
|
|
410
|
+
app.post('/v1/webhook', { config: { psecure: false } }, handler); // never checked
|
|
411
|
+
// Express / Edge: psecure({ protect: ['POST /v1/pay', '/v1/orders/*'] })
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Denied and malformed envelopes are still refused on every guarded route in Block; `protect` only decides where a
|
|
415
|
+
**missing** envelope or an unreachable authority is refused.
|
|
416
|
+
|
|
417
|
+
**Fastify with TypeScript.** `app.register(psecureFastify, { onDecision, blockedResponse })` types the callbacks
|
|
418
|
+
(1.1.1; in 1.1.0 they were implicitly `any` under `strict`). Add the augmentation once to type `request.psecure`
|
|
419
|
+
(`PSecureDecision | null`) and the route config:
|
|
420
|
+
|
|
421
|
+
```ts
|
|
422
|
+
import '@pawmaskrelease/psecure/fastify/augment'; // types only (needs fastify 4 or 5 in your project)
|
|
423
|
+
// or, equivalently:
|
|
424
|
+
// declare module 'fastify' {
|
|
425
|
+
// interface FastifyRequest extends PSecureFastifyRequestDecoration {}
|
|
426
|
+
// interface FastifyContextConfig extends PSecureFastifyRouteConfig {}
|
|
427
|
+
// }
|
|
428
|
+
```
|
|
429
|
+
|
|
394
430
|
### Decision table
|
|
395
431
|
|
|
396
432
|
| Outcome | Monitor | Block (enforce), `protect` route | Block, other route |
|
|
@@ -412,13 +448,59 @@ trusting it.
|
|
|
412
448
|
The authority reports the app's console mode on every verdict (`appMode`). In `auto` the guard blocks only while the
|
|
413
449
|
app is in **Block**. When a request carries no verdict (no envelope, authority unreachable), the guard uses the last
|
|
414
450
|
mode it saw for the app, for up to 10 minutes; with nothing known yet (cold start) it behaves as Monitor. Trade-off:
|
|
415
|
-
right after a restart during an authority outage, unsealed requests are served until the first verdict arrives
|
|
416
|
-
|
|
451
|
+
right after a restart during an authority outage, unsealed requests are served until the first verdict arrives (a
|
|
452
|
+
cold start is Monitor), and the same happens when the cached mode expired during a long outage. Where that matters
|
|
453
|
+
more than availability:
|
|
454
|
+
|
|
455
|
+
- `PSECURE_MODE=enforce` pins Block whatever the console says (the switch is then ignored), or
|
|
456
|
+
- `PSECURE_MODE_FALLBACK=enforce` (`modeFallback: 'enforce'`) keeps following the switch but applies Block while the
|
|
457
|
+
console mode is unknown. A verdict that carries the console mode always wins. Default `monitor`.
|
|
417
458
|
|
|
418
459
|
Set `PSECURE_APP_KEY`. Without it, the guard follows the mode of whichever app a lease belongs to, so a lease of one
|
|
419
460
|
of your Monitor apps replayed against a Block app's backend would only be logged; the guard warns once at startup
|
|
420
|
-
(`APP_KEY_NOT_PINNED`). With it, that lease is denied (`reason: 'app_mismatch'`) and refused in Block
|
|
421
|
-
|
|
461
|
+
(`APP_KEY_NOT_PINNED`). With it, that lease is denied (`reason: 'app_mismatch'`) and refused in Block, and the guard
|
|
462
|
+
trusts a verdict's `appMode` only when the verdict's `appKey` equals the pinned key; any other verdict is treated as
|
|
463
|
+
carrying no mode (cache, then `modeFallback`). Each decision says which mode applied (`effectiveMode`) and why
|
|
464
|
+
(`modeSource`: `console`, `cache`, `default` or `config`).
|
|
465
|
+
|
|
466
|
+
### Audit events
|
|
467
|
+
|
|
468
|
+
```ts
|
|
469
|
+
import { createPSecureAuditThrottle } from '@pawmaskrelease/psecure/fastify'; // also /express, /edge, /server
|
|
470
|
+
const audit = createPSecureAuditThrottle({ sink: (event) => auditLog.write(event) });
|
|
471
|
+
await app.register(psecureFastify, { onDecision: audit.onDecision });
|
|
472
|
+
app.addHook('onClose', () => audit.close());
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
The sink (`PSecureAuditSink`, `(event) => void | Promise<void>`) receives a `PSecureGuardAuditEvent`; it is never
|
|
476
|
+
awaited by the request path and its errors are swallowed. Events never contain the key, envelope, lease or body:
|
|
477
|
+
|
|
478
|
+
- `{ type: 'psecure.reject', result, action, reason, route, method, ip? }`: a refused request, emitted at once.
|
|
479
|
+
Identical refusals (result, reason, route, ip) are emitted once per `rejectCooldownMs` (default 60 s).
|
|
480
|
+
- `{ type: 'psecure.monitor_summary', windowStart, windowEnd, wouldBlock, distinctIps, distinctIpsCapped, buckets }`:
|
|
481
|
+
what Monitor would have refused in a window (`summaryWindowMs`, default 10 min); `buckets` is
|
|
482
|
+
`[{ result, reason, route, count }]`, top 50 by count.
|
|
483
|
+
|
|
484
|
+
`flush()` emits the pending summary now (nothing if the window is empty) and starts a new window; refusals are never
|
|
485
|
+
buffered. `close()` stops the timer and **flushes**, then ignores later decisions; it is idempotent. Both return a
|
|
486
|
+
promise that settles when the sink finished (`await audit.close()` before exiting).
|
|
487
|
+
|
|
488
|
+
### Testing with a stubbed authority
|
|
489
|
+
|
|
490
|
+
Point `authorityUrl` at a local stub (http is accepted on loopback) or pass `fetch`. The guard calls
|
|
491
|
+
`POST {authorityUrl}/psecure.authority.v1.PSecureAuthorityService/VerifySealedRequest` and needs only:
|
|
492
|
+
|
|
493
|
+
```json
|
|
494
|
+
{ "allowed": true, "action": "ALLOW", "reason": "ok" }
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
A denial is `{ "allowed": false, "action": "STEP_UP_CHALLENGE", "reason": "verification_failed" }`; a reissue is
|
|
498
|
+
`{ "allowed": false, "action": "REISSUE_LEASE", "reason": "reissue_required", "reissuedLease": { "compactToken": "…" } }`.
|
|
499
|
+
To exercise `auto`, add `"appMode": "block"` (or `"monitor"`) and, when the guard is pinned,
|
|
500
|
+
`"appKey": "<the pinned PSECURE_APP_KEY>"`: without a matching `appKey` the mode is ignored. Requests still need a
|
|
501
|
+
well-formed `x-psecure-envelope` (from a real client, or `sealWirePayloadB64Url` from
|
|
502
|
+
`@pawmaskrelease/psecure/protocol`); without one the guard does not call the authority (`result: 'missing'`). For
|
|
503
|
+
tests that need no verification at all, `PSECURE_MODE=off`.
|
|
422
504
|
|
|
423
505
|
### Raw body
|
|
424
506
|
|
|
@@ -487,9 +569,29 @@ Returns `{ fetch, setAccount, status, lastError, ready, start, dispose }`. `stat
|
|
|
487
569
|
never re-sent unsealed (no duplicated POST).
|
|
488
570
|
- The lease is refreshed in the background when it expires or the API answers `PSECURE_REJECTED`.
|
|
489
571
|
- The SDK core is loaded lazily on the first sealed request (a dynamic import your bundler puts in its own chunk).
|
|
490
|
-
The eager part of `@pawmaskrelease/psecure/fetch` is about 16 KiB gzip; the lazy core about 112 KiB gzip (
|
|
491
|
-
before your bundler's minification).
|
|
492
|
-
-
|
|
572
|
+
The eager part of `@pawmaskrelease/psecure/fetch` is about 16 KiB gzip; the lazy core about 112 KiB gzip (measured
|
|
573
|
+
on 1.1.0, before your bundler's minification).
|
|
574
|
+
- `ready()` resolves with the outcome of the connect or lease refresh in flight: `ready`, or `failed` when the latest
|
|
575
|
+
lease acquisition failed (including a failed background refresh, 1.1.1); the next successful lease returns to
|
|
576
|
+
`ready`.
|
|
577
|
+
- Browser CSP: add the authority origin to `connect-src` (e.g. `connect-src 'self' https://api.example.com
|
|
578
|
+
https://psecure-api.pawmask.com`). A blocked request is reported as `CSP_BLOCKED`.
|
|
579
|
+
|
|
580
|
+
**Web apps.** Call `setAccount(user.id)` after sign-in and `setAccount(null)` after sign-out: the lease is bound to the
|
|
581
|
+
account and re-acquired (calling it before the first request only records the account). Use `enabled` as the rollout
|
|
582
|
+
switch (`enabled: false` = plain `fetch`, the core is never loaded). The core is loaded on the first sealed request or
|
|
583
|
+
`start()`; call `start()` early (e.g. after the first render) to hide the lease latency.
|
|
584
|
+
|
|
585
|
+
To keep even the eager ~16 KiB out of a build where PSecure is disabled, import the helper dynamically behind your
|
|
586
|
+
flag; your bundler then splits it out and never loads it:
|
|
587
|
+
|
|
588
|
+
```ts
|
|
589
|
+
let apiFetch: typeof fetch = fetch;
|
|
590
|
+
if (import.meta.env.VITE_PSECURE_ENABLED === 'true') {
|
|
591
|
+
const { createPSecureFetch } = await import('@pawmaskrelease/psecure/fetch');
|
|
592
|
+
apiFetch = createPSecureFetch({ appKey, serverPublicKey, apiOrigins: ['https://api.example.com'] }).fetch;
|
|
593
|
+
}
|
|
594
|
+
```
|
|
493
595
|
|
|
494
596
|
## Errors
|
|
495
597
|
|
|
@@ -508,7 +610,7 @@ as `psecure config:` lines with the same codes.
|
|
|
508
610
|
| `AUTHORITY_INSECURE`, `AUTHORITY_INVALID`, `AUTHORITY_UNREACHABLE`, `CSP_BLOCKED` | http authority, bad URL, network/DNS, CSP `connect-src` |
|
|
509
611
|
| `CLOCK_SKEW` | the device or server clock is off |
|
|
510
612
|
| `RAW_BODY_MISSING` | the body parser dropped the raw bytes |
|
|
511
|
-
| `MODE_INVALID` | `PSECURE_MODE` is not `auto`, `monitor`, `enforce` or `off` |
|
|
613
|
+
| `MODE_INVALID` | `PSECURE_MODE` is not `auto`, `monitor`, `enforce` or `off` (or `PSECURE_MODE_FALLBACK` not `monitor` / `enforce`) |
|
|
512
614
|
|
|
513
615
|
## `doctor` CLI
|
|
514
616
|
|
|
@@ -529,8 +631,9 @@ the token's organization; unset, `doctor` warns. Exit code 1 when a check fails.
|
|
|
529
631
|
| --- | --- |
|
|
530
632
|
| `@pawmaskrelease/psecure` | Client SDK barrel (protocol, crypto, vm, rasp, client, adapters); no server code |
|
|
531
633
|
| `@pawmaskrelease/psecure/fetch` | `createPSecureFetch` (sealing `fetch` with fallback; lazy-loads the client core) |
|
|
532
|
-
| `@pawmaskrelease/psecure/fastify` | **Backend.** `psecureFastify` plugin, `PSECURE_REQUEST_HEADERS`, `PSECURE_EXPOSED_HEADERS` |
|
|
533
|
-
| `@pawmaskrelease/psecure/
|
|
634
|
+
| `@pawmaskrelease/psecure/fastify` | **Backend.** `psecureFastify` plugin, `PSECURE_REQUEST_HEADERS`, `PSECURE_EXPOSED_HEADERS`, `createPSecureAuditThrottle` |
|
|
635
|
+
| `@pawmaskrelease/psecure/fastify/augment` | Types only: `request.psecure` and route config `{ psecure, psecureAppKey }` on Fastify's types |
|
|
636
|
+
| `@pawmaskrelease/psecure/express` | **Backend.** `psecure()` middleware, `psecureRawBody`, `createPSecureAuditThrottle` |
|
|
534
637
|
| `@pawmaskrelease/psecure/edge` | **Backend / Edge.** `withPSecure`, `createPSecureEdge` (Next.js, Hono, Workers, Bun, Deno) |
|
|
535
638
|
| `@pawmaskrelease/psecure/client` | `PSecureClient` (`connect` / `sealRequest` / `sealRequestAsync` / `protectFetch` / `dispose`) |
|
|
536
639
|
| `@pawmaskrelease/psecure/server` | **Backend / Edge only.** Remote Authority client & verification middlewares: `PSecureRemoteAuthorityClient`, `createExpressMiddleware`, `createPSecureExpressMiddleware`, `createPSecureRemoteExpressMiddleware`, `createPSecureFetchEdgeMiddleware`, `createPSecureRemoteFetchEdgeMiddleware`, plus the 1.1 guard (`createPSecureGuard`) and the Express / Edge adapters. (The Split-Key Verification Engine is never shipped in the public npm package to prevent offline white-box oracle attacks; never import `@pawmaskrelease/psecure/server` from browser code.) |
|
package/dist/adapters/desktop.js
CHANGED
|
@@ -55,4 +55,4 @@ dispose(){if(this.#_0x1dd12b)
|
|
|
55
55
|
return;this.#_0x1dd12b=true;this.#_0x557f55.fill(0);this.#_0xd63721.clear();this.#_0x32df7f.dispose();}}
|
|
56
56
|
export async function sealDesktopRequestAsync(_0x53637e,_0x02eef0){if(_0x53637e instanceof PSecureDesktopBridge){return _0x53637e.sealDesktopRequestAsync(_0x02eef0);}
|
|
57
57
|
return _0x53637e.sealRequestAsync({[_0xc9bd50_S(26)]:_0x02eef0.method,[_0xc9bd50_S(27)]:_0x02eef0.path,[_0xc9bd50_S(28)]:_0x02eef0.origin,[_0xc9bd50_S(29)]:_0x02eef0.body,[_0xc9bd50_S(30)]:_0x02eef0.nowMs,});}
|
|
58
|
-
/* @psec-self-seal sha256=
|
|
58
|
+
/* @psec-self-seal sha256=2a8c0aa9c667aa603e5f3b3a4cf29077637dc0fb7a64c87c5edf46e6766b9daf fnv1a=dd197b03 */
|
package/dist/adapters/index.js
CHANGED
|
@@ -3,4 +3,4 @@ export * from "./mobile-bridge.js";
|
|
|
3
3
|
export * from "./react-native.js";
|
|
4
4
|
export * from "./desktop.js";
|
|
5
5
|
|
|
6
|
-
/* @psec-self-seal sha256=
|
|
6
|
+
/* @psec-self-seal sha256=6711c3a559952f6bcf55039df4e99df9f78f11aa2db94ff9d53f19950930e50c fnv1a=dd197b03 */
|
|
@@ -51,4 +51,4 @@ const _0xe2bdfd=this.evaluateMobileSignals(_0x3bcc02);if(_0x567126===PSecureNati
|
|
|
51
51
|
if(_0x567126===PSecureNativeCommand.CMD_COLLECT_NATIVE_RASP){const _0x430798=new Uint8Array(8);const _0xa0e68a=new DataView(_0x430798.buffer);_0xa0e68a.setUint32(0,_0xe2bdfd>>>0,true);_0xa0e68a.setUint32(4,psecPolyHash32(_0x954c5b,_0xe2bdfd)>>>0,true);return{[_0x1aa615_S(11)]:0,[_0x1aa615_S(12)]:_0x1aa615_S(2),[_0x1aa615_S(13)]:_0xe2bdfd,[_0x1aa615_S(14)]:bytesToHex(_0x430798),};}
|
|
52
52
|
const _0x4eace7=new Uint8Array(this.#_0xa727e7);if(_0xe2bdfd!==0){_0x4eace7[0]=(_0x4eace7[0]^(_0xe2bdfd&(0x5a3ee1a5^0x5a3ee15a)))&(0x2f6ed5a5^0x2f6ed55a);_0x4eace7[1]=(_0x4eace7[1]^((_0xe2bdfd>>>8)&(0x1f803ca5^0x1f803c5a)))&(0x64879ea5^0x64879e5a);_0x4eace7[2]=(_0x4eace7[2]^((_0xe2bdfd>>>(0x9e7964a^0x9e7965a))&(0x3fe139a5^0x3fe1395a)))&(0x166786a5^0x1667865a);_0x4eace7[3]=(_0x4eace7[3]^((_0xe2bdfd>>>(0x7bf8ef42^0x7bf8ef5a))&(0x12a035a5^0x12a0355a)))&(0x6c1325a5^0x6c13255a);_0x4eace7[(0x52913045^0x5291305a)]=(_0x4eace7[(0x1f31f645^0x1f31f65a)]^(0x5b85a3ff^0x5b85a35a))&(0x67acf4a5^0x67acf45a);}
|
|
53
53
|
const _0x088074=psecRandomBytes((0x686bac56^0x686bac5a));const _0xfb6e20=new DataView(_0x088074.buffer,_0x088074.byteOffset,_0x088074.byteLength);_0xfb6e20.setUint32(0,(_0xfb6e20.getUint32(0,true)^(_0x567126>>>0))>>>0,true);_0xfb6e20.setUint32(4,(_0xfb6e20.getUint32(4,true)^(_0x954c5b.length>>>0))>>>0,true);const _0x3271f6=psecChaChaCfbSeal(_0x954c5b,_0x4eace7,_0x088074);_0x4eace7.fill(0);const _0x733c76=new Uint8Array(_0x088074.length+_0x3271f6.ciphertext.length+_0x3271f6.tag.length);_0x733c76.set(_0x088074,0);_0x733c76.set(_0x3271f6.ciphertext,_0x088074.length);_0x733c76.set(_0x3271f6.tag,_0x088074.length+_0x3271f6.ciphertext.length);return{[_0x1aa615_S(11)]:0,[_0x1aa615_S(12)]:_0x1aa615_S(2),[_0x1aa615_S(13)]:_0xe2bdfd,[_0x1aa615_S(14)]:bytesToHex(_0x733c76),[_0x1aa615_S(15)]:bytesToHex(_0x088074),};}}
|
|
54
|
-
/* @psec-self-seal sha256=
|
|
54
|
+
/* @psec-self-seal sha256=4515ad549f59476dfb8fca019b54a1b205734b6112b067ea6eaa8d041c6bc8af fnv1a=dd197b03 */
|
|
@@ -43,4 +43,4 @@ pingNativeCore(){this.#_0xafdc03();return this.#_0xae6fa2.dispatch(PSecureNative
|
|
|
43
43
|
sealMobileRequest(_0x167378){this.#_0xafdc03();return this.#_0xae6fa2.sealMobileRequest(this.#_0x7902b1,_0x167378,this.#_0xa9f01f);}
|
|
44
44
|
async sealRequestAsync(_0x167378){this.#_0xafdc03();return this.#_0xae6fa2.sealMobileRequestAsync(this.#_0x7902b1,_0x167378,this.#_0xa9f01f);}
|
|
45
45
|
async sealMobileRequestAsync(_0x167378){return this.sealRequestAsync(_0x167378);}}
|
|
46
|
-
/* @psec-self-seal sha256=
|
|
46
|
+
/* @psec-self-seal sha256=2ba3a484fdf1b03616607acecee1b1da2d21a7127676c0a5188a4ef814901727 fnv1a=dd197b03 */
|
|
@@ -50,4 +50,4 @@ return{[_0x63aba3_S(17)]:_0x219643.length===0,[_0x63aba3_S(18)]:_0x219643,[_0x63
|
|
|
50
50
|
createProtectedFetchInterceptor(_0x81dde3,_0x58a799){return(_0xe81982,_0xf1ec43)=>{if(_0x81dde3.requiresAsyncSealing){throw new Error(_0x63aba3_S(4));}
|
|
51
51
|
const _0xb962a1=globalThis.location;const _0x22312b=typeof _0xb962a1?.href===_0x63aba3_S(5)&&/^https?:/i.test(_0xb962a1.href)?_0xb962a1.href:undefined;const _0xd56d2b=typeof _0xe81982===_0x63aba3_S(5)?new URL(_0xe81982,_0x22312b):new URL(_0xe81982.href);const origin=canonicalizeOrigin(_0xd56d2b);if(!_0x81dde3.isSealOriginAllowed(origin)){throw new Error(`PSecureWebShield: refusing to seal for non-allowlisted origin ${origin} (configure sealOrigins)`);}
|
|
52
52
|
const _0xbb457f=_0x58a799();const _0xb4f832=this.verifyDomSimHashDrift(_0xbb457f.domTokens);const _0x795be8=this.auditScriptTagsForSkimming(_0xbb457f.scripts);const _0x91cb3a=_0xb4f832.raspBit|_0x795be8.raspBit;return _0x81dde3.sealRequest({[_0x63aba3_S(19)]:_0xf1ec43?.method??_0x63aba3_S(6),[_0x63aba3_S(20)]:origin,[_0x63aba3_S(21)]:buildPathAndQuery(_0xd56d2b),[_0x63aba3_S(22)]:(_0xf1ec43?.body??''),[_0x63aba3_S(23)]:_0x91cb3a!==0?_0x91cb3a:undefined,});};}}
|
|
53
|
-
/* @psec-self-seal sha256=
|
|
53
|
+
/* @psec-self-seal sha256=4d1ad4a9f3a42a09c88458d8b580fd0de9dbf5117546402736259e45d954f4ac fnv1a=dd197b03 */
|
|
@@ -127,4 +127,4 @@ _0x69cf3d.poisonMask)>>>
|
|
|
127
127
|
return;}
|
|
128
128
|
if(!handlerObj||typeof handlerObj!==_0x1b7e94_S((0x42513f4b^0x42513f5a))){return;}
|
|
129
129
|
const _0x0fb898=handlerObj;if(typeof _0x0fb898.PS762===_0x1b7e94_S((0x2d3c9c78^0x2d3c9c5a))){handshakeCompleted=true;const _0xa458a0=_0x0fb898.PS762;_0x0fb898.PS762=()=>{};_0xa458a0(Object.freeze(_0x802124),_0xc00404,_0xf1626f);}},});return{[_0x1b7e94_S(119)]:_0xb6fbb2};}
|
|
130
|
-
/* @psec-self-seal sha256=
|
|
130
|
+
/* @psec-self-seal sha256=e6add63495a52a16fb9fe77bd728e7e755745a4a80e6f7e9d6f0dd7c5366da87 fnv1a=dd197b03 */
|
package/dist/cli/doctor.js
CHANGED
|
@@ -105,4 +105,4 @@ if(m[1]===_0xb25bc7_S((0x3d6f9266^0x3d6f925a))){_0x8ee251.stderr(_0xb25bc7_S((0x
|
|
|
105
105
|
const value=m[2]??_0xbfbda6[++i];if(value===undefined){_0x8ee251.stderr(`Option --${m[1]} needs a value.`);return 2;}
|
|
106
106
|
_0xfef070[m[1]]=value;}
|
|
107
107
|
const env=_0x8ee251.env;const checks=await runPSecureDoctor({[_0xb25bc7_S(97)]:_0xfef070.authority??env.PSECURE_AUTHORITY_URL,[_0xb25bc7_S(115)]:_0xfef070[_0xb25bc7_S((0x30cca038^0x30cca05a))]??env.PSECURE_APP_KEY,[_0xb25bc7_S(130)]:_0xfef070[_0xb25bc7_S((0x458a4046^0x458a405a))]??env.PSECURE_PUBLIC_KEY,[_0xb25bc7_S(99)]:_0xfef070.origin??env.PSECURE_WEB_ORIGIN,...(_0xfef070.api?{[_0xb25bc7_S(100)]:_0xfef070.api}:{}),...(env.PSECURE_SERVER_KEY?{[_0xb25bc7_S(131)]:env.PSECURE_SERVER_KEY}:{}),...(env.PSECURE_APP_KEY?{[_0xb25bc7_S(132)]:env.PSECURE_APP_KEY}:{}),...(_0x8ee251.fetch?{[_0xb25bc7_S(133)]:_0x8ee251.fetch}:{}),});_0x8ee251.stdout(json?JSON.stringify({[_0xb25bc7_S(134)]:PSECURE_SDK_VERSION,[_0xb25bc7_S(135)]:checks},null,2):formatPSecureDoctorReport(checks));return checks.some((c)=>c.status===_0xb25bc7_S(2))?1:0;}
|
|
108
|
-
/* @psec-self-seal sha256=
|
|
108
|
+
/* @psec-self-seal sha256=6eebabdc16f03292df4612a2b6d8c121f44ce4ad5b5dff1f304268e3b9a987b3 fnv1a=dd197b03 */
|
package/dist/client/index.js
CHANGED
|
@@ -213,4 +213,4 @@ function _0x1e9a27(_0x7f3676,_0xff2e92){const _0x60c0b2=_0x7f3676===_0x559202_S(
|
|
|
213
213
|
else if(!_0xff2e92.hardwareAnchors){_0xfc7320.push(_0x559202_S((0x52b05033^0x52b0505a)));}
|
|
214
214
|
if(_0x5136b1)
|
|
215
215
|
_0xfc7320.push(_0x559202_S((0x541fb430^0x541fb45a)));return Object.freeze({[_0x559202_S(172)]:_0x7f3676,[_0x559202_S(173)]:_0x5136b1,[_0x559202_S(174)]:_0x60c0b2,[_0x559202_S(175)]:Object.freeze(_0xfc7320),});}
|
|
216
|
-
/* @psec-self-seal sha256=
|
|
216
|
+
/* @psec-self-seal sha256=7499b01d86e14b8aeaf7c03d5e2386d1da8fd8d4b28255c93b7641ce3bf39407 fnv1a=dd197b03 */
|
|
@@ -55,4 +55,4 @@ throw new Error(_0xd329e2_S(6));const S=this.expandKey(_0x67835c);const _0xb5ce7
|
|
|
55
55
|
A=(A+S[(0x26d84e70^0x26d84e5a)])>>>0;C=(C+S[(0x554e1671^0x554e165a)])>>>0;const _0xb54442=new Uint8Array((0x3d83a4a^0x3d83a5a));const _0x06c6c8=new DataView(_0xb54442.buffer);_0x06c6c8.setUint32(0,A,true);_0x06c6c8.setUint32(4,B,true);_0x06c6c8.setUint32(8,C,true);_0x06c6c8.setUint32((0x4c0ef656^0x4c0ef65a),D,true);return _0xb54442;},decryptBlock(_0x3d60f3,_0x67835c){if(_0x3d60f3.length!==(0x1002664a^0x1002665a))
|
|
56
56
|
throw new Error(_0xd329e2_S(6));const S=this.expandKey(_0x67835c);const _0xb5ce7c=new DataView(_0x3d60f3.buffer,_0x3d60f3.byteOffset,(0x32cd264a^0x32cd265a));let A=(_0xb5ce7c.getUint32(0,true)-S[(0x46675870^0x4667585a)])>>>0;let B=_0xb5ce7c.getUint32(4,true);let C=(_0xb5ce7c.getUint32(8,true)-S[(0x4fc39171^0x4fc3915a)])>>>0;let D=_0xb5ce7c.getUint32((0x7ee58156^0x7ee5815a),true);for(let r=(0x14f5f84e^0x14f5f85a);r>=1;r--){const _0x2434c4=D;D=C;C=B;B=A;A=_0x2434c4;const u=rotl32(Math.imul(D,((D<<1)|1)>>>0)>>>0,5);const t=rotl32(Math.imul(B,((B<<1)|1)>>>0)>>>0,5);C=rotr32((C-S[2*r+1])>>>0,t&(0x65a81c45^0x65a81c5a))^u;A=rotr32((A-S[2*r])>>>0,u&(0x7cd2b845^0x7cd2b85a))^t;}
|
|
57
57
|
D=(D-S[1])>>>0;B=(B-S[0])>>>0;const _0xb54442=new Uint8Array((0x2672714a^0x2672715a));const _0x06c6c8=new DataView(_0xb54442.buffer);_0x06c6c8.setUint32(0,A>>>0,true);_0x06c6c8.setUint32(4,B>>>0,true);_0x06c6c8.setUint32(8,C>>>0,true);_0x06c6c8.setUint32((0x6f017056^0x6f01705a),D>>>0,true);return _0xb54442;},};
|
|
58
|
-
/* @psec-self-seal sha256=
|
|
58
|
+
/* @psec-self-seal sha256=d29d0d97e30379b7d4cceeab7fb384e67e098ad4d574f51a604ef9bcb504d07c fnv1a=dd197b03 */
|
|
@@ -78,4 +78,4 @@ if(!Number.isSafeInteger(length)||length<=0||length>(0x3d7fe7a5^0x3d7fe75a)*(0x2
|
|
|
78
78
|
const _0x4be346=Math.ceil(length/(0x2ef5f7a^0x2ef5f5a));const _0xe3d75c=new Uint8Array(_0x4be346*(0x6b55c97a^0x6b55c95a));let t=new Uint8Array(0);for(let i=1;i<=_0x4be346;i++){const _0xaccf8c=new Uint8Array(t.length+_0xbae16e.length+1);_0xaccf8c.set(t,0);_0xaccf8c.set(_0xbae16e,t.length);_0xaccf8c[t.length+_0xbae16e.length]=i;t=psecHmacSha256Bytes(_0x653b72,_0xaccf8c);_0xe3d75c.set(t,(i-1)*(0x4c5e797a^0x4c5e795a));}
|
|
79
79
|
return _0xe3d75c.subarray(0,length);}
|
|
80
80
|
export function psecHkdfSha256(_0xa627e2,length,_0x89fec8=new Uint8Array(0),_0xbae16e=new Uint8Array(0)){const _0x653b72=psecHkdfSha256Extract(_0x89fec8,_0xa627e2);return psecHkdfSha256Expand(_0x653b72,_0xbae16e,length);}
|
|
81
|
-
/* @psec-self-seal sha256=
|
|
81
|
+
/* @psec-self-seal sha256=80682afdca54cbba95139df34b8da67632c30157630ddfb44b74b41a43dc23b7 fnv1a=dd197b03 */
|
package/dist/crypto/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export * from "./primitives.js";
|
|
2
2
|
export * from "./wasm-coprocessor.js";
|
|
3
3
|
|
|
4
|
-
/* @psec-self-seal sha256=
|
|
4
|
+
/* @psec-self-seal sha256=c87e64f28c142c7eb9a8b49838ad2a0db486de5156ec318eddc0849aea818745 fnv1a=dd197b03 */
|
package/dist/crypto/mba.js
CHANGED
|
@@ -46,4 +46,4 @@ const _0xf9b964=psecMba32.linearAdd(x,_0x8cd27b);const _0x40c9cc=rotl32(_0xf9b96
|
|
|
46
46
|
const _0x5f23aa=(_0x6138d3^_0x2dc805)>>>0;const _0x98123c=(_0x3ade4c^_0xe8638b)>>>0;return psecMba32.affineMix(psecMba32.linearAdd(_0x5f23aa,_0x98123c),_0xc5ed5c);},wasmArxMix(x,y,z){const _0x4f3bfd=_0xcdbdf8();if(_0x4f3bfd){return _0x4f3bfd._0x4d(x|0,y|0,z|0)>>>0;}
|
|
47
47
|
const a=(rotl32((x+y)>>>0,(0x622ca14a^0x622ca15a))^z)>>>0;const b=rotl32((y^z)>>>0,(0x77717956^0x7771795a));return psecMba32.linearAdd(a,b);},};export function psecPolyHash32(_0x990d25,_0x94e3a1=((0x318eba^0x812d137f)>>>0)){let _0xa5d6a9=_0x94e3a1>>>0;for(let i=0;i<_0x990d25.length;i++){const _0x60b5af=_0x990d25[i]>>>0;const _0x86cd2c=psecMba32.orAndAdd(_0x60b5af,(i&(0x14ce65a5^0x14ce655a))^(0x7583c900^0x7583c95a));_0xa5d6a9=psecMba32.affineMix(_0xa5d6a9,_0x86cd2c);}
|
|
48
48
|
return _0xa5d6a9>>>0;}
|
|
49
|
-
/* @psec-self-seal sha256=
|
|
49
|
+
/* @psec-self-seal sha256=78c1c39df52a9ad0060c96deeb7504ffc5171fdf2ef11490892c603ad768311a fnv1a=dd197b03 */
|
|
@@ -5,4 +5,4 @@ export * from "./whitebox-aes.js";
|
|
|
5
5
|
export * from "./chacha-cfb.js";
|
|
6
6
|
export { psecRandomBytes } from "../protocol/codecs.js";
|
|
7
7
|
|
|
8
|
-
/* @psec-self-seal sha256=
|
|
8
|
+
/* @psec-self-seal sha256=b38f5b6360fc33e062cf1690db0fe19f7f92a976f3fcdb72ca45c783d50d0d16 fnv1a=dd197b03 */
|
package/dist/crypto/threefish.js
CHANGED
|
@@ -51,4 +51,4 @@ _0x579e60[i]=v[_0x6e84ab[i]];v=_0x579e60;const r=_0xc944d4[d%8];for(let j=0;j<4;
|
|
|
51
51
|
if(d%4===0){const s=d/4;for(let i=0;i<8;i++){v[i]=(v[i]-this.subkey(_0x60a0de,_0x424efd,s,i))&MASK64;}}}
|
|
52
52
|
const _0xfb76e0=new Uint8Array((0x3f79581a^0x3f79585a));const _0xe8257e=new DataView(_0xfb76e0.buffer);for(let i=0;i<8;i++)
|
|
53
53
|
_0xe8257e.setBigUint64(i*8,v[i],true);return _0xfb76e0;},};
|
|
54
|
-
/* @psec-self-seal sha256=
|
|
54
|
+
/* @psec-self-seal sha256=983452beb61a131b1ecffd47b3b09f9cbd7738447a0aeb9a8432e53b471401ed fnv1a=dd197b03 */
|
|
@@ -70,4 +70,4 @@ const[wrappedB64,nonceB64,tagB64,cipherB64]=_0x6fa97b.slice(-4);const kid=_0x6fa
|
|
|
70
70
|
if(expectedKid!==undefined&&kid!==expectedKid){throw new Error(`Unexpected hybrid envelope key ID: ${kid} (expected ${expectedKid})`);}
|
|
71
71
|
const _0x61af5d=_0xb7abbf(_0x50fdab);const _0x060b86=fromBase64Url(wrappedB64);const _0x7e7b26=new Uint8Array(_0x9d5453({[_0x27819f_S(37)]:_0x61af5d,[_0x27819f_S(38)]:_0xc3c6f0.RSA_PKCS1_OAEP_PADDING,[_0x27819f_S(39)]:_0x27819f_S((0x78361e50^0x78361e5a)),},_0x060b86));let key32;try{key32=psecHkdfSha256(_0x7e7b26,(0x1a30767a^0x1a30765a),new Uint8Array(0),new TextEncoder().encode(`psec-hybrid-rfc8439:${kid}`));const _0xe43fe8=fromBase64Url(nonceB64);const _0x2cb569=fromBase64Url(tagB64);const _0x2e5bb1=fromBase64Url(cipherB64);const _0x360001=new TextEncoder().encode(`rfc8439.${kid}.${wrappedB64}.${nonceB64}`);const _0x8762e6=psecRfc8439ChaCha20Poly1305Open({[_0x27819f_S(42)]:_0xe43fe8,[_0x27819f_S(43)]:_0x2e5bb1,[_0x27819f_S(44)]:_0x2cb569},key32,_0x360001);return{[_0x27819f_S(31)]:kid,[_0x27819f_S(45)]:new TextDecoder().decode(_0x8762e6),};}
|
|
72
72
|
finally{_0x7e7b26.fill(0);key32?.fill(0);}}
|
|
73
|
-
/* @psec-self-seal sha256=
|
|
73
|
+
/* @psec-self-seal sha256=54b10c4ad080252a34d8a910a245d6864872dc15cb325730b0a3642a93710d78 fnv1a=dd197b03 */
|
|
@@ -73,4 +73,4 @@ _0x17b321=this.invShiftRows(_0x17b321);const _0xd40bf9=new Uint8Array((0x6ff2744
|
|
|
73
73
|
_0x17b321=_0xd40bf9;}
|
|
74
74
|
const _0x45399a=new Uint8Array((0x1d92d04a^0x1d92d05a));for(let _0x47a223=0;_0x47a223<(0x4b94c04a^0x4b94c05a);_0x47a223++){_0x45399a[_0x47a223]=_0x7021db.invInputBijections[_0x47a223*(0x24c56e5a^0x24c56f5a)+_0x17b321[_0x47a223]];}
|
|
75
75
|
return _0x45399a;},};
|
|
76
|
-
/* @psec-self-seal sha256=
|
|
76
|
+
/* @psec-self-seal sha256=28414b1ed793bc8584be5bc0e8b94342880e68023bc843f6aec5a1c5e7abe27f fnv1a=dd197b03 */
|