@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.
Files changed (67) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +122 -19
  3. package/dist/adapters/desktop.js +1 -1
  4. package/dist/adapters/index.js +1 -1
  5. package/dist/adapters/mobile-bridge.js +1 -1
  6. package/dist/adapters/react-native.js +1 -1
  7. package/dist/adapters/web-shield.js +1 -1
  8. package/dist/adapters/web-vault.js +1 -1
  9. package/dist/cli/doctor.js +1 -1
  10. package/dist/client/index.js +1 -1
  11. package/dist/client/psecure-client.js +1 -1
  12. package/dist/crypto/block-ciphers.js +1 -1
  13. package/dist/crypto/chacha-cfb.js +1 -1
  14. package/dist/crypto/index.js +1 -1
  15. package/dist/crypto/mba.js +1 -1
  16. package/dist/crypto/primitives.js +1 -1
  17. package/dist/crypto/threefish.js +1 -1
  18. package/dist/crypto/wasm-coprocessor.js +1 -1
  19. package/dist/crypto/whitebox-aes.js +1 -1
  20. package/dist/dist-manifest.json +64 -64
  21. package/dist/errors.js +1 -1
  22. package/dist/fetch/index.js +12 -11
  23. package/dist/fetch/load-client.js +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/protocol/canonical.js +1 -1
  26. package/dist/protocol/codecs.js +1 -1
  27. package/dist/protocol/constants.js +1 -1
  28. package/dist/protocol/dvp-probes.js +1 -1
  29. package/dist/protocol/ed25519.js +1 -1
  30. package/dist/protocol/index.js +1 -1
  31. package/dist/protocol/types.js +1 -1
  32. package/dist/protocol/wire.js +1 -1
  33. package/dist/rasp/auto-collector.js +1 -1
  34. package/dist/rasp/behavior-stream.js +1 -1
  35. package/dist/rasp/dvp-consistency.js +1 -1
  36. package/dist/rasp/hardware-binding.js +1 -1
  37. package/dist/rasp/index.js +1 -1
  38. package/dist/rasp/klepto-seal.js +1 -1
  39. package/dist/rasp/mobile-native-probes.js +1 -1
  40. package/dist/rasp/probes.js +1 -1
  41. package/dist/rasp/web-integrity-probes.js +43 -44
  42. package/dist/server/authority-types.js +1 -1
  43. package/dist/server/edge.d.ts +3 -3
  44. package/dist/server/edge.js +2 -2
  45. package/dist/server/express.d.ts +4 -3
  46. package/dist/server/express.js +8 -8
  47. package/dist/server/fastify.d.ts +13 -4
  48. package/dist/server/fastify.js +11 -12
  49. package/dist/server/guard.d.ts +8 -5
  50. package/dist/server/guard.js +62 -56
  51. package/dist/server/index.js +1 -1
  52. package/dist/server/middleware.js +1 -1
  53. package/dist/server/remote-authority-client.js +1 -1
  54. package/dist/server/verdicts.js +1 -1
  55. package/dist/version.d.ts +1 -1
  56. package/dist/version.js +2 -2
  57. package/dist/vm/dynamic-ob.js +1 -1
  58. package/dist/vm/env-key.js +1 -1
  59. package/dist/vm/iabc-isa.js +1 -1
  60. package/dist/vm/index.js +1 -1
  61. package/dist/vm/psecure-vm.js +1 -1
  62. package/dist/web/psecure-polymorphic-loader.obf.js +1 -1
  63. package/dist/web/psecure-vm-kernel.js +1 -1
  64. package/dist/web/psecure-web-shield.bundle.js +1 -1
  65. package/package.json +7 -1
  66. package/types/fastify-augment.d.ts +14 -0
  67. 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. **Monitor** first: verify every request and record the verdicts, but let denied requests
358
- through — this is a decision of your backend (for example an environment flag around the `if (!verdict.allowed)`
359
- branch). **Enforce** once the reports look clean. The application mode in the PSecure console (Monitor / Block)
360
- classifies the app's telemetry; it does not change verdicts. `verdict.shadowWouldHaveAction` is set only when the
361
- authority deployment itself runs in shadow mode. See https://psecure.pawmask.com/docs/backend/rollout.
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' }` | Your API's error shape for refused requests. |
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. Express extras:
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
- Pin `mode: 'enforce'` (or `PSECURE_MODE=enforce`) where that matters more than availability.
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. Each decision says which
421
- mode applied (`effectiveMode`) and why (`modeSource`: `console`, `cache`, `default` or `config`).
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 (1.1.0,
491
- before your bundler's minification).
492
- - Browser CSP: add the authority origin to `connect-src`. A blocked request is reported as `CSP_BLOCKED`.
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/express` | **Backend.** `psecure()` middleware, `psecureRawBody` |
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.) |
@@ -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=1789b4905f27eec1dc7c7be9cbd964b8e06e194e710d2ed7cf3606b00c234077 fnv1a=117da010 */
58
+ /* @psec-self-seal sha256=2a8c0aa9c667aa603e5f3b3a4cf29077637dc0fb7a64c87c5edf46e6766b9daf fnv1a=dd197b03 */
@@ -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=2f38a9597f9db18b05602cfca1bafa465b1ac361b00890553793033f004b80d6 fnv1a=117da010 */
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=43061b8174042b3ad21ad653d5c37bac4f32dd0c8143c2eb668e220a6e6299cc fnv1a=117da010 */
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=30fd0e998f80cc8e85dab875d3bc52dd90d456c40ea02e64d202e1f78afc0998 fnv1a=117da010 */
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=47abfa9f579d6822bcc6cf9bcc6e48c3815e142c57dc4c3d9a11e2c259d8abab fnv1a=117da010 */
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=a211895f858b8ee7b9dd4c247af008e5ee41715a10b9ecb22eba33daa6d33a6f fnv1a=117da010 */
130
+ /* @psec-self-seal sha256=e6add63495a52a16fb9fe77bd728e7e755745a4a80e6f7e9d6f0dd7c5366da87 fnv1a=dd197b03 */
@@ -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=85f5f30f33cec02eebe8432377c8dd9201571f1fd2364ac358e7d0b28ce3e89a fnv1a=117da010 */
108
+ /* @psec-self-seal sha256=6eebabdc16f03292df4612a2b6d8c121f44ce4ad5b5dff1f304268e3b9a987b3 fnv1a=dd197b03 */
@@ -1,3 +1,3 @@
1
1
  export * from "./psecure-client.js";
2
2
 
3
- /* @psec-self-seal sha256=ae699fe109d16306da1cf2f6c9bac30d894988dfadbd51b7706d74ae1ff1a1c5 fnv1a=117da010 */
3
+ /* @psec-self-seal sha256=214583390c6cb45c82f9b240f054d31e9c8eb266ea5bf4ceb754d286acd1db9b fnv1a=dd197b03 */
@@ -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=1655a6d4df6347f2243d3a5c8dadf9b58c545ec4fb759ad89f51dcd812d7488c fnv1a=117da010 */
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=a534b30cd57579571504a1fbf479108d4e53a4a23d7e5bb4c01575efd8e9b7a8 fnv1a=117da010 */
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=4110d1c2ff357f1203edd205b8b5b2b7abc7fedf030a44b7cccc990b80a03ea6 fnv1a=117da010 */
81
+ /* @psec-self-seal sha256=80682afdca54cbba95139df34b8da67632c30157630ddfb44b74b41a43dc23b7 fnv1a=dd197b03 */
@@ -1,4 +1,4 @@
1
1
  export * from "./primitives.js";
2
2
  export * from "./wasm-coprocessor.js";
3
3
 
4
- /* @psec-self-seal sha256=e387570005ab1b1768ff0a56b62ad259ec3cc9f6730bd35e2e9e318412dc37aa fnv1a=117da010 */
4
+ /* @psec-self-seal sha256=c87e64f28c142c7eb9a8b49838ad2a0db486de5156ec318eddc0849aea818745 fnv1a=dd197b03 */
@@ -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=da4bc84bb3426b13acb3f65de1df1f96a6b943033ca45109144e9c826bcd8028 fnv1a=117da010 */
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=7201ec6d1cd5bbff6e2fbe1c87dd3f651f2959e3140d7b39eea82dd4cca44990 fnv1a=117da010 */
8
+ /* @psec-self-seal sha256=b38f5b6360fc33e062cf1690db0fe19f7f92a976f3fcdb72ca45c783d50d0d16 fnv1a=dd197b03 */
@@ -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=6403626f9c6bad9e2098e413a160cad83173127cba791e2a8751c609e725b4ad fnv1a=117da010 */
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=49aff11948cff426060a0de377a8bb8e5f9c822ab4a2191e171be019092ed336 fnv1a=117da010 */
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=c39bc0eec8f2d5573abaa079f2a05e1a5f0d296a921e02086674812d39d93d8f fnv1a=117da010 */
76
+ /* @psec-self-seal sha256=28414b1ed793bc8584be5bc0e8b94342880e68023bc843f6aec5a1c5e7abe27f fnv1a=dd197b03 */