dotdo 0.0.1 → 0.0.2
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/LICENSE +1 -1
- package/README.md +446 -315
- package/dist/ai/index.js +19 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/template-literals.js +852 -0
- package/dist/ai/template-literals.js.map +1 -0
- package/dist/api/analytics/router.js +601 -0
- package/dist/api/analytics/router.js.map +1 -0
- package/dist/api/index.js +158 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/middleware/auth-federation.js +573 -0
- package/dist/api/middleware/auth-federation.js.map +1 -0
- package/dist/api/middleware/auth.js +544 -0
- package/dist/api/middleware/auth.js.map +1 -0
- package/dist/api/middleware/error-handling.js +176 -0
- package/dist/api/middleware/error-handling.js.map +1 -0
- package/dist/api/middleware/request-id.js +21 -0
- package/dist/api/middleware/request-id.js.map +1 -0
- package/dist/api/pages.js +1180 -0
- package/dist/api/pages.js.map +1 -0
- package/dist/api/routes/api.js +612 -0
- package/dist/api/routes/api.js.map +1 -0
- package/dist/api/routes/browsers.js +471 -0
- package/dist/api/routes/browsers.js.map +1 -0
- package/dist/api/routes/do.js +188 -0
- package/dist/api/routes/do.js.map +1 -0
- package/dist/api/routes/mcp.js +459 -0
- package/dist/api/routes/mcp.js.map +1 -0
- package/dist/api/routes/obs.js +445 -0
- package/dist/api/routes/obs.js.map +1 -0
- package/dist/api/routes/openapi.js +794 -0
- package/dist/api/routes/openapi.js.map +1 -0
- package/dist/api/routes/rpc.js +1103 -0
- package/dist/api/routes/rpc.js.map +1 -0
- package/dist/api/routes/sandboxes.js +389 -0
- package/dist/api/routes/sandboxes.js.map +1 -0
- package/dist/api/test-do.js +38 -0
- package/dist/api/test-do.js.map +1 -0
- package/dist/api/types.js +11 -0
- package/dist/api/types.js.map +1 -0
- package/dist/cli/bin.js +2 -0
- package/dist/cli/main.js +52342 -0
- package/dist/db/actions.js +212 -0
- package/dist/db/actions.js.map +1 -0
- package/dist/db/auth.js +506 -0
- package/dist/db/auth.js.map +1 -0
- package/dist/db/branches.js +65 -0
- package/dist/db/branches.js.map +1 -0
- package/dist/db/clickhouse.js +1074 -0
- package/dist/db/clickhouse.js.map +1 -0
- package/dist/db/dlq.js +39 -0
- package/dist/db/dlq.js.map +1 -0
- package/dist/db/events.js +28 -0
- package/dist/db/events.js.map +1 -0
- package/dist/db/exec.js +64 -0
- package/dist/db/exec.js.map +1 -0
- package/dist/db/files.js +85 -0
- package/dist/db/files.js.map +1 -0
- package/dist/db/flags.js +24 -0
- package/dist/db/flags.js.map +1 -0
- package/dist/db/git.js +116 -0
- package/dist/db/git.js.map +1 -0
- package/dist/db/iceberg/inverted-index.js +862 -0
- package/dist/db/iceberg/inverted-index.js.map +1 -0
- package/dist/db/iceberg/puffin.js +878 -0
- package/dist/db/iceberg/puffin.js.map +1 -0
- package/dist/db/iceberg/search-manifest.js +422 -0
- package/dist/db/iceberg/search-manifest.js.map +1 -0
- package/dist/db/iceberg/types.js +8 -0
- package/dist/db/iceberg/types.js.map +1 -0
- package/dist/db/index.js +121 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/integrations.js +368 -0
- package/dist/db/integrations.js.map +1 -0
- package/dist/db/json-indexes.js +332 -0
- package/dist/db/json-indexes.js.map +1 -0
- package/dist/db/linked-accounts.js +287 -0
- package/dist/db/linked-accounts.js.map +1 -0
- package/dist/db/nouns.js +183 -0
- package/dist/db/nouns.js.map +1 -0
- package/dist/db/objects.js +170 -0
- package/dist/db/objects.js.map +1 -0
- package/dist/db/primitives/dag-scheduler/index.js +869 -0
- package/dist/db/primitives/dag-scheduler/index.js.map +1 -0
- package/dist/db/primitives/exactly-once-context.js +237 -0
- package/dist/db/primitives/exactly-once-context.js.map +1 -0
- package/dist/db/primitives/index.js +62 -0
- package/dist/db/primitives/index.js.map +1 -0
- package/dist/db/primitives/keyed-router.js +145 -0
- package/dist/db/primitives/keyed-router.js.map +1 -0
- package/dist/db/primitives/observability.js +162 -0
- package/dist/db/primitives/observability.js.map +1 -0
- package/dist/db/primitives/schema-evolution.js +643 -0
- package/dist/db/primitives/schema-evolution.js.map +1 -0
- package/dist/db/primitives/stateful-operator/index.js +770 -0
- package/dist/db/primitives/stateful-operator/index.js.map +1 -0
- package/dist/db/primitives/temporal-store.js +306 -0
- package/dist/db/primitives/temporal-store.js.map +1 -0
- package/dist/db/primitives/typed-column-store.js +1229 -0
- package/dist/db/primitives/typed-column-store.js.map +1 -0
- package/dist/db/primitives/utils/duration.js +162 -0
- package/dist/db/primitives/utils/duration.js.map +1 -0
- package/dist/db/primitives/utils/murmur3.js +118 -0
- package/dist/db/primitives/utils/murmur3.js.map +1 -0
- package/dist/db/primitives/watermark-service.js +136 -0
- package/dist/db/primitives/watermark-service.js.map +1 -0
- package/dist/db/primitives/window-manager.js +764 -0
- package/dist/db/primitives/window-manager.js.map +1 -0
- package/dist/db/relationships.js +66 -0
- package/dist/db/relationships.js.map +1 -0
- package/dist/db/schema-minimal.js +61 -0
- package/dist/db/schema-minimal.js.map +1 -0
- package/dist/db/search.js +28 -0
- package/dist/db/search.js.map +1 -0
- package/dist/db/stores.js +1665 -0
- package/dist/db/stores.js.map +1 -0
- package/dist/db/things.js +297 -0
- package/dist/db/things.js.map +1 -0
- package/dist/db/vault.js +171 -0
- package/dist/db/vault.js.map +1 -0
- package/dist/db/verbs.js +102 -0
- package/dist/db/verbs.js.map +1 -0
- package/dist/do/base.js +48 -0
- package/dist/do/base.js.map +1 -0
- package/dist/do/bash.js +35 -0
- package/dist/do/bash.js.map +1 -0
- package/dist/do/fs.js +25 -0
- package/dist/do/fs.js.map +1 -0
- package/dist/do/full.js +61 -0
- package/dist/do/full.js.map +1 -0
- package/dist/do/git.js +28 -0
- package/dist/do/git.js.map +1 -0
- package/dist/do/index.js +52 -0
- package/dist/do/index.js.map +1 -0
- package/dist/do/tiny.js +31 -0
- package/dist/do/tiny.js.map +1 -0
- package/dist/lib/DOAuth.js +261 -0
- package/dist/lib/DOAuth.js.map +1 -0
- package/dist/lib/DODispatcher.js +72 -0
- package/dist/lib/DODispatcher.js.map +1 -0
- package/dist/lib/Modifier.js +189 -0
- package/dist/lib/Modifier.js.map +1 -0
- package/dist/lib/StateStorage.js +403 -0
- package/dist/lib/StateStorage.js.map +1 -0
- package/dist/lib/TypeRegistry.js +122 -0
- package/dist/lib/TypeRegistry.js.map +1 -0
- package/dist/lib/agent/tools/bash.js +336 -0
- package/dist/lib/agent/tools/bash.js.map +1 -0
- package/dist/lib/agent/tools/edit.js +157 -0
- package/dist/lib/agent/tools/edit.js.map +1 -0
- package/dist/lib/agent/tools/glob.js +137 -0
- package/dist/lib/agent/tools/glob.js.map +1 -0
- package/dist/lib/agent/tools/grep.js +315 -0
- package/dist/lib/agent/tools/grep.js.map +1 -0
- package/dist/lib/agent/tools/index.js +71 -0
- package/dist/lib/agent/tools/index.js.map +1 -0
- package/dist/lib/agent/tools/read.js +212 -0
- package/dist/lib/agent/tools/read.js.map +1 -0
- package/dist/lib/agent/tools/types.js +197 -0
- package/dist/lib/agent/tools/types.js.map +1 -0
- package/dist/lib/agent/tools/write.js +159 -0
- package/dist/lib/agent/tools/write.js.map +1 -0
- package/dist/lib/ai/gateway.js +247 -0
- package/dist/lib/ai/gateway.js.map +1 -0
- package/dist/lib/ai/tool-loop-agent.js +591 -0
- package/dist/lib/ai/tool-loop-agent.js.map +1 -0
- package/dist/lib/auto-wiring.js +439 -0
- package/dist/lib/auto-wiring.js.map +1 -0
- package/dist/lib/browse/browserbase.js +163 -0
- package/dist/lib/browse/browserbase.js.map +1 -0
- package/dist/lib/browse/cloudflare.js +144 -0
- package/dist/lib/browse/cloudflare.js.map +1 -0
- package/dist/lib/browse/index.js +62 -0
- package/dist/lib/browse/index.js.map +1 -0
- package/dist/lib/browse/types.js +13 -0
- package/dist/lib/browse/types.js.map +1 -0
- package/dist/lib/cache/index.js +37 -0
- package/dist/lib/cache/index.js.map +1 -0
- package/dist/lib/cache/visibility.js +638 -0
- package/dist/lib/cache/visibility.js.map +1 -0
- package/dist/lib/capabilities.js +268 -0
- package/dist/lib/capabilities.js.map +1 -0
- package/dist/lib/channels/base.js +106 -0
- package/dist/lib/channels/base.js.map +1 -0
- package/dist/lib/channels/discord.js +94 -0
- package/dist/lib/channels/discord.js.map +1 -0
- package/dist/lib/channels/email.js +204 -0
- package/dist/lib/channels/email.js.map +1 -0
- package/dist/lib/channels/index.js +90 -0
- package/dist/lib/channels/index.js.map +1 -0
- package/dist/lib/channels/mdxui-chat.js +95 -0
- package/dist/lib/channels/mdxui-chat.js.map +1 -0
- package/dist/lib/channels/slack-blockkit.js +121 -0
- package/dist/lib/channels/slack-blockkit.js.map +1 -0
- package/dist/lib/channels/types.js +7 -0
- package/dist/lib/channels/types.js.map +1 -0
- package/dist/lib/cloudflare/ai.js +654 -0
- package/dist/lib/cloudflare/ai.js.map +1 -0
- package/dist/lib/cloudflare/index.js +88 -0
- package/dist/lib/cloudflare/index.js.map +1 -0
- package/dist/lib/cloudflare/kv.js +342 -0
- package/dist/lib/cloudflare/kv.js.map +1 -0
- package/dist/lib/cloudflare/queues.js +434 -0
- package/dist/lib/cloudflare/queues.js.map +1 -0
- package/dist/lib/cloudflare/r2.js +604 -0
- package/dist/lib/cloudflare/r2.js.map +1 -0
- package/dist/lib/cloudflare/vectorize.js +494 -0
- package/dist/lib/cloudflare/vectorize.js.map +1 -0
- package/dist/lib/cloudflare/workflows.js +569 -0
- package/dist/lib/cloudflare/workflows.js.map +1 -0
- package/dist/lib/colo/caching.js +196 -0
- package/dist/lib/colo/caching.js.map +1 -0
- package/dist/lib/colo/detection.js +194 -0
- package/dist/lib/colo/detection.js.map +1 -0
- package/dist/lib/colo/external-data.js +219 -0
- package/dist/lib/colo/external-data.js.map +1 -0
- package/dist/lib/colo/globe-data.js +179 -0
- package/dist/lib/colo/globe-data.js.map +1 -0
- package/dist/lib/colo/index.js +16 -0
- package/dist/lib/colo/index.js.map +1 -0
- package/dist/lib/decorators.js +37 -0
- package/dist/lib/decorators.js.map +1 -0
- package/dist/lib/discovery.js +81 -0
- package/dist/lib/discovery.js.map +1 -0
- package/dist/lib/executors/AgenticFunctionExecutor.js +619 -0
- package/dist/lib/executors/AgenticFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/BaseFunctionExecutor.js +328 -0
- package/dist/lib/executors/BaseFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/CascadeExecutor.js +418 -0
- package/dist/lib/executors/CascadeExecutor.js.map +1 -0
- package/dist/lib/executors/CodeFunctionExecutor.js +904 -0
- package/dist/lib/executors/CodeFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/GenerativeFunctionExecutor.js +904 -0
- package/dist/lib/executors/GenerativeFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/HumanFunctionExecutor.js +884 -0
- package/dist/lib/executors/HumanFunctionExecutor.js.map +1 -0
- package/dist/lib/executors/ParallelStepExecutor.js +308 -0
- package/dist/lib/executors/ParallelStepExecutor.js.map +1 -0
- package/dist/lib/executors/types.js +12 -0
- package/dist/lib/executors/types.js.map +1 -0
- package/dist/lib/experiments.js +89 -0
- package/dist/lib/experiments.js.map +1 -0
- package/dist/lib/flags/store.js +262 -0
- package/dist/lib/flags/store.js.map +1 -0
- package/dist/lib/functions/FunctionComposition.js +467 -0
- package/dist/lib/functions/FunctionComposition.js.map +1 -0
- package/dist/lib/functions/FunctionMiddleware.js +457 -0
- package/dist/lib/functions/FunctionMiddleware.js.map +1 -0
- package/dist/lib/functions/FunctionRegistry.js +426 -0
- package/dist/lib/functions/FunctionRegistry.js.map +1 -0
- package/dist/lib/functions/createFunction.js +1048 -0
- package/dist/lib/functions/createFunction.js.map +1 -0
- package/dist/lib/humans/index.js +68 -0
- package/dist/lib/humans/index.js.map +1 -0
- package/dist/lib/humans/templates.js +117 -0
- package/dist/lib/humans/templates.js.map +1 -0
- package/dist/lib/identity.js +98 -0
- package/dist/lib/identity.js.map +1 -0
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/logging/error-logger.js +163 -0
- package/dist/lib/logging/error-logger.js.map +1 -0
- package/dist/lib/logging/index.js +160 -0
- package/dist/lib/logging/index.js.map +1 -0
- package/dist/lib/mixins/bash.js +825 -0
- package/dist/lib/mixins/bash.js.map +1 -0
- package/dist/lib/mixins/fs.js +648 -0
- package/dist/lib/mixins/fs.js.map +1 -0
- package/dist/lib/mixins/git.js +1011 -0
- package/dist/lib/mixins/git.js.map +1 -0
- package/dist/lib/mixins/index.js +29 -0
- package/dist/lib/mixins/index.js.map +1 -0
- package/dist/lib/mixins/npm.js +662 -0
- package/dist/lib/mixins/npm.js.map +1 -0
- package/dist/lib/noun-id.js +278 -0
- package/dist/lib/noun-id.js.map +1 -0
- package/dist/lib/rate-limit/sliding-window.js +148 -0
- package/dist/lib/rate-limit/sliding-window.js.map +1 -0
- package/dist/lib/rate-limit.js +110 -0
- package/dist/lib/rate-limit.js.map +1 -0
- package/dist/lib/rpc/bindings.js +548 -0
- package/dist/lib/rpc/bindings.js.map +1 -0
- package/dist/lib/rpc/index.js +64 -0
- package/dist/lib/rpc/index.js.map +1 -0
- package/dist/lib/safe-stringify.js +223 -0
- package/dist/lib/safe-stringify.js.map +1 -0
- package/dist/lib/sandbox/miniflare-sandbox.js +1007 -0
- package/dist/lib/sandbox/miniflare-sandbox.js.map +1 -0
- package/dist/lib/sqids.js +110 -0
- package/dist/lib/sqids.js.map +1 -0
- package/dist/lib/sql/adapters/index.js +10 -0
- package/dist/lib/sql/adapters/index.js.map +1 -0
- package/dist/lib/sql/adapters/node-sql-parser.js +552 -0
- package/dist/lib/sql/adapters/node-sql-parser.js.map +1 -0
- package/dist/lib/sql/adapters/pgsql-parser.js +1189 -0
- package/dist/lib/sql/adapters/pgsql-parser.js.map +1 -0
- package/dist/lib/sql/index.js +277 -0
- package/dist/lib/sql/index.js.map +1 -0
- package/dist/lib/sql/types.js +56 -0
- package/dist/lib/sql/types.js.map +1 -0
- package/dist/lib/type-classifier.js +126 -0
- package/dist/lib/type-classifier.js.map +1 -0
- package/dist/lib/utils/html.js +47 -0
- package/dist/lib/utils/html.js.map +1 -0
- package/dist/lib/validation.js +48 -0
- package/dist/lib/validation.js.map +1 -0
- package/dist/lib/vault/store.js +411 -0
- package/dist/lib/vault/store.js.map +1 -0
- package/dist/metrics/hunch.js +739 -0
- package/dist/metrics/hunch.js.map +1 -0
- package/dist/objects/API.js +302 -0
- package/dist/objects/API.js.map +1 -0
- package/dist/objects/Agent.js +179 -0
- package/dist/objects/Agent.js.map +1 -0
- package/dist/objects/AgenticFunctionExecutor.js +8 -0
- package/dist/objects/AgenticFunctionExecutor.js.map +1 -0
- package/dist/objects/App.js +83 -0
- package/dist/objects/App.js.map +1 -0
- package/dist/objects/Browser.js +884 -0
- package/dist/objects/Browser.js.map +1 -0
- package/dist/objects/Business.js +107 -0
- package/dist/objects/Business.js.map +1 -0
- package/dist/objects/CLI.js +221 -0
- package/dist/objects/CLI.js.map +1 -0
- package/dist/objects/CodeFunctionExecutor.js +8 -0
- package/dist/objects/CodeFunctionExecutor.js.map +1 -0
- package/dist/objects/Collection.js +161 -0
- package/dist/objects/Collection.js.map +1 -0
- package/dist/objects/DO.js +41 -0
- package/dist/objects/DO.js.map +1 -0
- package/dist/objects/DOBase.js +2309 -0
- package/dist/objects/DOBase.js.map +1 -0
- package/dist/objects/DOFull.js +1676 -0
- package/dist/objects/DOFull.js.map +1 -0
- package/dist/objects/DOTiny.js +207 -0
- package/dist/objects/DOTiny.js.map +1 -0
- package/dist/objects/Directory.js +199 -0
- package/dist/objects/Directory.js.map +1 -0
- package/dist/objects/Entity.js +413 -0
- package/dist/objects/Entity.js.map +1 -0
- package/dist/objects/Function.js +116 -0
- package/dist/objects/Function.js.map +1 -0
- package/dist/objects/Human.js +231 -0
- package/dist/objects/Human.js.map +1 -0
- package/dist/objects/HumanFunctionExecutor.js +8 -0
- package/dist/objects/HumanFunctionExecutor.js.map +1 -0
- package/dist/objects/IcebergMetadataDO.js +938 -0
- package/dist/objects/IcebergMetadataDO.js.map +1 -0
- package/dist/objects/IntegrationsDO.js +1174 -0
- package/dist/objects/IntegrationsDO.js.map +1 -0
- package/dist/objects/ObservabilityBroadcaster.js +149 -0
- package/dist/objects/ObservabilityBroadcaster.js.map +1 -0
- package/dist/objects/Package.js +154 -0
- package/dist/objects/Package.js.map +1 -0
- package/dist/objects/Product.js +193 -0
- package/dist/objects/Product.js.map +1 -0
- package/dist/objects/SDK.js +152 -0
- package/dist/objects/SDK.js.map +1 -0
- package/dist/objects/SaaS.js +235 -0
- package/dist/objects/SaaS.js.map +1 -0
- package/dist/objects/SandboxDO.js +759 -0
- package/dist/objects/SandboxDO.js.map +1 -0
- package/dist/objects/Service.js +337 -0
- package/dist/objects/Service.js.map +1 -0
- package/dist/objects/Site.js +80 -0
- package/dist/objects/Site.js.map +1 -0
- package/dist/objects/Startup.js +479 -0
- package/dist/objects/Startup.js.map +1 -0
- package/dist/objects/ThingsDO.js +170 -0
- package/dist/objects/ThingsDO.js.map +1 -0
- package/dist/objects/VectorShardDO.js +648 -0
- package/dist/objects/VectorShardDO.js.map +1 -0
- package/dist/objects/Worker.js +144 -0
- package/dist/objects/Worker.js.map +1 -0
- package/dist/objects/Workflow.js +196 -0
- package/dist/objects/Workflow.js.map +1 -0
- package/dist/objects/WorkflowFactory.js +313 -0
- package/dist/objects/WorkflowFactory.js.map +1 -0
- package/dist/objects/WorkflowRuntime.js +863 -0
- package/dist/objects/WorkflowRuntime.js.map +1 -0
- package/dist/objects/circuit-breaker-bulkhead.js +178 -0
- package/dist/objects/circuit-breaker-bulkhead.js.map +1 -0
- package/dist/objects/createFunction.js +934 -0
- package/dist/objects/createFunction.js.map +1 -0
- package/dist/objects/index.js +80 -0
- package/dist/objects/index.js.map +1 -0
- package/dist/objects/lifecycle/Branch.js +275 -0
- package/dist/objects/lifecycle/Branch.js.map +1 -0
- package/dist/objects/lifecycle/Clone.js +1499 -0
- package/dist/objects/lifecycle/Clone.js.map +1 -0
- package/dist/objects/lifecycle/Compact.js +237 -0
- package/dist/objects/lifecycle/Compact.js.map +1 -0
- package/dist/objects/lifecycle/Promote.js +476 -0
- package/dist/objects/lifecycle/Promote.js.map +1 -0
- package/dist/objects/lifecycle/Shard.js +560 -0
- package/dist/objects/lifecycle/Shard.js.map +1 -0
- package/dist/objects/lifecycle/index.js +15 -0
- package/dist/objects/lifecycle/index.js.map +1 -0
- package/dist/objects/lifecycle/types.js +33 -0
- package/dist/objects/lifecycle/types.js.map +1 -0
- package/dist/objects/mixins/infrastructure.js +171 -0
- package/dist/objects/mixins/infrastructure.js.map +1 -0
- package/dist/objects/modules/StoresModule.js +153 -0
- package/dist/objects/modules/StoresModule.js.map +1 -0
- package/dist/objects/persistence/checkpoint-manager.js +606 -0
- package/dist/objects/persistence/checkpoint-manager.js.map +1 -0
- package/dist/objects/persistence/index.js +72 -0
- package/dist/objects/persistence/index.js.map +1 -0
- package/dist/objects/persistence/migration-runner.js +562 -0
- package/dist/objects/persistence/migration-runner.js.map +1 -0
- package/dist/objects/persistence/replication-manager.js +501 -0
- package/dist/objects/persistence/replication-manager.js.map +1 -0
- package/dist/objects/persistence/tiered-storage-manager.js +595 -0
- package/dist/objects/persistence/tiered-storage-manager.js.map +1 -0
- package/dist/objects/persistence/types.js +14 -0
- package/dist/objects/persistence/types.js.map +1 -0
- package/dist/objects/persistence/wal-manager.js +653 -0
- package/dist/objects/persistence/wal-manager.js.map +1 -0
- package/dist/objects/presets/index.js +20 -0
- package/dist/objects/presets/index.js.map +1 -0
- package/dist/objects/presets/primitives.js +188 -0
- package/dist/objects/presets/primitives.js.map +1 -0
- package/dist/objects/primitives/alarm-adapter.js +141 -0
- package/dist/objects/primitives/alarm-adapter.js.map +1 -0
- package/dist/objects/primitives/index.js +337 -0
- package/dist/objects/primitives/index.js.map +1 -0
- package/dist/objects/primitives/storage-adapter.js +182 -0
- package/dist/objects/primitives/storage-adapter.js.map +1 -0
- package/dist/objects/primitives/with-primitives.js +102 -0
- package/dist/objects/primitives/with-primitives.js.map +1 -0
- package/dist/objects/services/StoreManager.js +227 -0
- package/dist/objects/services/StoreManager.js.map +1 -0
- package/dist/objects/services/index.js +13 -0
- package/dist/objects/services/index.js.map +1 -0
- package/dist/objects/transport/auth-layer.js +1451 -0
- package/dist/objects/transport/auth-layer.js.map +1 -0
- package/dist/objects/transport/capnweb-target.js +355 -0
- package/dist/objects/transport/capnweb-target.js.map +1 -0
- package/dist/objects/transport/chain.js +441 -0
- package/dist/objects/transport/chain.js.map +1 -0
- package/dist/objects/transport/handler.js +58 -0
- package/dist/objects/transport/handler.js.map +1 -0
- package/dist/objects/transport/index.js +53 -0
- package/dist/objects/transport/index.js.map +1 -0
- package/dist/objects/transport/mcp-server.js +690 -0
- package/dist/objects/transport/mcp-server.js.map +1 -0
- package/dist/objects/transport/rest-autowire.js +1507 -0
- package/dist/objects/transport/rest-autowire.js.map +1 -0
- package/dist/objects/transport/rest-router.js +440 -0
- package/dist/objects/transport/rest-router.js.map +1 -0
- package/dist/objects/transport/rpc-server.js +1536 -0
- package/dist/objects/transport/rpc-server.js.map +1 -0
- package/dist/objects/transport/shared.js +575 -0
- package/dist/objects/transport/shared.js.map +1 -0
- package/dist/objects/transport/sync-engine.js +291 -0
- package/dist/objects/transport/sync-engine.js.map +1 -0
- package/dist/objects/transport/types.js +8 -0
- package/dist/objects/transport/types.js.map +1 -0
- package/dist/primitives/bashx/src/ast/analyze.js +1472 -0
- package/dist/primitives/bashx/src/ast/analyze.js.map +1 -0
- package/dist/primitives/bashx/src/ast/parser.js +1488 -0
- package/dist/primitives/bashx/src/ast/parser.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/crypto.js +1954 -0
- package/dist/primitives/bashx/src/do/commands/crypto.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/data-processing.js +1812 -0
- package/dist/primitives/bashx/src/do/commands/data-processing.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/extended-utils.js +804 -0
- package/dist/primitives/bashx/src/do/commands/extended-utils.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/math-control.js +1122 -0
- package/dist/primitives/bashx/src/do/commands/math-control.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/posix-utils.js +1015 -0
- package/dist/primitives/bashx/src/do/commands/posix-utils.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/system-utils.js +687 -0
- package/dist/primitives/bashx/src/do/commands/system-utils.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/test-command.js +523 -0
- package/dist/primitives/bashx/src/do/commands/test-command.js.map +1 -0
- package/dist/primitives/bashx/src/do/commands/text-processing.js +1550 -0
- package/dist/primitives/bashx/src/do/commands/text-processing.js.map +1 -0
- package/dist/primitives/bashx/src/do/container-executor.js +429 -0
- package/dist/primitives/bashx/src/do/container-executor.js.map +1 -0
- package/dist/primitives/bashx/src/do/index.js +668 -0
- package/dist/primitives/bashx/src/do/index.js.map +1 -0
- package/dist/primitives/bashx/src/do/tiered-executor.js +2647 -0
- package/dist/primitives/bashx/src/do/tiered-executor.js.map +1 -0
- package/dist/primitives/bashx/src/do/worker.js +352 -0
- package/dist/primitives/bashx/src/do/worker.js.map +1 -0
- package/dist/primitives/bashx/src/types.js +10 -0
- package/dist/primitives/bashx/src/types.js.map +1 -0
- package/dist/primitives/fsx/core/backend.js +480 -0
- package/dist/primitives/fsx/core/backend.js.map +1 -0
- package/dist/primitives/fsx/core/constants.js +140 -0
- package/dist/primitives/fsx/core/constants.js.map +1 -0
- package/dist/primitives/fsx/core/fsx.js +1184 -0
- package/dist/primitives/fsx/core/fsx.js.map +1 -0
- package/dist/primitives/fsx/core/glob/glob.js +438 -0
- package/dist/primitives/fsx/core/glob/glob.js.map +1 -0
- package/dist/primitives/fsx/core/glob/index.js +8 -0
- package/dist/primitives/fsx/core/glob/index.js.map +1 -0
- package/dist/primitives/fsx/core/glob/match.js +392 -0
- package/dist/primitives/fsx/core/glob/match.js.map +1 -0
- package/dist/primitives/fsx/core/types.js +307 -0
- package/dist/primitives/fsx/core/types.js.map +1 -0
- package/dist/sandbox/index.js +258 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sdk/capnweb-compat.js +42 -0
- package/dist/sdk/capnweb-compat.js.map +1 -0
- package/dist/sdk/client.js +20 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/sdk/index.js +17 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/snippets/artifacts-config.js +241 -0
- package/dist/snippets/artifacts-config.js.map +1 -0
- package/dist/snippets/artifacts-ingest.js +832 -0
- package/dist/snippets/artifacts-ingest.js.map +1 -0
- package/dist/snippets/artifacts-serve.js +1035 -0
- package/dist/snippets/artifacts-serve.js.map +1 -0
- package/dist/snippets/artifacts-types.js +161 -0
- package/dist/snippets/artifacts-types.js.map +1 -0
- package/dist/snippets/cache-probe.js +376 -0
- package/dist/snippets/cache-probe.js.map +1 -0
- package/dist/snippets/cache.js +10 -0
- package/dist/snippets/cache.js.map +1 -0
- package/dist/snippets/events.js +469 -0
- package/dist/snippets/events.js.map +1 -0
- package/dist/snippets/index.js +7 -0
- package/dist/snippets/index.js.map +1 -0
- package/dist/snippets/proxy.js +495 -0
- package/dist/snippets/proxy.js.map +1 -0
- package/dist/snippets/search.js +1759 -0
- package/dist/snippets/search.js.map +1 -0
- package/dist/streams/index.js +30 -0
- package/dist/streams/index.js.map +1 -0
- package/dist/streams/observability.js +68 -0
- package/dist/streams/observability.js.map +1 -0
- package/dist/types/AI.js +92 -0
- package/dist/types/AI.js.map +1 -0
- package/dist/types/AIFunction.js +171 -0
- package/dist/types/AIFunction.js.map +1 -0
- package/dist/types/BrowseVerb.js +89 -0
- package/dist/types/BrowseVerb.js.map +1 -0
- package/dist/types/Browser.js +31 -0
- package/dist/types/Browser.js.map +1 -0
- package/dist/types/Chaos.js +15 -0
- package/dist/types/Chaos.js.map +1 -0
- package/dist/types/CloudflareBindings.js +109 -0
- package/dist/types/CloudflareBindings.js.map +1 -0
- package/dist/types/Collection.js +50 -0
- package/dist/types/Collection.js.map +1 -0
- package/dist/types/DO.js +2 -0
- package/dist/types/DO.js.map +1 -0
- package/dist/types/DOLocation.js +63 -0
- package/dist/types/DOLocation.js.map +1 -0
- package/dist/types/EventHandler.js +57 -0
- package/dist/types/EventHandler.js.map +1 -0
- package/dist/types/Experiment.js +33 -0
- package/dist/types/Experiment.js.map +1 -0
- package/dist/types/Flag.js +57 -0
- package/dist/types/Flag.js.map +1 -0
- package/dist/types/Lifecycle.js +13 -0
- package/dist/types/Lifecycle.js.map +1 -0
- package/dist/types/Location.js +169 -0
- package/dist/types/Location.js.map +1 -0
- package/dist/types/Noun.js +66 -0
- package/dist/types/Noun.js.map +1 -0
- package/dist/types/SessionEvent.js +194 -0
- package/dist/types/SessionEvent.js.map +1 -0
- package/dist/types/Thing.js +55 -0
- package/dist/types/Thing.js.map +1 -0
- package/dist/types/ThingDO.js +153 -0
- package/dist/types/ThingDO.js.map +1 -0
- package/dist/types/Things.js +2 -0
- package/dist/types/Things.js.map +1 -0
- package/dist/types/Verb.js +119 -0
- package/dist/types/Verb.js.map +1 -0
- package/dist/types/WorkflowContext.js +70 -0
- package/dist/types/WorkflowContext.js.map +1 -0
- package/dist/types/analytics-api.js +13 -0
- package/dist/types/analytics-api.js.map +1 -0
- package/dist/types/capabilities.js +135 -0
- package/dist/types/capabilities.js.map +1 -0
- package/dist/types/drizzle.js +12 -0
- package/dist/types/drizzle.js.map +1 -0
- package/dist/types/event.js +201 -0
- package/dist/types/event.js.map +1 -0
- package/dist/types/fn.js +12 -0
- package/dist/types/fn.js.map +1 -0
- package/dist/types/iceberg.js +48 -0
- package/dist/types/iceberg.js.map +1 -0
- package/dist/types/ids.js +170 -0
- package/dist/types/ids.js.map +1 -0
- package/dist/types/index.js +41 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/introspect.js +54 -0
- package/dist/types/introspect.js.map +1 -0
- package/dist/types/observability.js +124 -0
- package/dist/types/observability.js.map +1 -0
- package/dist/types/sync-protocol.js +175 -0
- package/dist/types/sync-protocol.js.map +1 -0
- package/dist/types/vector.js +13 -0
- package/dist/types/vector.js.map +1 -0
- package/dist/workflows/ScheduleManager.js +473 -0
- package/dist/workflows/ScheduleManager.js.map +1 -0
- package/dist/workflows/StepDOBridge.js +149 -0
- package/dist/workflows/StepDOBridge.js.map +1 -0
- package/dist/workflows/StepResultStorage.js +232 -0
- package/dist/workflows/StepResultStorage.js.map +1 -0
- package/dist/workflows/WaitForEventManager.js +461 -0
- package/dist/workflows/WaitForEventManager.js.map +1 -0
- package/dist/workflows/analyzer.js +332 -0
- package/dist/workflows/analyzer.js.map +1 -0
- package/dist/workflows/compat/activity-router.js +484 -0
- package/dist/workflows/compat/activity-router.js.map +1 -0
- package/dist/workflows/compat/backends/cloudflare-workflows.js +431 -0
- package/dist/workflows/compat/backends/cloudflare-workflows.js.map +1 -0
- package/dist/workflows/compat/backends/index.js +14 -0
- package/dist/workflows/compat/backends/index.js.map +1 -0
- package/dist/workflows/compat/errors/index.js +375 -0
- package/dist/workflows/compat/errors/index.js.map +1 -0
- package/dist/workflows/compat/index.js +79 -0
- package/dist/workflows/compat/index.js.map +1 -0
- package/dist/workflows/compat/inngest/index.js +989 -0
- package/dist/workflows/compat/inngest/index.js.map +1 -0
- package/dist/workflows/compat/qstash/index.js +1263 -0
- package/dist/workflows/compat/qstash/index.js.map +1 -0
- package/dist/workflows/compat/temporal/activities.js +739 -0
- package/dist/workflows/compat/temporal/activities.js.map +1 -0
- package/dist/workflows/compat/temporal/child-workflows.js +154 -0
- package/dist/workflows/compat/temporal/child-workflows.js.map +1 -0
- package/dist/workflows/compat/temporal/client.js +381 -0
- package/dist/workflows/compat/temporal/client.js.map +1 -0
- package/dist/workflows/compat/temporal/context.js +309 -0
- package/dist/workflows/compat/temporal/context.js.map +1 -0
- package/dist/workflows/compat/temporal/determinism.js +216 -0
- package/dist/workflows/compat/temporal/determinism.js.map +1 -0
- package/dist/workflows/compat/temporal/errors.js +128 -0
- package/dist/workflows/compat/temporal/errors.js.map +1 -0
- package/dist/workflows/compat/temporal/index.js +2464 -0
- package/dist/workflows/compat/temporal/index.js.map +1 -0
- package/dist/workflows/compat/temporal/saga.js +504 -0
- package/dist/workflows/compat/temporal/saga.js.map +1 -0
- package/dist/workflows/compat/temporal/signals.js +364 -0
- package/dist/workflows/compat/temporal/signals.js.map +1 -0
- package/dist/workflows/compat/temporal/storage.js +271 -0
- package/dist/workflows/compat/temporal/storage.js.map +1 -0
- package/dist/workflows/compat/temporal/timers.js +347 -0
- package/dist/workflows/compat/temporal/timers.js.map +1 -0
- package/dist/workflows/compat/temporal/types.js +7 -0
- package/dist/workflows/compat/temporal/types.js.map +1 -0
- package/dist/workflows/compat/temporal/unified-primitives.js +339 -0
- package/dist/workflows/compat/temporal/unified-primitives.js.map +1 -0
- package/dist/workflows/compat/trigger/index.js +468 -0
- package/dist/workflows/compat/trigger/index.js.map +1 -0
- package/dist/workflows/compat/utils/index.js +69 -0
- package/dist/workflows/compat/utils/index.js.map +1 -0
- package/dist/workflows/context/correlation-capability.js +266 -0
- package/dist/workflows/context/correlation-capability.js.map +1 -0
- package/dist/workflows/context/correlation.js +484 -0
- package/dist/workflows/context/correlation.js.map +1 -0
- package/dist/workflows/context/experiment.js +289 -0
- package/dist/workflows/context/experiment.js.map +1 -0
- package/dist/workflows/context/flag.js +244 -0
- package/dist/workflows/context/flag.js.map +1 -0
- package/dist/workflows/context/foundation.js +648 -0
- package/dist/workflows/context/foundation.js.map +1 -0
- package/dist/workflows/context/human-base.js +106 -0
- package/dist/workflows/context/human-base.js.map +1 -0
- package/dist/workflows/context/human.js +368 -0
- package/dist/workflows/context/human.js.map +1 -0
- package/dist/workflows/context/measure.js +354 -0
- package/dist/workflows/context/measure.js.map +1 -0
- package/dist/workflows/context/rate-limit.js +358 -0
- package/dist/workflows/context/rate-limit.js.map +1 -0
- package/dist/workflows/context/user.js +117 -0
- package/dist/workflows/context/user.js.map +1 -0
- package/dist/workflows/context/vault.js +360 -0
- package/dist/workflows/context/vault.js.map +1 -0
- package/dist/workflows/data/entity-events/entity-events.js +489 -0
- package/dist/workflows/data/entity-events/entity-events.js.map +1 -0
- package/dist/workflows/data/experiment/index.js +599 -0
- package/dist/workflows/data/experiment/index.js.map +1 -0
- package/dist/workflows/data/goal/context.js +558 -0
- package/dist/workflows/data/goal/context.js.map +1 -0
- package/dist/workflows/data/goal/index.js +32 -0
- package/dist/workflows/data/goal/index.js.map +1 -0
- package/dist/workflows/data/measure/index.js +840 -0
- package/dist/workflows/data/measure/index.js.map +1 -0
- package/dist/workflows/data/stream/index.js +1215 -0
- package/dist/workflows/data/stream/index.js.map +1 -0
- package/dist/workflows/data/track/context.js +883 -0
- package/dist/workflows/data/track/context.js.map +1 -0
- package/dist/workflows/data/track/index.js +15 -0
- package/dist/workflows/data/track/index.js.map +1 -0
- package/dist/workflows/data/view/context.js +864 -0
- package/dist/workflows/data/view/context.js.map +1 -0
- package/dist/workflows/domain.js +93 -0
- package/dist/workflows/domain.js.map +1 -0
- package/dist/workflows/flag.js +176 -0
- package/dist/workflows/flag.js.map +1 -0
- package/dist/workflows/flags.js +217 -0
- package/dist/workflows/flags.js.map +1 -0
- package/dist/workflows/hash.js +209 -0
- package/dist/workflows/hash.js.map +1 -0
- package/dist/workflows/index.js +50 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/on.js +378 -0
- package/dist/workflows/on.js.map +1 -0
- package/dist/workflows/pipeline-promise.js +481 -0
- package/dist/workflows/pipeline-promise.js.map +1 -0
- package/dist/workflows/pipeline-types.js +20 -0
- package/dist/workflows/pipeline-types.js.map +1 -0
- package/dist/workflows/proxy.js +76 -0
- package/dist/workflows/proxy.js.map +1 -0
- package/dist/workflows/runtime.js +310 -0
- package/dist/workflows/runtime.js.map +1 -0
- package/dist/workflows/schedule-builder.js +327 -0
- package/dist/workflows/schedule-builder.js.map +1 -0
- package/dist/workflows/visibility/index.js +148 -0
- package/dist/workflows/visibility/index.js.map +1 -0
- package/dist/workflows/visibility/query-parser.js +150 -0
- package/dist/workflows/visibility/query-parser.js.map +1 -0
- package/dist/workflows/visibility/store.js +223 -0
- package/dist/workflows/visibility/store.js.map +1 -0
- package/dist/workflows/visibility/types.js +30 -0
- package/dist/workflows/visibility/types.js.map +1 -0
- package/dist/workflows/workflow.js +53 -0
- package/dist/workflows/workflow.js.map +1 -0
- package/package.json +279 -46
|
@@ -0,0 +1,1954 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Crypto/Hashing Commands Implementation
|
|
3
|
+
*
|
|
4
|
+
* Native implementations of crypto and hashing commands using Web Crypto API:
|
|
5
|
+
* - sha256sum, sha1sum, sha512sum, md5sum
|
|
6
|
+
* - uuidgen / uuid
|
|
7
|
+
* - cksum / sum
|
|
8
|
+
* - openssl (subset)
|
|
9
|
+
*
|
|
10
|
+
* All implementations are designed for Cloudflare Workers environment
|
|
11
|
+
* using Web Crypto API and native crypto primitives.
|
|
12
|
+
*
|
|
13
|
+
* ## Architecture
|
|
14
|
+
*
|
|
15
|
+
* This module uses a unified `Hasher` interface that abstracts over different
|
|
16
|
+
* hash algorithm implementations:
|
|
17
|
+
* - Web Crypto API algorithms (SHA-1, SHA-256, SHA-384, SHA-512)
|
|
18
|
+
* - Custom pure JavaScript implementation (MD5)
|
|
19
|
+
*
|
|
20
|
+
* The `Hasher` interface supports both one-shot hashing via `hash()` and
|
|
21
|
+
* streaming via `createStream()` for processing large files efficiently.
|
|
22
|
+
*
|
|
23
|
+
* ## Encoding Utilities
|
|
24
|
+
*
|
|
25
|
+
* Consolidated encoding utilities in the `Encoding` namespace:
|
|
26
|
+
* - `Encoding.toHex()` / `Encoding.fromHex()` - Hexadecimal encoding
|
|
27
|
+
* - `Encoding.toBase64()` / `Encoding.fromBase64()` - Base64 encoding
|
|
28
|
+
* - `Encoding.stringToBytes()` / `Encoding.bytesToString()` - UTF-8 encoding
|
|
29
|
+
*
|
|
30
|
+
* @module bashx/do/commands/crypto
|
|
31
|
+
*/
|
|
32
|
+
/**
|
|
33
|
+
* Well-known UUID namespaces as defined in RFC 4122.
|
|
34
|
+
* Use with UUID v3 and v5 for deterministic UUID generation.
|
|
35
|
+
*/
|
|
36
|
+
export const UUID_NAMESPACES = {
|
|
37
|
+
/** DNS namespace UUID */
|
|
38
|
+
DNS: '6ba7b810-9dad-11d1-80b4-00c04fd430c8',
|
|
39
|
+
/** URL namespace UUID */
|
|
40
|
+
URL: '6ba7b811-9dad-11d1-80b4-00c04fd430c8',
|
|
41
|
+
/** OID namespace UUID */
|
|
42
|
+
OID: '6ba7b812-9dad-11d1-80b4-00c04fd430c8',
|
|
43
|
+
/** X.500 DN namespace UUID */
|
|
44
|
+
X500: '6ba7b814-9dad-11d1-80b4-00c04fd430c8',
|
|
45
|
+
};
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// ENCODING UTILITIES
|
|
48
|
+
// ============================================================================
|
|
49
|
+
/**
|
|
50
|
+
* Consolidated encoding utilities for hex, base64, and UTF-8 conversions.
|
|
51
|
+
* All functions are pure and stateless.
|
|
52
|
+
*/
|
|
53
|
+
export var Encoding;
|
|
54
|
+
(function (Encoding) {
|
|
55
|
+
/**
|
|
56
|
+
* Convert a Uint8Array to a hexadecimal string.
|
|
57
|
+
*
|
|
58
|
+
* @param bytes - The bytes to convert
|
|
59
|
+
* @returns Lowercase hexadecimal string representation
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* Encoding.toHex(new Uint8Array([0xde, 0xad, 0xbe, 0xef]))
|
|
64
|
+
* // Returns: 'deadbeef'
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
function toHex(bytes) {
|
|
68
|
+
return Array.from(bytes)
|
|
69
|
+
.map(b => b.toString(16).padStart(2, '0'))
|
|
70
|
+
.join('');
|
|
71
|
+
}
|
|
72
|
+
Encoding.toHex = toHex;
|
|
73
|
+
/**
|
|
74
|
+
* Convert a hexadecimal string to a Uint8Array.
|
|
75
|
+
*
|
|
76
|
+
* @param hex - The hexadecimal string (case-insensitive)
|
|
77
|
+
* @returns Uint8Array of decoded bytes
|
|
78
|
+
* @throws If the string length is not even
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* Encoding.fromHex('deadbeef')
|
|
83
|
+
* // Returns: Uint8Array([0xde, 0xad, 0xbe, 0xef])
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
function fromHex(hex) {
|
|
87
|
+
const bytes = new Uint8Array(hex.length / 2);
|
|
88
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
89
|
+
bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
|
|
90
|
+
}
|
|
91
|
+
return bytes;
|
|
92
|
+
}
|
|
93
|
+
Encoding.fromHex = fromHex;
|
|
94
|
+
/**
|
|
95
|
+
* Convert a string to Uint8Array using UTF-8 encoding.
|
|
96
|
+
*
|
|
97
|
+
* @param str - The string to encode
|
|
98
|
+
* @returns UTF-8 encoded bytes
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```ts
|
|
102
|
+
* Encoding.stringToBytes('hello')
|
|
103
|
+
* // Returns: Uint8Array([104, 101, 108, 108, 111])
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
function stringToBytes(str) {
|
|
107
|
+
return new TextEncoder().encode(str);
|
|
108
|
+
}
|
|
109
|
+
Encoding.stringToBytes = stringToBytes;
|
|
110
|
+
/**
|
|
111
|
+
* Convert a Uint8Array to a string using UTF-8 decoding.
|
|
112
|
+
*
|
|
113
|
+
* @param bytes - The bytes to decode
|
|
114
|
+
* @returns Decoded string
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* Encoding.bytesToString(new Uint8Array([104, 101, 108, 108, 111]))
|
|
119
|
+
* // Returns: 'hello'
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
function bytesToString(bytes) {
|
|
123
|
+
return new TextDecoder().decode(bytes);
|
|
124
|
+
}
|
|
125
|
+
Encoding.bytesToString = bytesToString;
|
|
126
|
+
/**
|
|
127
|
+
* Encode bytes to Base64 string.
|
|
128
|
+
*
|
|
129
|
+
* @param bytes - The bytes to encode
|
|
130
|
+
* @returns Base64 encoded string
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```ts
|
|
134
|
+
* Encoding.toBase64(new Uint8Array([104, 101, 108, 108, 111]))
|
|
135
|
+
* // Returns: 'aGVsbG8='
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
function toBase64(bytes) {
|
|
139
|
+
return btoa(String.fromCharCode(...bytes));
|
|
140
|
+
}
|
|
141
|
+
Encoding.toBase64 = toBase64;
|
|
142
|
+
/**
|
|
143
|
+
* Decode Base64 string to bytes.
|
|
144
|
+
*
|
|
145
|
+
* @param base64 - The Base64 string to decode
|
|
146
|
+
* @returns Decoded bytes
|
|
147
|
+
* @throws If the string is not valid Base64
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* Encoding.fromBase64('aGVsbG8=')
|
|
152
|
+
* // Returns: Uint8Array([104, 101, 108, 108, 111])
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
function fromBase64(base64) {
|
|
156
|
+
const binary = atob(base64);
|
|
157
|
+
const bytes = new Uint8Array(binary.length);
|
|
158
|
+
for (let i = 0; i < binary.length; i++) {
|
|
159
|
+
bytes[i] = binary.charCodeAt(i);
|
|
160
|
+
}
|
|
161
|
+
return bytes;
|
|
162
|
+
}
|
|
163
|
+
Encoding.fromBase64 = fromBase64;
|
|
164
|
+
})(Encoding || (Encoding = {}));
|
|
165
|
+
// Legacy exports for backward compatibility
|
|
166
|
+
/** @deprecated Use `Encoding.toHex()` instead */
|
|
167
|
+
export const toHex = Encoding.toHex;
|
|
168
|
+
/** @deprecated Use `Encoding.fromHex()` instead */
|
|
169
|
+
export const fromHex = Encoding.fromHex;
|
|
170
|
+
/** @deprecated Use `Encoding.stringToBytes()` instead */
|
|
171
|
+
export const stringToBytes = Encoding.stringToBytes;
|
|
172
|
+
/**
|
|
173
|
+
* Hash algorithm configurations with metadata for each supported algorithm.
|
|
174
|
+
*/
|
|
175
|
+
export const HASH_CONFIGS = {
|
|
176
|
+
md5: { algorithm: 'md5', hexLength: 32, tagName: 'MD5' },
|
|
177
|
+
sha1: { algorithm: 'sha1', hexLength: 40, tagName: 'SHA1', webCryptoAlgorithm: 'SHA-1' },
|
|
178
|
+
sha256: { algorithm: 'sha256', hexLength: 64, tagName: 'SHA256', webCryptoAlgorithm: 'SHA-256' },
|
|
179
|
+
sha384: { algorithm: 'sha384', hexLength: 96, tagName: 'SHA384', webCryptoAlgorithm: 'SHA-384' },
|
|
180
|
+
sha512: { algorithm: 'sha512', hexLength: 128, tagName: 'SHA512', webCryptoAlgorithm: 'SHA-512' },
|
|
181
|
+
};
|
|
182
|
+
// ============================================================================
|
|
183
|
+
// MD5 PURE IMPLEMENTATION
|
|
184
|
+
// ============================================================================
|
|
185
|
+
/**
|
|
186
|
+
* MD5 algorithm constants and helper functions.
|
|
187
|
+
* Extracted into a namespace for clarity and testability.
|
|
188
|
+
*
|
|
189
|
+
* Implementation based on RFC 1321.
|
|
190
|
+
* Note: MD5 is cryptographically broken and should not be used for security.
|
|
191
|
+
* It is provided only for compatibility with legacy systems.
|
|
192
|
+
*/
|
|
193
|
+
export var MD5;
|
|
194
|
+
(function (MD5) {
|
|
195
|
+
/** Per-round shift amounts as specified in RFC 1321 */
|
|
196
|
+
MD5.SHIFT_AMOUNTS = [
|
|
197
|
+
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
|
198
|
+
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
|
199
|
+
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
|
200
|
+
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
|
|
201
|
+
];
|
|
202
|
+
/** Pre-computed sine table: K[i] = floor(2^32 * |sin(i + 1)|) */
|
|
203
|
+
MD5.SINE_TABLE = (() => {
|
|
204
|
+
const K = new Uint32Array(64);
|
|
205
|
+
for (let i = 0; i < 64; i++) {
|
|
206
|
+
K[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000);
|
|
207
|
+
}
|
|
208
|
+
return K;
|
|
209
|
+
})();
|
|
210
|
+
/** Initial hash state values (A, B, C, D) */
|
|
211
|
+
MD5.INITIAL_STATE = {
|
|
212
|
+
A: 0x67452301,
|
|
213
|
+
B: 0xefcdab89,
|
|
214
|
+
C: 0x98badcfe,
|
|
215
|
+
D: 0x10325476,
|
|
216
|
+
};
|
|
217
|
+
/** Round function F: (X AND Y) OR (NOT X AND Z) */
|
|
218
|
+
function F(x, y, z) {
|
|
219
|
+
return (x & y) | (~x & z);
|
|
220
|
+
}
|
|
221
|
+
MD5.F = F;
|
|
222
|
+
/** Round function G: (X AND Z) OR (Y AND NOT Z) */
|
|
223
|
+
function G(x, y, z) {
|
|
224
|
+
return (x & z) | (y & ~z);
|
|
225
|
+
}
|
|
226
|
+
MD5.G = G;
|
|
227
|
+
/** Round function H: X XOR Y XOR Z */
|
|
228
|
+
function H(x, y, z) {
|
|
229
|
+
return x ^ y ^ z;
|
|
230
|
+
}
|
|
231
|
+
MD5.H = H;
|
|
232
|
+
/** Round function I: Y XOR (X OR NOT Z) */
|
|
233
|
+
function I(x, y, z) {
|
|
234
|
+
return y ^ (x | ~z);
|
|
235
|
+
}
|
|
236
|
+
MD5.I = I;
|
|
237
|
+
/** Rotate a 32-bit value left by n bits */
|
|
238
|
+
function rotateLeft(x, n) {
|
|
239
|
+
return (x << n) | (x >>> (32 - n));
|
|
240
|
+
}
|
|
241
|
+
MD5.rotateLeft = rotateLeft;
|
|
242
|
+
/** Add two 32-bit numbers with unsigned overflow */
|
|
243
|
+
function addUnsigned(x, y) {
|
|
244
|
+
return (x + y) >>> 0;
|
|
245
|
+
}
|
|
246
|
+
MD5.addUnsigned = addUnsigned;
|
|
247
|
+
/**
|
|
248
|
+
* Pad message according to MD5 specification.
|
|
249
|
+
* Appends a 1 bit, then zeros, then the original length in bits.
|
|
250
|
+
*
|
|
251
|
+
* @param data - Original message bytes
|
|
252
|
+
* @returns Padded message as Uint8Array
|
|
253
|
+
*/
|
|
254
|
+
function pad(data) {
|
|
255
|
+
const bitLen = data.length * 8;
|
|
256
|
+
const padLen = ((data.length + 8) % 64 === 0) ? 64 : 64 - ((data.length + 8) % 64);
|
|
257
|
+
const totalLen = data.length + padLen + 8;
|
|
258
|
+
const padded = new Uint8Array(totalLen);
|
|
259
|
+
padded.set(data);
|
|
260
|
+
padded[data.length] = 0x80;
|
|
261
|
+
// Append original length in bits as 64-bit little-endian
|
|
262
|
+
const lenView = new DataView(padded.buffer, totalLen - 8);
|
|
263
|
+
lenView.setUint32(0, bitLen >>> 0, true);
|
|
264
|
+
lenView.setUint32(4, Math.floor(bitLen / 0x100000000), true);
|
|
265
|
+
return padded;
|
|
266
|
+
}
|
|
267
|
+
MD5.pad = pad;
|
|
268
|
+
/**
|
|
269
|
+
* Process a single 64-byte block and update state.
|
|
270
|
+
*
|
|
271
|
+
* @param state - Current hash state [A, B, C, D]
|
|
272
|
+
* @param block - 64-byte block to process
|
|
273
|
+
*/
|
|
274
|
+
function processBlock(state, block, offset) {
|
|
275
|
+
const M = new Uint32Array(16);
|
|
276
|
+
for (let j = 0; j < 16; j++) {
|
|
277
|
+
M[j] = block.getUint32(offset + j * 4, true);
|
|
278
|
+
}
|
|
279
|
+
let [A, B, C, D] = state;
|
|
280
|
+
for (let i = 0; i < 64; i++) {
|
|
281
|
+
let f;
|
|
282
|
+
let g;
|
|
283
|
+
if (i < 16) {
|
|
284
|
+
f = F(B, C, D);
|
|
285
|
+
g = i;
|
|
286
|
+
}
|
|
287
|
+
else if (i < 32) {
|
|
288
|
+
f = G(B, C, D);
|
|
289
|
+
g = (5 * i + 1) % 16;
|
|
290
|
+
}
|
|
291
|
+
else if (i < 48) {
|
|
292
|
+
f = H(B, C, D);
|
|
293
|
+
g = (3 * i + 5) % 16;
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
f = I(B, C, D);
|
|
297
|
+
g = (7 * i) % 16;
|
|
298
|
+
}
|
|
299
|
+
const temp = D;
|
|
300
|
+
D = C;
|
|
301
|
+
C = B;
|
|
302
|
+
B = addUnsigned(B, rotateLeft(addUnsigned(addUnsigned(A, f), addUnsigned(MD5.SINE_TABLE[i], M[g])), MD5.SHIFT_AMOUNTS[i]));
|
|
303
|
+
A = temp;
|
|
304
|
+
}
|
|
305
|
+
state[0] = addUnsigned(state[0], A);
|
|
306
|
+
state[1] = addUnsigned(state[1], B);
|
|
307
|
+
state[2] = addUnsigned(state[2], C);
|
|
308
|
+
state[3] = addUnsigned(state[3], D);
|
|
309
|
+
}
|
|
310
|
+
MD5.processBlock = processBlock;
|
|
311
|
+
/**
|
|
312
|
+
* Convert final state to hex string in little-endian format.
|
|
313
|
+
*
|
|
314
|
+
* @param state - Final hash state [A, B, C, D]
|
|
315
|
+
* @returns 32-character hex string
|
|
316
|
+
*/
|
|
317
|
+
function stateToHex(state) {
|
|
318
|
+
const result = new Uint8Array(16);
|
|
319
|
+
const resultView = new DataView(result.buffer);
|
|
320
|
+
resultView.setUint32(0, state[0], true);
|
|
321
|
+
resultView.setUint32(4, state[1], true);
|
|
322
|
+
resultView.setUint32(8, state[2], true);
|
|
323
|
+
resultView.setUint32(12, state[3], true);
|
|
324
|
+
return Encoding.toHex(result);
|
|
325
|
+
}
|
|
326
|
+
MD5.stateToHex = stateToHex;
|
|
327
|
+
/**
|
|
328
|
+
* Compute MD5 hash of input data.
|
|
329
|
+
*
|
|
330
|
+
* @param data - Input bytes to hash
|
|
331
|
+
* @returns 32-character lowercase hex string
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* ```ts
|
|
335
|
+
* MD5.hash(Encoding.stringToBytes('hello'))
|
|
336
|
+
* // Returns: '5d41402abc4b2a76b9719d911017c592'
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
function hash(data) {
|
|
340
|
+
const padded = pad(data);
|
|
341
|
+
const state = [MD5.INITIAL_STATE.A, MD5.INITIAL_STATE.B, MD5.INITIAL_STATE.C, MD5.INITIAL_STATE.D];
|
|
342
|
+
const view = new DataView(padded.buffer);
|
|
343
|
+
for (let offset = 0; offset < padded.length; offset += 64) {
|
|
344
|
+
processBlock(state, view, offset);
|
|
345
|
+
}
|
|
346
|
+
return stateToHex(state);
|
|
347
|
+
}
|
|
348
|
+
MD5.hash = hash;
|
|
349
|
+
/**
|
|
350
|
+
* Create a streaming MD5 context for incremental hashing.
|
|
351
|
+
* Note: This is a simplified implementation that buffers all data.
|
|
352
|
+
* For true streaming with constant memory, a more complex implementation
|
|
353
|
+
* would be needed to handle partial blocks.
|
|
354
|
+
*
|
|
355
|
+
* @returns StreamingHashContext for incremental updates
|
|
356
|
+
*/
|
|
357
|
+
function createStream() {
|
|
358
|
+
const chunks = [];
|
|
359
|
+
return {
|
|
360
|
+
update(data) {
|
|
361
|
+
chunks.push(data.slice());
|
|
362
|
+
},
|
|
363
|
+
async finalize() {
|
|
364
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
365
|
+
const combined = new Uint8Array(totalLength);
|
|
366
|
+
let offset = 0;
|
|
367
|
+
for (const chunk of chunks) {
|
|
368
|
+
combined.set(chunk, offset);
|
|
369
|
+
offset += chunk.length;
|
|
370
|
+
}
|
|
371
|
+
return hash(combined);
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
MD5.createStream = createStream;
|
|
376
|
+
})(MD5 || (MD5 = {}));
|
|
377
|
+
// ============================================================================
|
|
378
|
+
// WEB CRYPTO HASHER IMPLEMENTATION
|
|
379
|
+
// ============================================================================
|
|
380
|
+
/**
|
|
381
|
+
* Create a Hasher implementation using Web Crypto API.
|
|
382
|
+
*
|
|
383
|
+
* @param config - Hash algorithm configuration
|
|
384
|
+
* @returns Hasher implementation
|
|
385
|
+
*/
|
|
386
|
+
function createWebCryptoHasher(config) {
|
|
387
|
+
const algorithm = config.webCryptoAlgorithm;
|
|
388
|
+
return {
|
|
389
|
+
config,
|
|
390
|
+
async hash(input) {
|
|
391
|
+
const data = typeof input === 'string' ? Encoding.stringToBytes(input) : input;
|
|
392
|
+
const hash = await crypto.subtle.digest(algorithm, data);
|
|
393
|
+
return Encoding.toHex(new Uint8Array(hash));
|
|
394
|
+
},
|
|
395
|
+
createStream() {
|
|
396
|
+
const chunks = [];
|
|
397
|
+
return {
|
|
398
|
+
update(data) {
|
|
399
|
+
chunks.push(data.slice());
|
|
400
|
+
},
|
|
401
|
+
async finalize() {
|
|
402
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
403
|
+
const combined = new Uint8Array(totalLength);
|
|
404
|
+
let offset = 0;
|
|
405
|
+
for (const chunk of chunks) {
|
|
406
|
+
combined.set(chunk, offset);
|
|
407
|
+
offset += chunk.length;
|
|
408
|
+
}
|
|
409
|
+
const hash = await crypto.subtle.digest(algorithm, combined);
|
|
410
|
+
return Encoding.toHex(new Uint8Array(hash));
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Create a Hasher implementation for MD5.
|
|
418
|
+
*
|
|
419
|
+
* @returns Hasher implementation using pure JavaScript MD5
|
|
420
|
+
*/
|
|
421
|
+
function createMD5Hasher() {
|
|
422
|
+
const config = HASH_CONFIGS.md5;
|
|
423
|
+
return {
|
|
424
|
+
config,
|
|
425
|
+
async hash(input) {
|
|
426
|
+
const data = typeof input === 'string' ? Encoding.stringToBytes(input) : input;
|
|
427
|
+
return MD5.hash(data);
|
|
428
|
+
},
|
|
429
|
+
createStream() {
|
|
430
|
+
return MD5.createStream();
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Get a Hasher for the specified algorithm.
|
|
436
|
+
*
|
|
437
|
+
* @param algorithm - Hash algorithm identifier
|
|
438
|
+
* @returns Hasher implementation
|
|
439
|
+
*
|
|
440
|
+
* @example
|
|
441
|
+
* ```ts
|
|
442
|
+
* const hasher = getHasher('sha256')
|
|
443
|
+
* const hash = await hasher.hash('hello world')
|
|
444
|
+
* ```
|
|
445
|
+
*/
|
|
446
|
+
export function getHasher(algorithm) {
|
|
447
|
+
const config = HASH_CONFIGS[algorithm];
|
|
448
|
+
if (algorithm === 'md5') {
|
|
449
|
+
return createMD5Hasher();
|
|
450
|
+
}
|
|
451
|
+
return createWebCryptoHasher(config);
|
|
452
|
+
}
|
|
453
|
+
// ============================================================================
|
|
454
|
+
// CORE HASH FUNCTIONS
|
|
455
|
+
// ============================================================================
|
|
456
|
+
/**
|
|
457
|
+
* Compute SHA-256 hash of input data.
|
|
458
|
+
*
|
|
459
|
+
* @param input - Data to hash (string or bytes)
|
|
460
|
+
* @returns Promise resolving to 64-character lowercase hex string
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
* ```ts
|
|
464
|
+
* await sha256sum('hello world')
|
|
465
|
+
* // Returns: 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
|
|
466
|
+
* ```
|
|
467
|
+
*/
|
|
468
|
+
export async function sha256sum(input) {
|
|
469
|
+
return getHasher('sha256').hash(input);
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Compute SHA-1 hash of input data.
|
|
473
|
+
*
|
|
474
|
+
* @param input - Data to hash (string or bytes)
|
|
475
|
+
* @returns Promise resolving to 40-character lowercase hex string
|
|
476
|
+
*
|
|
477
|
+
* @deprecated SHA-1 is cryptographically broken. Use SHA-256 or SHA-512 for security.
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* ```ts
|
|
481
|
+
* await sha1sum('hello world')
|
|
482
|
+
* // Returns: '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
|
|
483
|
+
* ```
|
|
484
|
+
*/
|
|
485
|
+
export async function sha1sum(input) {
|
|
486
|
+
return getHasher('sha1').hash(input);
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Compute SHA-512 hash of input data.
|
|
490
|
+
*
|
|
491
|
+
* @param input - Data to hash (string or bytes)
|
|
492
|
+
* @returns Promise resolving to 128-character lowercase hex string
|
|
493
|
+
*
|
|
494
|
+
* @example
|
|
495
|
+
* ```ts
|
|
496
|
+
* await sha512sum('hello world')
|
|
497
|
+
* // Returns: '309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f989dd35bc5ff499670da34255b45b0cfd830e81f605dcf7dc5542e93ae9cd76f'
|
|
498
|
+
* ```
|
|
499
|
+
*/
|
|
500
|
+
export async function sha512sum(input) {
|
|
501
|
+
return getHasher('sha512').hash(input);
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Compute SHA-384 hash of input data.
|
|
505
|
+
*
|
|
506
|
+
* @param input - Data to hash (string or bytes)
|
|
507
|
+
* @returns Promise resolving to 96-character lowercase hex string
|
|
508
|
+
*
|
|
509
|
+
* @example
|
|
510
|
+
* ```ts
|
|
511
|
+
* await sha384sum('hello world')
|
|
512
|
+
* // Returns: 'fdbd8e75a67f29f701a4e040385e2e23986303ea10239211af907fcbb83578b3e417cb71ce646efd0819dd8c088de1bd'
|
|
513
|
+
* ```
|
|
514
|
+
*/
|
|
515
|
+
export async function sha384sum(input) {
|
|
516
|
+
return getHasher('sha384').hash(input);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Compute MD5 hash of input data.
|
|
520
|
+
*
|
|
521
|
+
* @param input - Data to hash (string or bytes)
|
|
522
|
+
* @returns Promise resolving to 32-character lowercase hex string
|
|
523
|
+
*
|
|
524
|
+
* @deprecated MD5 is cryptographically broken. Use SHA-256 or SHA-512 for security.
|
|
525
|
+
* Provided only for compatibility with legacy systems.
|
|
526
|
+
*
|
|
527
|
+
* @example
|
|
528
|
+
* ```ts
|
|
529
|
+
* await md5sum('hello world')
|
|
530
|
+
* // Returns: '5eb63bbbe01eeed093cb22bb8f5acdc3'
|
|
531
|
+
* ```
|
|
532
|
+
*/
|
|
533
|
+
export async function md5sum(input) {
|
|
534
|
+
return getHasher('md5').hash(input);
|
|
535
|
+
}
|
|
536
|
+
// ============================================================================
|
|
537
|
+
// UUID FUNCTIONS
|
|
538
|
+
// ============================================================================
|
|
539
|
+
/**
|
|
540
|
+
* Generate a random UUID (version 4).
|
|
541
|
+
*
|
|
542
|
+
* Uses `crypto.randomUUID()` which is available in all modern environments
|
|
543
|
+
* including Cloudflare Workers. This produces cryptographically random UUIDs.
|
|
544
|
+
*
|
|
545
|
+
* @returns A random UUID in standard format (8-4-4-4-12)
|
|
546
|
+
*
|
|
547
|
+
* @example
|
|
548
|
+
* ```ts
|
|
549
|
+
* uuidv4()
|
|
550
|
+
* // Returns: '550e8400-e29b-41d4-a716-446655440000' (example)
|
|
551
|
+
* ```
|
|
552
|
+
*/
|
|
553
|
+
export function uuidv4() {
|
|
554
|
+
return crypto.randomUUID();
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Generate a time-based UUID (version 1).
|
|
558
|
+
*
|
|
559
|
+
* Creates a UUID based on the current timestamp and a random node identifier.
|
|
560
|
+
* Since we don't have access to MAC addresses in Workers, the node ID is random
|
|
561
|
+
* but has the multicast bit set to indicate it's a random node (per RFC 4122).
|
|
562
|
+
*
|
|
563
|
+
* Note: This implementation uses the current system time, so UUIDs generated
|
|
564
|
+
* close together may not be monotonically increasing due to clock precision.
|
|
565
|
+
*
|
|
566
|
+
* @returns A time-based UUID in standard format (8-4-4-4-12)
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* ```ts
|
|
570
|
+
* uuidv1()
|
|
571
|
+
* // Returns: 'f47ac10b-58cc-1198-a0fd-00002b2f3041' (example)
|
|
572
|
+
* ```
|
|
573
|
+
*/
|
|
574
|
+
export function uuidv1() {
|
|
575
|
+
// Get current timestamp in 100-nanosecond intervals since UUID epoch (Oct 15, 1582)
|
|
576
|
+
const UUID_EPOCH_MS = Date.UTC(1582, 9, 15);
|
|
577
|
+
const now = Date.now();
|
|
578
|
+
const timestamp = BigInt((now - UUID_EPOCH_MS) * 10000);
|
|
579
|
+
// Extract time components (60 bits total)
|
|
580
|
+
const timeLow = Number(timestamp & 0xffffffffn);
|
|
581
|
+
const timeMid = Number((timestamp >> 32n) & 0xffffn);
|
|
582
|
+
const timeHiAndVersion = Number((timestamp >> 48n) & 0x0fffn) | 0x1000; // Version 1
|
|
583
|
+
// Clock sequence (14 bits random)
|
|
584
|
+
const clockSeqBytes = new Uint8Array(2);
|
|
585
|
+
crypto.getRandomValues(clockSeqBytes);
|
|
586
|
+
const clockSeq = ((clockSeqBytes[0] & 0x3f) << 8) | clockSeqBytes[1];
|
|
587
|
+
const clockSeqHiAndReserved = ((clockSeq >> 8) & 0x3f) | 0x80; // Variant 10xx
|
|
588
|
+
const clockSeqLow = clockSeq & 0xff;
|
|
589
|
+
// Node (48 bits random since we don't have MAC address)
|
|
590
|
+
const nodeBytes = new Uint8Array(6);
|
|
591
|
+
crypto.getRandomValues(nodeBytes);
|
|
592
|
+
// Set multicast bit to indicate random node
|
|
593
|
+
nodeBytes[0] |= 0x01;
|
|
594
|
+
// Format UUID
|
|
595
|
+
const hex = (n, len) => n.toString(16).padStart(len, '0');
|
|
596
|
+
const nodeHex = Array.from(nodeBytes).map(b => hex(b, 2)).join('');
|
|
597
|
+
return `${hex(timeLow, 8)}-${hex(timeMid, 4)}-${hex(timeHiAndVersion, 4)}-${hex(clockSeqHiAndReserved, 2)}${hex(clockSeqLow, 2)}-${nodeHex}`;
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Generate a namespace-based UUID using MD5 (version 3).
|
|
601
|
+
*
|
|
602
|
+
* Creates a deterministic UUID from a namespace UUID and a name string.
|
|
603
|
+
* The same namespace/name combination will always produce the same UUID.
|
|
604
|
+
*
|
|
605
|
+
* @param namespace - Namespace UUID (use UUID_NAMESPACES or a custom UUID)
|
|
606
|
+
* @param name - Name to hash within the namespace
|
|
607
|
+
* @returns A deterministic UUID based on the namespace and name
|
|
608
|
+
*
|
|
609
|
+
* @deprecated UUID v3 uses MD5. Prefer uuidv5 which uses SHA-1.
|
|
610
|
+
*
|
|
611
|
+
* @example
|
|
612
|
+
* ```ts
|
|
613
|
+
* await uuidv3(UUID_NAMESPACES.URL, 'https://example.com.ai')
|
|
614
|
+
* // Returns: 'e8b764da-5fe5-3576-8a15-4b8b24b8c3b0'
|
|
615
|
+
* ```
|
|
616
|
+
*/
|
|
617
|
+
export async function uuidv3(namespace, name) {
|
|
618
|
+
const namespaceBytes = parseUuid(namespace);
|
|
619
|
+
const nameBytes = stringToBytes(name);
|
|
620
|
+
const data = new Uint8Array(namespaceBytes.length + nameBytes.length);
|
|
621
|
+
data.set(namespaceBytes);
|
|
622
|
+
data.set(nameBytes, namespaceBytes.length);
|
|
623
|
+
const hash = await md5sum(data);
|
|
624
|
+
return formatUuidFromHash(hash, 3);
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Generate a namespace-based UUID using SHA-1 (version 5).
|
|
628
|
+
*
|
|
629
|
+
* Creates a deterministic UUID from a namespace UUID and a name string.
|
|
630
|
+
* The same namespace/name combination will always produce the same UUID.
|
|
631
|
+
* This is the preferred namespace-based UUID version.
|
|
632
|
+
*
|
|
633
|
+
* @param namespace - Namespace UUID (use UUID_NAMESPACES or a custom UUID)
|
|
634
|
+
* @param name - Name to hash within the namespace
|
|
635
|
+
* @returns A deterministic UUID based on the namespace and name
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
* ```ts
|
|
639
|
+
* await uuidv5(UUID_NAMESPACES.URL, 'https://example.com.ai')
|
|
640
|
+
* // Returns: '2ed6657d-e927-568b-95e1-2665a8aea6a2'
|
|
641
|
+
*
|
|
642
|
+
* // Using DNS namespace
|
|
643
|
+
* await uuidv5(UUID_NAMESPACES.DNS, 'example.com.ai')
|
|
644
|
+
* ```
|
|
645
|
+
*/
|
|
646
|
+
export async function uuidv5(namespace, name) {
|
|
647
|
+
const namespaceBytes = parseUuid(namespace);
|
|
648
|
+
const nameBytes = stringToBytes(name);
|
|
649
|
+
const data = new Uint8Array(namespaceBytes.length + nameBytes.length);
|
|
650
|
+
data.set(namespaceBytes);
|
|
651
|
+
data.set(nameBytes, namespaceBytes.length);
|
|
652
|
+
const hash = await sha1sum(data);
|
|
653
|
+
return formatUuidFromHash(hash, 5);
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Parse a UUID string into its raw bytes.
|
|
657
|
+
*
|
|
658
|
+
* @param uuid - UUID string in standard format (with or without dashes)
|
|
659
|
+
* @returns 16-byte Uint8Array representation
|
|
660
|
+
* @throws If the UUID is not valid (not 32 hex characters)
|
|
661
|
+
*
|
|
662
|
+
* @internal
|
|
663
|
+
*/
|
|
664
|
+
function parseUuid(uuid) {
|
|
665
|
+
const hex = uuid.replace(/-/g, '');
|
|
666
|
+
if (hex.length !== 32) {
|
|
667
|
+
throw new Error(`Invalid UUID: ${uuid}`);
|
|
668
|
+
}
|
|
669
|
+
return fromHex(hex);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Format a hash output as a UUID with the specified version.
|
|
673
|
+
*
|
|
674
|
+
* Sets the version nibble (bits 12-15 of time_hi_and_version) and
|
|
675
|
+
* variant bits (bits 6-7 of clock_seq_hi_and_reserved) per RFC 4122.
|
|
676
|
+
*
|
|
677
|
+
* @param hash - Hash output as hex string (at least 32 characters)
|
|
678
|
+
* @param version - UUID version (3 for MD5, 5 for SHA-1)
|
|
679
|
+
* @returns Formatted UUID string
|
|
680
|
+
*
|
|
681
|
+
* @internal
|
|
682
|
+
*/
|
|
683
|
+
function formatUuidFromHash(hash, version) {
|
|
684
|
+
// Take first 16 bytes (32 hex chars)
|
|
685
|
+
const bytes = fromHex(hash.slice(0, 32));
|
|
686
|
+
// Set version (4 bits at position 12-15)
|
|
687
|
+
bytes[6] = (bytes[6] & 0x0f) | (version << 4);
|
|
688
|
+
// Set variant (2 bits at position 64-65)
|
|
689
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
690
|
+
const hex = toHex(bytes);
|
|
691
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Get the nil UUID (all zeros).
|
|
695
|
+
*
|
|
696
|
+
* The nil UUID is a special UUID with all 128 bits set to zero.
|
|
697
|
+
* It can be used as a placeholder or sentinel value.
|
|
698
|
+
*
|
|
699
|
+
* @returns The nil UUID string '00000000-0000-0000-0000-000000000000'
|
|
700
|
+
*
|
|
701
|
+
* @example
|
|
702
|
+
* ```ts
|
|
703
|
+
* uuidNil()
|
|
704
|
+
* // Returns: '00000000-0000-0000-0000-000000000000'
|
|
705
|
+
* ```
|
|
706
|
+
*/
|
|
707
|
+
export function uuidNil() {
|
|
708
|
+
return '00000000-0000-0000-0000-000000000000';
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Generate cryptographically secure random bytes.
|
|
712
|
+
*
|
|
713
|
+
* Uses `crypto.getRandomValues()` which is available in all modern environments
|
|
714
|
+
* including Cloudflare Workers.
|
|
715
|
+
*
|
|
716
|
+
* @param length - Number of random bytes to generate
|
|
717
|
+
* @param format - Output format: 'hex', 'base64', or 'raw' (default: 'hex')
|
|
718
|
+
* @returns Random bytes in the specified format
|
|
719
|
+
*
|
|
720
|
+
* @example
|
|
721
|
+
* ```ts
|
|
722
|
+
* // Generate 32 random bytes as hex
|
|
723
|
+
* randomBytes(32, 'hex')
|
|
724
|
+
* // Returns: 'a1b2c3d4...' (64 hex characters)
|
|
725
|
+
*
|
|
726
|
+
* // Generate 16 random bytes as base64
|
|
727
|
+
* randomBytes(16, 'base64')
|
|
728
|
+
* // Returns: 'oLbD1E5...' (base64 encoded)
|
|
729
|
+
*
|
|
730
|
+
* // Get raw bytes
|
|
731
|
+
* randomBytes(8, 'raw')
|
|
732
|
+
* // Returns: Uint8Array(8)
|
|
733
|
+
* ```
|
|
734
|
+
*/
|
|
735
|
+
export function randomBytes(length, format = 'hex') {
|
|
736
|
+
const bytes = new Uint8Array(length);
|
|
737
|
+
crypto.getRandomValues(bytes);
|
|
738
|
+
if (format === 'hex') {
|
|
739
|
+
return toHex(bytes);
|
|
740
|
+
}
|
|
741
|
+
else if (format === 'base64') {
|
|
742
|
+
return btoa(String.fromCharCode(...bytes));
|
|
743
|
+
}
|
|
744
|
+
return bytes;
|
|
745
|
+
}
|
|
746
|
+
// ============================================================================
|
|
747
|
+
// CRC / CHECKSUM FUNCTIONS
|
|
748
|
+
// ============================================================================
|
|
749
|
+
/**
|
|
750
|
+
* CRC-32 lookup table for IEEE 802.3 polynomial (0xEDB88320).
|
|
751
|
+
*
|
|
752
|
+
* This is a pre-computed lookup table for fast CRC-32 calculation.
|
|
753
|
+
* Uses the reflected polynomial (bits reversed) for efficient computation.
|
|
754
|
+
*
|
|
755
|
+
* @internal
|
|
756
|
+
*/
|
|
757
|
+
const CRC32_TABLE = (() => {
|
|
758
|
+
const table = new Uint32Array(256);
|
|
759
|
+
for (let i = 0; i < 256; i++) {
|
|
760
|
+
let crc = i;
|
|
761
|
+
for (let j = 0; j < 8; j++) {
|
|
762
|
+
crc = (crc & 1) ? (0xedb88320 ^ (crc >>> 1)) : (crc >>> 1);
|
|
763
|
+
}
|
|
764
|
+
table[i] = crc >>> 0;
|
|
765
|
+
}
|
|
766
|
+
return table;
|
|
767
|
+
})();
|
|
768
|
+
/**
|
|
769
|
+
* Compute CRC-32 checksum compatible with POSIX cksum.
|
|
770
|
+
*
|
|
771
|
+
* Uses the IEEE 802.3 polynomial and includes the data length in the CRC
|
|
772
|
+
* calculation, matching the behavior of the POSIX `cksum` command.
|
|
773
|
+
*
|
|
774
|
+
* @param data - Input data to checksum
|
|
775
|
+
* @returns 32-bit unsigned CRC value
|
|
776
|
+
*
|
|
777
|
+
* @example
|
|
778
|
+
* ```ts
|
|
779
|
+
* const data = Encoding.stringToBytes('hello world\n')
|
|
780
|
+
* crc32(data)
|
|
781
|
+
* // Returns: 3582776692 (matches: cksum < <(echo 'hello world'))
|
|
782
|
+
* ```
|
|
783
|
+
*/
|
|
784
|
+
export function crc32(data) {
|
|
785
|
+
let crc = 0xffffffff;
|
|
786
|
+
for (let i = 0; i < data.length; i++) {
|
|
787
|
+
crc = CRC32_TABLE[(crc ^ data[i]) & 0xff] ^ (crc >>> 8);
|
|
788
|
+
}
|
|
789
|
+
// Include length in CRC (POSIX cksum does this)
|
|
790
|
+
let len = data.length;
|
|
791
|
+
while (len > 0) {
|
|
792
|
+
crc = CRC32_TABLE[(crc ^ (len & 0xff)) & 0xff] ^ (crc >>> 8);
|
|
793
|
+
len >>>= 8;
|
|
794
|
+
}
|
|
795
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Compute BSD-style checksum.
|
|
799
|
+
*
|
|
800
|
+
* Uses a 16-bit rotating checksum algorithm that matches the default
|
|
801
|
+
* behavior of the BSD `sum` command (and `sum -r` on GNU systems).
|
|
802
|
+
*
|
|
803
|
+
* @param data - Input data to checksum
|
|
804
|
+
* @returns Object with 16-bit checksum and block count (1024-byte blocks)
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```ts
|
|
808
|
+
* const data = Encoding.stringToBytes('hello world\n')
|
|
809
|
+
* bsdSum(data)
|
|
810
|
+
* // Returns: { checksum: 12345, blocks: 1 }
|
|
811
|
+
* ```
|
|
812
|
+
*/
|
|
813
|
+
export function bsdSum(data) {
|
|
814
|
+
let checksum = 0;
|
|
815
|
+
for (let i = 0; i < data.length; i++) {
|
|
816
|
+
// Rotate right by 1
|
|
817
|
+
checksum = ((checksum >> 1) | ((checksum & 1) << 15)) & 0xffff;
|
|
818
|
+
// Add byte
|
|
819
|
+
checksum = (checksum + data[i]) & 0xffff;
|
|
820
|
+
}
|
|
821
|
+
// Calculate blocks (1024 byte blocks, rounded up)
|
|
822
|
+
const blocks = Math.ceil(data.length / 1024);
|
|
823
|
+
return { checksum, blocks };
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Compute System V-style checksum.
|
|
827
|
+
*
|
|
828
|
+
* Uses a simple sum algorithm with 16-bit folding that matches the
|
|
829
|
+
* behavior of `sum -s` (SYSV mode) on GNU systems.
|
|
830
|
+
*
|
|
831
|
+
* @param data - Input data to checksum
|
|
832
|
+
* @returns Object with 16-bit checksum and block count (512-byte blocks)
|
|
833
|
+
*
|
|
834
|
+
* @example
|
|
835
|
+
* ```ts
|
|
836
|
+
* const data = Encoding.stringToBytes('hello world\n')
|
|
837
|
+
* sysvSum(data)
|
|
838
|
+
* // Returns: { checksum: 1234, blocks: 1 }
|
|
839
|
+
* ```
|
|
840
|
+
*/
|
|
841
|
+
export function sysvSum(data) {
|
|
842
|
+
let sum = 0;
|
|
843
|
+
for (let i = 0; i < data.length; i++) {
|
|
844
|
+
sum += data[i];
|
|
845
|
+
}
|
|
846
|
+
// Fold to 16 bits
|
|
847
|
+
let checksum = (sum & 0xffff) + ((sum >> 16) & 0xffff);
|
|
848
|
+
checksum = (checksum & 0xffff) + ((checksum >> 16) & 0xffff);
|
|
849
|
+
// Calculate blocks (512 byte blocks, rounded up)
|
|
850
|
+
const blocks = Math.ceil(data.length / 512);
|
|
851
|
+
return { checksum, blocks };
|
|
852
|
+
}
|
|
853
|
+
// ============================================================================
|
|
854
|
+
// PASSWORD HASHING (SHA-CRYPT)
|
|
855
|
+
// ============================================================================
|
|
856
|
+
/**
|
|
857
|
+
* Base64 alphabet used by SHA-crypt password hashing.
|
|
858
|
+
*
|
|
859
|
+
* This is different from standard Base64 - it uses a different character set
|
|
860
|
+
* and ordering for compatibility with Unix password hashing.
|
|
861
|
+
*
|
|
862
|
+
* @internal
|
|
863
|
+
*/
|
|
864
|
+
const SHA_CRYPT_ALPHABET = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
865
|
+
/**
|
|
866
|
+
* Encode bytes to SHA-crypt base64 format with a specific byte order.
|
|
867
|
+
*
|
|
868
|
+
* SHA-crypt uses a custom base64 encoding with a specific byte permutation
|
|
869
|
+
* order that differs between SHA-256 and SHA-512.
|
|
870
|
+
*
|
|
871
|
+
* @param bytes - Raw hash output bytes
|
|
872
|
+
* @param order - Byte permutation order for encoding
|
|
873
|
+
* @returns Base64-encoded string using SHA-crypt alphabet
|
|
874
|
+
*
|
|
875
|
+
* @internal
|
|
876
|
+
*/
|
|
877
|
+
function shaCryptBase64(bytes, order) {
|
|
878
|
+
let result = '';
|
|
879
|
+
for (let i = 0; i < order.length; i += 3) {
|
|
880
|
+
const b0 = bytes[order[i]] ?? 0;
|
|
881
|
+
const b1 = bytes[order[i + 1]] ?? 0;
|
|
882
|
+
const b2 = bytes[order[i + 2]] ?? 0;
|
|
883
|
+
let value = (b0 << 16) | (b1 << 8) | b2;
|
|
884
|
+
const chars = i + 3 > order.length ? (order.length - i) + 1 : 4;
|
|
885
|
+
for (let j = 0; j < chars; j++) {
|
|
886
|
+
result += SHA_CRYPT_ALPHABET[value & 0x3f];
|
|
887
|
+
value >>>= 6;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return result;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Generate a random salt for SHA-crypt password hashing.
|
|
894
|
+
*
|
|
895
|
+
* Creates a cryptographically random salt string using characters
|
|
896
|
+
* from the SHA-crypt alphabet.
|
|
897
|
+
*
|
|
898
|
+
* @param length - Salt length in characters (default: 16, max: 16)
|
|
899
|
+
* @returns Random salt string
|
|
900
|
+
*
|
|
901
|
+
* @internal
|
|
902
|
+
*/
|
|
903
|
+
function generateSalt(length = 16) {
|
|
904
|
+
const bytes = new Uint8Array(length);
|
|
905
|
+
crypto.getRandomValues(bytes);
|
|
906
|
+
return Array.from(bytes)
|
|
907
|
+
.map(b => SHA_CRYPT_ALPHABET[b % 64])
|
|
908
|
+
.join('');
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Hash a password using SHA-512 crypt algorithm ($6$).
|
|
912
|
+
*
|
|
913
|
+
* Implements the SHA-512 variant of the crypt(3) specification used for
|
|
914
|
+
* Unix password hashing. The output format is `$6$salt$hash`.
|
|
915
|
+
*
|
|
916
|
+
* This uses 5000 rounds by default for reasonable security. The hash
|
|
917
|
+
* includes the salt, allowing verification without storing the salt separately.
|
|
918
|
+
*
|
|
919
|
+
* @param password - Plain text password to hash
|
|
920
|
+
* @param salt - Optional salt (random 16-char salt generated if not provided)
|
|
921
|
+
* @returns Password hash in format `$6$salt$hash`
|
|
922
|
+
*
|
|
923
|
+
* @example
|
|
924
|
+
* ```ts
|
|
925
|
+
* // Hash a password
|
|
926
|
+
* await sha512Crypt('mypassword')
|
|
927
|
+
* // Returns: '$6$<random-salt>$<hash>'
|
|
928
|
+
*
|
|
929
|
+
* // Verify a password (re-hash with same salt and compare)
|
|
930
|
+
* const hash = '$6$mysalt$...'
|
|
931
|
+
* const salt = hash.split('$')[2]
|
|
932
|
+
* const rehash = await sha512Crypt('mypassword', salt)
|
|
933
|
+
* const valid = (hash === rehash)
|
|
934
|
+
* ```
|
|
935
|
+
*/
|
|
936
|
+
export async function sha512Crypt(password, salt) {
|
|
937
|
+
salt = salt || generateSalt(16);
|
|
938
|
+
// Limit salt to 16 characters
|
|
939
|
+
salt = salt.slice(0, 16);
|
|
940
|
+
const passwordBytes = stringToBytes(password);
|
|
941
|
+
const saltBytes = stringToBytes(salt);
|
|
942
|
+
// Initial digest: password + salt + password
|
|
943
|
+
const digestB = await crypto.subtle.digest('SHA-512', new Uint8Array([...passwordBytes, ...saltBytes, ...passwordBytes]));
|
|
944
|
+
const B = new Uint8Array(digestB);
|
|
945
|
+
// Digest A: password + salt + B (repeated)
|
|
946
|
+
const aInput = [...passwordBytes, ...saltBytes];
|
|
947
|
+
let len = passwordBytes.length;
|
|
948
|
+
while (len > 0) {
|
|
949
|
+
const take = Math.min(len, 64);
|
|
950
|
+
aInput.push(...B.slice(0, take));
|
|
951
|
+
len -= take;
|
|
952
|
+
}
|
|
953
|
+
// Add bits based on password length
|
|
954
|
+
len = passwordBytes.length;
|
|
955
|
+
while (len > 0) {
|
|
956
|
+
if (len & 1) {
|
|
957
|
+
aInput.push(...B);
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
aInput.push(...passwordBytes);
|
|
961
|
+
}
|
|
962
|
+
len >>>= 1;
|
|
963
|
+
}
|
|
964
|
+
let A = new Uint8Array(await crypto.subtle.digest('SHA-512', new Uint8Array(aInput)));
|
|
965
|
+
// Digest DP (password repeated)
|
|
966
|
+
const dpInput = [];
|
|
967
|
+
for (let i = 0; i < passwordBytes.length; i++) {
|
|
968
|
+
dpInput.push(...passwordBytes);
|
|
969
|
+
}
|
|
970
|
+
const DP = new Uint8Array(await crypto.subtle.digest('SHA-512', new Uint8Array(dpInput)));
|
|
971
|
+
// Create P sequence
|
|
972
|
+
const P = new Uint8Array(passwordBytes.length);
|
|
973
|
+
for (let i = 0; i < passwordBytes.length; i++) {
|
|
974
|
+
P[i] = DP[i % 64];
|
|
975
|
+
}
|
|
976
|
+
// Digest DS (salt repeated)
|
|
977
|
+
const dsInput = [];
|
|
978
|
+
for (let i = 0; i < 16 + A[0]; i++) {
|
|
979
|
+
dsInput.push(...saltBytes);
|
|
980
|
+
}
|
|
981
|
+
const DS = new Uint8Array(await crypto.subtle.digest('SHA-512', new Uint8Array(dsInput)));
|
|
982
|
+
// Create S sequence
|
|
983
|
+
const S = new Uint8Array(saltBytes.length);
|
|
984
|
+
for (let i = 0; i < saltBytes.length; i++) {
|
|
985
|
+
S[i] = DS[i % 64];
|
|
986
|
+
}
|
|
987
|
+
// 5000 rounds
|
|
988
|
+
for (let round = 0; round < 5000; round++) {
|
|
989
|
+
const cInput = [];
|
|
990
|
+
if (round & 1) {
|
|
991
|
+
cInput.push(...P);
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
cInput.push(...A);
|
|
995
|
+
}
|
|
996
|
+
if (round % 3 !== 0) {
|
|
997
|
+
cInput.push(...S);
|
|
998
|
+
}
|
|
999
|
+
if (round % 7 !== 0) {
|
|
1000
|
+
cInput.push(...P);
|
|
1001
|
+
}
|
|
1002
|
+
if (round & 1) {
|
|
1003
|
+
cInput.push(...A);
|
|
1004
|
+
}
|
|
1005
|
+
else {
|
|
1006
|
+
cInput.push(...P);
|
|
1007
|
+
}
|
|
1008
|
+
A = new Uint8Array(await crypto.subtle.digest('SHA-512', new Uint8Array(cInput)));
|
|
1009
|
+
}
|
|
1010
|
+
// Encode result using SHA-512 specific byte order
|
|
1011
|
+
const order = [
|
|
1012
|
+
0, 21, 42, 22, 43, 1, 44, 2, 23, 3, 24, 45,
|
|
1013
|
+
25, 46, 4, 47, 5, 26, 6, 27, 48, 28, 49, 7,
|
|
1014
|
+
50, 8, 29, 9, 30, 51, 31, 52, 10, 53, 11, 32,
|
|
1015
|
+
12, 33, 54, 34, 55, 13, 56, 14, 35, 15, 36, 57,
|
|
1016
|
+
37, 58, 16, 59, 17, 38, 18, 39, 60, 40, 61, 19,
|
|
1017
|
+
62, 20, 41, 63
|
|
1018
|
+
];
|
|
1019
|
+
const encoded = shaCryptBase64(A, order);
|
|
1020
|
+
return `$6$${salt}$${encoded}`;
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Hash a password using SHA-256 crypt algorithm ($5$).
|
|
1024
|
+
*
|
|
1025
|
+
* Implements the SHA-256 variant of the crypt(3) specification used for
|
|
1026
|
+
* Unix password hashing. The output format is `$5$salt$hash`.
|
|
1027
|
+
*
|
|
1028
|
+
* @param password - Plain text password to hash
|
|
1029
|
+
* @param salt - Optional salt (random 16-char salt generated if not provided)
|
|
1030
|
+
* @returns Password hash in format `$5$salt$hash`
|
|
1031
|
+
*
|
|
1032
|
+
* @example
|
|
1033
|
+
* ```ts
|
|
1034
|
+
* await sha256Crypt('mypassword')
|
|
1035
|
+
* // Returns: '$5$<random-salt>$<hash>'
|
|
1036
|
+
* ```
|
|
1037
|
+
*/
|
|
1038
|
+
export async function sha256Crypt(password, salt) {
|
|
1039
|
+
salt = salt || generateSalt(16);
|
|
1040
|
+
salt = salt.slice(0, 16);
|
|
1041
|
+
const passwordBytes = stringToBytes(password);
|
|
1042
|
+
const saltBytes = stringToBytes(salt);
|
|
1043
|
+
// Initial digest: password + salt + password
|
|
1044
|
+
const digestB = await crypto.subtle.digest('SHA-256', new Uint8Array([...passwordBytes, ...saltBytes, ...passwordBytes]));
|
|
1045
|
+
const B = new Uint8Array(digestB);
|
|
1046
|
+
// Digest A
|
|
1047
|
+
const aInput = [...passwordBytes, ...saltBytes];
|
|
1048
|
+
let len = passwordBytes.length;
|
|
1049
|
+
while (len > 0) {
|
|
1050
|
+
const take = Math.min(len, 32);
|
|
1051
|
+
aInput.push(...B.slice(0, take));
|
|
1052
|
+
len -= take;
|
|
1053
|
+
}
|
|
1054
|
+
len = passwordBytes.length;
|
|
1055
|
+
while (len > 0) {
|
|
1056
|
+
if (len & 1) {
|
|
1057
|
+
aInput.push(...B);
|
|
1058
|
+
}
|
|
1059
|
+
else {
|
|
1060
|
+
aInput.push(...passwordBytes);
|
|
1061
|
+
}
|
|
1062
|
+
len >>>= 1;
|
|
1063
|
+
}
|
|
1064
|
+
let A = new Uint8Array(await crypto.subtle.digest('SHA-256', new Uint8Array(aInput)));
|
|
1065
|
+
// Digest DP
|
|
1066
|
+
const dpInput = [];
|
|
1067
|
+
for (let i = 0; i < passwordBytes.length; i++) {
|
|
1068
|
+
dpInput.push(...passwordBytes);
|
|
1069
|
+
}
|
|
1070
|
+
const DP = new Uint8Array(await crypto.subtle.digest('SHA-256', new Uint8Array(dpInput)));
|
|
1071
|
+
const P = new Uint8Array(passwordBytes.length);
|
|
1072
|
+
for (let i = 0; i < passwordBytes.length; i++) {
|
|
1073
|
+
P[i] = DP[i % 32];
|
|
1074
|
+
}
|
|
1075
|
+
// Digest DS
|
|
1076
|
+
const dsInput = [];
|
|
1077
|
+
for (let i = 0; i < 16 + A[0]; i++) {
|
|
1078
|
+
dsInput.push(...saltBytes);
|
|
1079
|
+
}
|
|
1080
|
+
const DS = new Uint8Array(await crypto.subtle.digest('SHA-256', new Uint8Array(dsInput)));
|
|
1081
|
+
const S = new Uint8Array(saltBytes.length);
|
|
1082
|
+
for (let i = 0; i < saltBytes.length; i++) {
|
|
1083
|
+
S[i] = DS[i % 32];
|
|
1084
|
+
}
|
|
1085
|
+
// 5000 rounds
|
|
1086
|
+
for (let round = 0; round < 5000; round++) {
|
|
1087
|
+
const cInput = [];
|
|
1088
|
+
if (round & 1) {
|
|
1089
|
+
cInput.push(...P);
|
|
1090
|
+
}
|
|
1091
|
+
else {
|
|
1092
|
+
cInput.push(...A);
|
|
1093
|
+
}
|
|
1094
|
+
if (round % 3 !== 0) {
|
|
1095
|
+
cInput.push(...S);
|
|
1096
|
+
}
|
|
1097
|
+
if (round % 7 !== 0) {
|
|
1098
|
+
cInput.push(...P);
|
|
1099
|
+
}
|
|
1100
|
+
if (round & 1) {
|
|
1101
|
+
cInput.push(...A);
|
|
1102
|
+
}
|
|
1103
|
+
else {
|
|
1104
|
+
cInput.push(...P);
|
|
1105
|
+
}
|
|
1106
|
+
A = new Uint8Array(await crypto.subtle.digest('SHA-256', new Uint8Array(cInput)));
|
|
1107
|
+
}
|
|
1108
|
+
// SHA-256 specific byte order
|
|
1109
|
+
const order = [
|
|
1110
|
+
0, 10, 20, 21, 1, 11, 12, 22, 2, 3, 13, 23,
|
|
1111
|
+
24, 4, 14, 15, 25, 5, 6, 16, 26, 27, 7, 17,
|
|
1112
|
+
18, 28, 8, 9, 19, 29, 31, 30
|
|
1113
|
+
];
|
|
1114
|
+
const encoded = shaCryptBase64(A, order);
|
|
1115
|
+
return `$5$${salt}$${encoded}`;
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Parse command-line arguments for hash commands.
|
|
1119
|
+
*
|
|
1120
|
+
* @param args - Command-line arguments
|
|
1121
|
+
* @returns Parsed options
|
|
1122
|
+
*/
|
|
1123
|
+
function parseHashCommandArgs(args) {
|
|
1124
|
+
const options = {
|
|
1125
|
+
checkMode: false,
|
|
1126
|
+
bsdStyle: false,
|
|
1127
|
+
binaryMode: false,
|
|
1128
|
+
textMode: false,
|
|
1129
|
+
quiet: false,
|
|
1130
|
+
status: false,
|
|
1131
|
+
warn: false,
|
|
1132
|
+
files: [],
|
|
1133
|
+
};
|
|
1134
|
+
for (let i = 0; i < args.length; i++) {
|
|
1135
|
+
const arg = args[i];
|
|
1136
|
+
switch (arg) {
|
|
1137
|
+
case '-c':
|
|
1138
|
+
case '--check':
|
|
1139
|
+
options.checkMode = true;
|
|
1140
|
+
break;
|
|
1141
|
+
case '--tag':
|
|
1142
|
+
options.bsdStyle = true;
|
|
1143
|
+
break;
|
|
1144
|
+
case '-b':
|
|
1145
|
+
options.binaryMode = true;
|
|
1146
|
+
break;
|
|
1147
|
+
case '-t':
|
|
1148
|
+
options.textMode = true;
|
|
1149
|
+
break;
|
|
1150
|
+
case '--quiet':
|
|
1151
|
+
options.quiet = true;
|
|
1152
|
+
break;
|
|
1153
|
+
case '--status':
|
|
1154
|
+
options.status = true;
|
|
1155
|
+
break;
|
|
1156
|
+
case '--warn':
|
|
1157
|
+
options.warn = true;
|
|
1158
|
+
break;
|
|
1159
|
+
default:
|
|
1160
|
+
if (!arg.startsWith('-')) {
|
|
1161
|
+
options.files.push(arg);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return options;
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Execute sha256sum command.
|
|
1169
|
+
*
|
|
1170
|
+
* Computes SHA-256 hashes for files or stdin, with support for
|
|
1171
|
+
* verification mode (-c) and various output formats.
|
|
1172
|
+
*
|
|
1173
|
+
* @param args - Command-line arguments
|
|
1174
|
+
* @param ctx - Execution context with filesystem and stdin
|
|
1175
|
+
* @returns Command result with stdout, stderr, and exit code
|
|
1176
|
+
*
|
|
1177
|
+
* @example
|
|
1178
|
+
* ```ts
|
|
1179
|
+
* // Hash a file
|
|
1180
|
+
* await executeSha256sum(['/path/to/file'], { fs })
|
|
1181
|
+
*
|
|
1182
|
+
* // Verify checksums
|
|
1183
|
+
* await executeSha256sum(['-c', '/path/to/checksums.txt'], { fs })
|
|
1184
|
+
* ```
|
|
1185
|
+
*/
|
|
1186
|
+
export async function executeSha256sum(args, ctx) {
|
|
1187
|
+
return executeHashCommandWithHasher(getHasher('sha256'), args, ctx);
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Execute sha1sum command.
|
|
1191
|
+
*
|
|
1192
|
+
* Computes SHA-1 hashes for files or stdin.
|
|
1193
|
+
*
|
|
1194
|
+
* @deprecated SHA-1 is cryptographically broken. Use sha256sum for security.
|
|
1195
|
+
*
|
|
1196
|
+
* @param args - Command-line arguments
|
|
1197
|
+
* @param ctx - Execution context
|
|
1198
|
+
* @returns Command result
|
|
1199
|
+
*/
|
|
1200
|
+
export async function executeSha1sum(args, ctx) {
|
|
1201
|
+
return executeHashCommandWithHasher(getHasher('sha1'), args, ctx);
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Execute sha512sum command.
|
|
1205
|
+
*
|
|
1206
|
+
* Computes SHA-512 hashes for files or stdin.
|
|
1207
|
+
*
|
|
1208
|
+
* @param args - Command-line arguments
|
|
1209
|
+
* @param ctx - Execution context
|
|
1210
|
+
* @returns Command result
|
|
1211
|
+
*/
|
|
1212
|
+
export async function executeSha512sum(args, ctx) {
|
|
1213
|
+
return executeHashCommandWithHasher(getHasher('sha512'), args, ctx);
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Execute md5sum command.
|
|
1217
|
+
*
|
|
1218
|
+
* Computes MD5 hashes for files or stdin.
|
|
1219
|
+
*
|
|
1220
|
+
* @deprecated MD5 is cryptographically broken. Use sha256sum for security.
|
|
1221
|
+
*
|
|
1222
|
+
* @param args - Command-line arguments
|
|
1223
|
+
* @param ctx - Execution context
|
|
1224
|
+
* @returns Command result
|
|
1225
|
+
*/
|
|
1226
|
+
export async function executeMd5sum(args, ctx) {
|
|
1227
|
+
return executeHashCommandWithHasher(getHasher('md5'), args, ctx);
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Execute a hash command using the unified Hasher interface.
|
|
1231
|
+
*
|
|
1232
|
+
* This is the core implementation for all hash commands (sha256sum, sha1sum, etc.).
|
|
1233
|
+
* It uses the Hasher interface to support different hash algorithms uniformly.
|
|
1234
|
+
*
|
|
1235
|
+
* @param hasher - Hasher instance for the algorithm
|
|
1236
|
+
* @param args - Command-line arguments
|
|
1237
|
+
* @param ctx - Execution context
|
|
1238
|
+
* @returns Command result
|
|
1239
|
+
*/
|
|
1240
|
+
async function executeHashCommandWithHasher(hasher, args, ctx) {
|
|
1241
|
+
const { config } = hasher;
|
|
1242
|
+
const options = parseHashCommandArgs(args);
|
|
1243
|
+
// Check mode: verify checksums from file
|
|
1244
|
+
if (options.checkMode) {
|
|
1245
|
+
return verifyChecksums(options.files, hasher.hash.bind(hasher), ctx, {
|
|
1246
|
+
quiet: options.quiet,
|
|
1247
|
+
status: options.status,
|
|
1248
|
+
warn: options.warn,
|
|
1249
|
+
});
|
|
1250
|
+
}
|
|
1251
|
+
// Hash mode: compute hashes
|
|
1252
|
+
let stdout = '';
|
|
1253
|
+
let stderr = '';
|
|
1254
|
+
let exitCode = 0;
|
|
1255
|
+
// If no files and stdin provided, hash stdin
|
|
1256
|
+
if (options.files.length === 0 || (options.files.length === 1 && options.files[0] === '-')) {
|
|
1257
|
+
const input = ctx.stdin || '';
|
|
1258
|
+
const hash = await hasher.hash(input);
|
|
1259
|
+
if (options.bsdStyle) {
|
|
1260
|
+
stdout = `${config.tagName} (-) = ${hash}\n`;
|
|
1261
|
+
}
|
|
1262
|
+
else {
|
|
1263
|
+
stdout = `${hash} -\n`;
|
|
1264
|
+
}
|
|
1265
|
+
return { stdout, stderr, exitCode };
|
|
1266
|
+
}
|
|
1267
|
+
// Hash each file
|
|
1268
|
+
for (const file of options.files) {
|
|
1269
|
+
try {
|
|
1270
|
+
if (!ctx.fs) {
|
|
1271
|
+
stderr += `${config.algorithm}sum: ${file}: No filesystem available\n`;
|
|
1272
|
+
exitCode = 1;
|
|
1273
|
+
continue;
|
|
1274
|
+
}
|
|
1275
|
+
const content = await ctx.fs.read(file, { encoding: 'utf-8' });
|
|
1276
|
+
const hash = await hasher.hash(content);
|
|
1277
|
+
if (options.bsdStyle) {
|
|
1278
|
+
stdout += `${config.tagName} (${file}) = ${hash}\n`;
|
|
1279
|
+
}
|
|
1280
|
+
else if (options.binaryMode) {
|
|
1281
|
+
stdout += `${hash} *${file}\n`;
|
|
1282
|
+
}
|
|
1283
|
+
else {
|
|
1284
|
+
stdout += `${hash} ${file}\n`;
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
catch (error) {
|
|
1288
|
+
stderr += `${config.algorithm}sum: ${file}: No such file or directory\n`;
|
|
1289
|
+
exitCode = 1;
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return { stdout, stderr, exitCode };
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Generic hash command executor (legacy).
|
|
1296
|
+
*
|
|
1297
|
+
* @deprecated Use executeHashCommandWithHasher with a Hasher instance instead.
|
|
1298
|
+
*
|
|
1299
|
+
* @param algorithm - Hash algorithm identifier
|
|
1300
|
+
* @param hashLength - Expected hash length in hex characters
|
|
1301
|
+
* @param tagName - Display name for BSD-style output
|
|
1302
|
+
* @param args - Command-line arguments
|
|
1303
|
+
* @param ctx - Execution context
|
|
1304
|
+
* @returns Command result
|
|
1305
|
+
*/
|
|
1306
|
+
async function executeHashCommand(algorithm, _hashLength, tagName, args, ctx) {
|
|
1307
|
+
const hashFn = {
|
|
1308
|
+
md5: md5sum,
|
|
1309
|
+
sha1: sha1sum,
|
|
1310
|
+
sha256: sha256sum,
|
|
1311
|
+
sha384: sha384sum,
|
|
1312
|
+
sha512: sha512sum,
|
|
1313
|
+
}[algorithm];
|
|
1314
|
+
// Parse options
|
|
1315
|
+
let checkMode = false;
|
|
1316
|
+
let bsdStyle = false;
|
|
1317
|
+
let binaryMode = false;
|
|
1318
|
+
let quiet = false;
|
|
1319
|
+
let status = false;
|
|
1320
|
+
let warn = false;
|
|
1321
|
+
const files = [];
|
|
1322
|
+
for (let i = 0; i < args.length; i++) {
|
|
1323
|
+
const arg = args[i];
|
|
1324
|
+
if (arg === '-c' || arg === '--check') {
|
|
1325
|
+
checkMode = true;
|
|
1326
|
+
}
|
|
1327
|
+
else if (arg === '--tag') {
|
|
1328
|
+
bsdStyle = true;
|
|
1329
|
+
}
|
|
1330
|
+
else if (arg === '-b') {
|
|
1331
|
+
binaryMode = true;
|
|
1332
|
+
}
|
|
1333
|
+
else if (arg === '-t') {
|
|
1334
|
+
// Text mode - no-op since we treat all input as text
|
|
1335
|
+
}
|
|
1336
|
+
else if (arg === '--quiet') {
|
|
1337
|
+
quiet = true;
|
|
1338
|
+
}
|
|
1339
|
+
else if (arg === '--status') {
|
|
1340
|
+
status = true;
|
|
1341
|
+
}
|
|
1342
|
+
else if (arg === '--warn') {
|
|
1343
|
+
warn = true;
|
|
1344
|
+
}
|
|
1345
|
+
else if (!arg.startsWith('-')) {
|
|
1346
|
+
files.push(arg);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
// Check mode: verify checksums from file
|
|
1350
|
+
if (checkMode) {
|
|
1351
|
+
return verifyChecksums(files, hashFn, ctx, { quiet, status, warn });
|
|
1352
|
+
}
|
|
1353
|
+
// Hash mode: compute hashes
|
|
1354
|
+
let stdout = '';
|
|
1355
|
+
let stderr = '';
|
|
1356
|
+
let exitCode = 0;
|
|
1357
|
+
// If no files and stdin provided, hash stdin
|
|
1358
|
+
if (files.length === 0 || (files.length === 1 && files[0] === '-')) {
|
|
1359
|
+
const input = ctx.stdin || '';
|
|
1360
|
+
const hash = await hashFn(input);
|
|
1361
|
+
if (bsdStyle) {
|
|
1362
|
+
stdout = `${tagName} (-) = ${hash}\n`;
|
|
1363
|
+
}
|
|
1364
|
+
else {
|
|
1365
|
+
stdout = `${hash} -\n`;
|
|
1366
|
+
}
|
|
1367
|
+
return { stdout, stderr, exitCode };
|
|
1368
|
+
}
|
|
1369
|
+
// Hash each file
|
|
1370
|
+
for (const file of files) {
|
|
1371
|
+
try {
|
|
1372
|
+
if (!ctx.fs) {
|
|
1373
|
+
stderr += `${algorithm}sum: ${file}: No filesystem available\n`;
|
|
1374
|
+
exitCode = 1;
|
|
1375
|
+
continue;
|
|
1376
|
+
}
|
|
1377
|
+
const content = await ctx.fs.read(file, { encoding: 'utf-8' });
|
|
1378
|
+
const hash = await hashFn(content);
|
|
1379
|
+
if (bsdStyle) {
|
|
1380
|
+
stdout += `${tagName} (${file}) = ${hash}\n`;
|
|
1381
|
+
}
|
|
1382
|
+
else if (binaryMode) {
|
|
1383
|
+
stdout += `${hash} *${file}\n`;
|
|
1384
|
+
}
|
|
1385
|
+
else {
|
|
1386
|
+
stdout += `${hash} ${file}\n`;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
catch {
|
|
1390
|
+
stderr += `${algorithm}sum: ${file}: No such file or directory\n`;
|
|
1391
|
+
exitCode = 1;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
return { stdout, stderr, exitCode };
|
|
1395
|
+
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Verify checksums from a file
|
|
1398
|
+
*/
|
|
1399
|
+
async function verifyChecksums(files, hashFn, ctx, options) {
|
|
1400
|
+
let stdout = '';
|
|
1401
|
+
let stderr = '';
|
|
1402
|
+
let exitCode = 0;
|
|
1403
|
+
let failures = 0;
|
|
1404
|
+
let validLinesProcessed = 0;
|
|
1405
|
+
if (!ctx.fs || files.length === 0) {
|
|
1406
|
+
return { stdout: '', stderr: 'No checksum file specified\n', exitCode: 1 };
|
|
1407
|
+
}
|
|
1408
|
+
for (const checksumFile of files) {
|
|
1409
|
+
try {
|
|
1410
|
+
const content = await ctx.fs.read(checksumFile, { encoding: 'utf-8' });
|
|
1411
|
+
const lines = content.trim().split('\n');
|
|
1412
|
+
let malformedCount = 0;
|
|
1413
|
+
for (const line of lines) {
|
|
1414
|
+
// Parse checksum line: "hash filename" or "hash *filename"
|
|
1415
|
+
const match = line.match(/^([a-f0-9]+)\s+[\s*]?(.+)$/);
|
|
1416
|
+
if (!match) {
|
|
1417
|
+
malformedCount++;
|
|
1418
|
+
if (options.warn) {
|
|
1419
|
+
stderr += `${checksumFile}: improperly formatted checksum line\n`;
|
|
1420
|
+
}
|
|
1421
|
+
continue;
|
|
1422
|
+
}
|
|
1423
|
+
validLinesProcessed++;
|
|
1424
|
+
const [, expectedHash, filename] = match;
|
|
1425
|
+
try {
|
|
1426
|
+
const fileContent = await ctx.fs.read(filename, { encoding: 'utf-8' });
|
|
1427
|
+
const actualHash = await hashFn(fileContent);
|
|
1428
|
+
if (actualHash === expectedHash) {
|
|
1429
|
+
if (!options.quiet && !options.status) {
|
|
1430
|
+
stdout += `${filename}: OK\n`;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
else {
|
|
1434
|
+
failures++;
|
|
1435
|
+
if (!options.status) {
|
|
1436
|
+
stdout += `${filename}: FAILED\n`;
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
catch {
|
|
1441
|
+
failures++;
|
|
1442
|
+
if (!options.status) {
|
|
1443
|
+
stdout += `${filename}: FAILED open or read\n`;
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
// If all lines were malformed, report error
|
|
1448
|
+
if (validLinesProcessed === 0 && malformedCount > 0) {
|
|
1449
|
+
stderr += `${checksumFile}: no properly formatted checksum lines found\n`;
|
|
1450
|
+
exitCode = 1;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
catch (error) {
|
|
1454
|
+
stderr += `Cannot read ${checksumFile}\n`;
|
|
1455
|
+
exitCode = 1;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
if (failures > 0) {
|
|
1459
|
+
exitCode = 1;
|
|
1460
|
+
}
|
|
1461
|
+
return { stdout, stderr, exitCode };
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Execute uuidgen command
|
|
1465
|
+
*/
|
|
1466
|
+
export async function executeUuidgen(args) {
|
|
1467
|
+
let version = 4;
|
|
1468
|
+
let count = 1;
|
|
1469
|
+
let uppercase = false;
|
|
1470
|
+
for (let i = 0; i < args.length; i++) {
|
|
1471
|
+
const arg = args[i];
|
|
1472
|
+
if (arg === '-r' || arg === '--random') {
|
|
1473
|
+
version = 4;
|
|
1474
|
+
}
|
|
1475
|
+
else if (arg === '-t' || arg === '--time') {
|
|
1476
|
+
version = 1;
|
|
1477
|
+
}
|
|
1478
|
+
else if (arg === '-n' && args[i + 1]) {
|
|
1479
|
+
count = parseInt(args[++i], 10);
|
|
1480
|
+
}
|
|
1481
|
+
else if (arg === '-u') {
|
|
1482
|
+
uppercase = true;
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
let stdout = '';
|
|
1486
|
+
for (let i = 0; i < count; i++) {
|
|
1487
|
+
let uuid;
|
|
1488
|
+
if (version === 1) {
|
|
1489
|
+
uuid = uuidv1();
|
|
1490
|
+
}
|
|
1491
|
+
else {
|
|
1492
|
+
uuid = uuidv4();
|
|
1493
|
+
}
|
|
1494
|
+
if (uppercase) {
|
|
1495
|
+
uuid = uuid.toUpperCase();
|
|
1496
|
+
}
|
|
1497
|
+
stdout += uuid + '\n';
|
|
1498
|
+
}
|
|
1499
|
+
return { stdout, stderr: '', exitCode: 0 };
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Execute uuid command
|
|
1503
|
+
*/
|
|
1504
|
+
export async function executeUuid(args) {
|
|
1505
|
+
let version = 4;
|
|
1506
|
+
let namespace;
|
|
1507
|
+
let name;
|
|
1508
|
+
for (let i = 0; i < args.length; i++) {
|
|
1509
|
+
const arg = args[i];
|
|
1510
|
+
if ((arg === '-v' || arg === '--version') && args[i + 1]) {
|
|
1511
|
+
const v = parseInt(args[++i], 10);
|
|
1512
|
+
if (![1, 3, 4, 5].includes(v)) {
|
|
1513
|
+
return { stdout: '', stderr: `uuid: invalid version: ${v}\n`, exitCode: 1 };
|
|
1514
|
+
}
|
|
1515
|
+
version = v;
|
|
1516
|
+
}
|
|
1517
|
+
else if (arg === '--nil') {
|
|
1518
|
+
return { stdout: uuidNil() + '\n', stderr: '', exitCode: 0 };
|
|
1519
|
+
}
|
|
1520
|
+
else if (!arg.startsWith('-')) {
|
|
1521
|
+
if (!namespace) {
|
|
1522
|
+
namespace = arg;
|
|
1523
|
+
}
|
|
1524
|
+
else if (!name) {
|
|
1525
|
+
name = arg;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
// For v3 and v5, we need namespace and name
|
|
1530
|
+
if ((version === 3 || version === 5) && (!namespace || !name)) {
|
|
1531
|
+
return {
|
|
1532
|
+
stdout: '',
|
|
1533
|
+
stderr: `uuid: version ${version} requires namespace and name\n`,
|
|
1534
|
+
exitCode: 1,
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
try {
|
|
1538
|
+
let uuid;
|
|
1539
|
+
switch (version) {
|
|
1540
|
+
case 1:
|
|
1541
|
+
uuid = uuidv1();
|
|
1542
|
+
break;
|
|
1543
|
+
case 3:
|
|
1544
|
+
uuid = await uuidv3(resolveNamespace(namespace), name);
|
|
1545
|
+
break;
|
|
1546
|
+
case 4:
|
|
1547
|
+
uuid = uuidv4();
|
|
1548
|
+
break;
|
|
1549
|
+
case 5:
|
|
1550
|
+
uuid = await uuidv5(resolveNamespace(namespace), name);
|
|
1551
|
+
break;
|
|
1552
|
+
default:
|
|
1553
|
+
return { stdout: '', stderr: `uuid: unsupported version: ${version}\n`, exitCode: 1 };
|
|
1554
|
+
}
|
|
1555
|
+
return { stdout: uuid + '\n', stderr: '', exitCode: 0 };
|
|
1556
|
+
}
|
|
1557
|
+
catch (error) {
|
|
1558
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1559
|
+
return { stdout: '', stderr: `uuid: ${message}\n`, exitCode: 1 };
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Resolve namespace alias or UUID
|
|
1564
|
+
*/
|
|
1565
|
+
function resolveNamespace(ns) {
|
|
1566
|
+
if (ns.startsWith('ns:')) {
|
|
1567
|
+
const name = ns.slice(3).toUpperCase();
|
|
1568
|
+
if (UUID_NAMESPACES[name]) {
|
|
1569
|
+
return UUID_NAMESPACES[name];
|
|
1570
|
+
}
|
|
1571
|
+
throw new Error(`Unknown namespace: ${ns}`);
|
|
1572
|
+
}
|
|
1573
|
+
// Assume it's a UUID string
|
|
1574
|
+
return ns;
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Execute cksum command
|
|
1578
|
+
*/
|
|
1579
|
+
export async function executeCksum(args, ctx) {
|
|
1580
|
+
const files = args.filter(a => !a.startsWith('-'));
|
|
1581
|
+
let stdout = '';
|
|
1582
|
+
let stderr = '';
|
|
1583
|
+
let exitCode = 0;
|
|
1584
|
+
// If no files, use stdin
|
|
1585
|
+
if (files.length === 0) {
|
|
1586
|
+
const input = stringToBytes(ctx.stdin || '');
|
|
1587
|
+
const crc = crc32(input);
|
|
1588
|
+
stdout = `${crc} ${input.length}\n`;
|
|
1589
|
+
return { stdout, stderr, exitCode };
|
|
1590
|
+
}
|
|
1591
|
+
for (const file of files) {
|
|
1592
|
+
try {
|
|
1593
|
+
if (!ctx.fs) {
|
|
1594
|
+
stderr += `cksum: ${file}: No filesystem available\n`;
|
|
1595
|
+
exitCode = 1;
|
|
1596
|
+
continue;
|
|
1597
|
+
}
|
|
1598
|
+
const content = await ctx.fs.read(file, { encoding: 'utf-8' });
|
|
1599
|
+
const data = stringToBytes(content);
|
|
1600
|
+
const crc = crc32(data);
|
|
1601
|
+
stdout += `${crc} ${data.length} ${file}\n`;
|
|
1602
|
+
}
|
|
1603
|
+
catch (error) {
|
|
1604
|
+
stderr += `cksum: ${file}: No such file or directory\n`;
|
|
1605
|
+
exitCode = 1;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
return { stdout, stderr, exitCode };
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Execute sum command
|
|
1612
|
+
*/
|
|
1613
|
+
export async function executeSum(args, ctx) {
|
|
1614
|
+
let useSysv = false;
|
|
1615
|
+
const files = [];
|
|
1616
|
+
for (const arg of args) {
|
|
1617
|
+
if (arg === '-s' || arg === '--sysv') {
|
|
1618
|
+
useSysv = true;
|
|
1619
|
+
}
|
|
1620
|
+
else if (arg === '-r') {
|
|
1621
|
+
useSysv = false; // BSD is default
|
|
1622
|
+
}
|
|
1623
|
+
else if (!arg.startsWith('-')) {
|
|
1624
|
+
files.push(arg);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
const sumFn = useSysv ? sysvSum : bsdSum;
|
|
1628
|
+
let stdout = '';
|
|
1629
|
+
let stderr = '';
|
|
1630
|
+
let exitCode = 0;
|
|
1631
|
+
// If no files, use stdin
|
|
1632
|
+
if (files.length === 0) {
|
|
1633
|
+
const input = stringToBytes(ctx.stdin || '');
|
|
1634
|
+
const { checksum, blocks } = sumFn(input);
|
|
1635
|
+
stdout = `${checksum} ${blocks}\n`;
|
|
1636
|
+
return { stdout, stderr, exitCode };
|
|
1637
|
+
}
|
|
1638
|
+
for (const file of files) {
|
|
1639
|
+
try {
|
|
1640
|
+
if (!ctx.fs) {
|
|
1641
|
+
stderr += `sum: ${file}: No filesystem available\n`;
|
|
1642
|
+
exitCode = 1;
|
|
1643
|
+
continue;
|
|
1644
|
+
}
|
|
1645
|
+
const content = await ctx.fs.read(file, { encoding: 'utf-8' });
|
|
1646
|
+
const data = stringToBytes(content);
|
|
1647
|
+
const { checksum, blocks } = sumFn(data);
|
|
1648
|
+
stdout += `${checksum} ${blocks} ${file}\n`;
|
|
1649
|
+
}
|
|
1650
|
+
catch (error) {
|
|
1651
|
+
stderr += `sum: ${file}: No such file or directory\n`;
|
|
1652
|
+
exitCode = 1;
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
return { stdout, stderr, exitCode };
|
|
1656
|
+
}
|
|
1657
|
+
/**
|
|
1658
|
+
* Execute openssl command
|
|
1659
|
+
*/
|
|
1660
|
+
export async function executeOpenssl(args, ctx) {
|
|
1661
|
+
if (args.length === 0) {
|
|
1662
|
+
return { stdout: '', stderr: 'openssl: missing command\n', exitCode: 1 };
|
|
1663
|
+
}
|
|
1664
|
+
const subcommand = args[0];
|
|
1665
|
+
const subArgs = args.slice(1);
|
|
1666
|
+
switch (subcommand) {
|
|
1667
|
+
case 'dgst':
|
|
1668
|
+
return executeOpensslDgst(subArgs, ctx);
|
|
1669
|
+
case 'enc':
|
|
1670
|
+
return executeOpensslEnc(subArgs, ctx);
|
|
1671
|
+
case 'rand':
|
|
1672
|
+
return executeOpensslRand(subArgs);
|
|
1673
|
+
case 'passwd':
|
|
1674
|
+
return executeOpensslPasswd(subArgs, ctx);
|
|
1675
|
+
default:
|
|
1676
|
+
return { stdout: '', stderr: `openssl: unknown command: ${subcommand}\n`, exitCode: 1 };
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
/**
|
|
1680
|
+
* Execute openssl dgst command
|
|
1681
|
+
*/
|
|
1682
|
+
async function executeOpensslDgst(args, ctx) {
|
|
1683
|
+
let algorithm = 'sha256';
|
|
1684
|
+
let reverseFormat = false;
|
|
1685
|
+
const files = [];
|
|
1686
|
+
for (let i = 0; i < args.length; i++) {
|
|
1687
|
+
const arg = args[i];
|
|
1688
|
+
if (arg === '-sha256') {
|
|
1689
|
+
algorithm = 'sha256';
|
|
1690
|
+
}
|
|
1691
|
+
else if (arg === '-sha1') {
|
|
1692
|
+
algorithm = 'sha1';
|
|
1693
|
+
}
|
|
1694
|
+
else if (arg === '-sha512') {
|
|
1695
|
+
algorithm = 'sha512';
|
|
1696
|
+
}
|
|
1697
|
+
else if (arg === '-md5') {
|
|
1698
|
+
algorithm = 'md5';
|
|
1699
|
+
}
|
|
1700
|
+
else if (arg === '-r') {
|
|
1701
|
+
reverseFormat = true;
|
|
1702
|
+
}
|
|
1703
|
+
else if (arg === '-hex') {
|
|
1704
|
+
// Default format, ignore
|
|
1705
|
+
}
|
|
1706
|
+
else if (arg.startsWith('-')) {
|
|
1707
|
+
if (!['sha256', 'sha1', 'sha512', 'md5', 'sha384'].includes(arg.slice(1))) {
|
|
1708
|
+
return { stdout: '', stderr: `openssl dgst: unknown option or digest: ${arg}\n`, exitCode: 1 };
|
|
1709
|
+
}
|
|
1710
|
+
algorithm = arg.slice(1);
|
|
1711
|
+
}
|
|
1712
|
+
else {
|
|
1713
|
+
files.push(arg);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
const hashFn = {
|
|
1717
|
+
md5: md5sum,
|
|
1718
|
+
sha1: sha1sum,
|
|
1719
|
+
sha256: sha256sum,
|
|
1720
|
+
sha384: sha384sum,
|
|
1721
|
+
sha512: sha512sum,
|
|
1722
|
+
}[algorithm];
|
|
1723
|
+
if (!hashFn) {
|
|
1724
|
+
return { stdout: '', stderr: `openssl dgst: unknown digest: ${algorithm}\n`, exitCode: 1 };
|
|
1725
|
+
}
|
|
1726
|
+
const tagName = {
|
|
1727
|
+
md5: 'MD5',
|
|
1728
|
+
sha1: 'SHA1',
|
|
1729
|
+
sha256: 'SHA2-256',
|
|
1730
|
+
sha384: 'SHA2-384',
|
|
1731
|
+
sha512: 'SHA2-512',
|
|
1732
|
+
}[algorithm];
|
|
1733
|
+
let stdout = '';
|
|
1734
|
+
let stderr = '';
|
|
1735
|
+
let exitCode = 0;
|
|
1736
|
+
// If no files, use stdin
|
|
1737
|
+
if (files.length === 0) {
|
|
1738
|
+
const input = ctx.stdin || '';
|
|
1739
|
+
const hash = await hashFn(input);
|
|
1740
|
+
if (reverseFormat) {
|
|
1741
|
+
stdout = `${hash} *stdin\n`;
|
|
1742
|
+
}
|
|
1743
|
+
else {
|
|
1744
|
+
stdout = `${tagName}(stdin)= ${hash}\n`;
|
|
1745
|
+
}
|
|
1746
|
+
return { stdout, stderr, exitCode };
|
|
1747
|
+
}
|
|
1748
|
+
for (const file of files) {
|
|
1749
|
+
try {
|
|
1750
|
+
if (!ctx.fs) {
|
|
1751
|
+
stderr += `openssl dgst: ${file}: No filesystem available\n`;
|
|
1752
|
+
exitCode = 1;
|
|
1753
|
+
continue;
|
|
1754
|
+
}
|
|
1755
|
+
const content = await ctx.fs.read(file, { encoding: 'utf-8' });
|
|
1756
|
+
const hash = await hashFn(content);
|
|
1757
|
+
if (reverseFormat) {
|
|
1758
|
+
stdout += `${hash} *${file}\n`;
|
|
1759
|
+
}
|
|
1760
|
+
else {
|
|
1761
|
+
stdout += `${tagName}(${file})= ${hash}\n`;
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
catch (error) {
|
|
1765
|
+
stderr += `openssl dgst: ${file}: No such file or directory\n`;
|
|
1766
|
+
exitCode = 1;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
return { stdout, stderr, exitCode };
|
|
1770
|
+
}
|
|
1771
|
+
/**
|
|
1772
|
+
* Execute openssl enc command (base64 encoding/decoding)
|
|
1773
|
+
*/
|
|
1774
|
+
async function executeOpensslEnc(args, ctx) {
|
|
1775
|
+
let decode = false;
|
|
1776
|
+
let singleLine = false;
|
|
1777
|
+
let inputFile;
|
|
1778
|
+
for (let i = 0; i < args.length; i++) {
|
|
1779
|
+
const arg = args[i];
|
|
1780
|
+
if (arg === '-d' || arg === '-decode') {
|
|
1781
|
+
decode = true;
|
|
1782
|
+
}
|
|
1783
|
+
else if (arg === '-A') {
|
|
1784
|
+
singleLine = true;
|
|
1785
|
+
}
|
|
1786
|
+
else if (arg === '-in' && args[i + 1]) {
|
|
1787
|
+
inputFile = args[++i];
|
|
1788
|
+
}
|
|
1789
|
+
else if (arg === '-base64') {
|
|
1790
|
+
// Default, ignore
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
let input;
|
|
1794
|
+
if (inputFile) {
|
|
1795
|
+
if (!ctx.fs) {
|
|
1796
|
+
return { stdout: '', stderr: 'openssl enc: No filesystem available\n', exitCode: 1 };
|
|
1797
|
+
}
|
|
1798
|
+
try {
|
|
1799
|
+
input = await ctx.fs.read(inputFile, { encoding: 'utf-8' });
|
|
1800
|
+
}
|
|
1801
|
+
catch {
|
|
1802
|
+
return { stdout: '', stderr: `openssl enc: ${inputFile}: No such file\n`, exitCode: 1 };
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
else {
|
|
1806
|
+
input = ctx.stdin || '';
|
|
1807
|
+
}
|
|
1808
|
+
try {
|
|
1809
|
+
let output;
|
|
1810
|
+
if (decode) {
|
|
1811
|
+
// Base64 decode
|
|
1812
|
+
const cleaned = input.replace(/\s/g, '');
|
|
1813
|
+
output = atob(cleaned);
|
|
1814
|
+
}
|
|
1815
|
+
else {
|
|
1816
|
+
// Base64 encode
|
|
1817
|
+
output = btoa(input);
|
|
1818
|
+
if (!singleLine && output.length > 64) {
|
|
1819
|
+
// Wrap at 64 characters
|
|
1820
|
+
output = output.match(/.{1,64}/g)?.join('\n') || output;
|
|
1821
|
+
}
|
|
1822
|
+
}
|
|
1823
|
+
return { stdout: output + (decode ? '' : '\n'), stderr: '', exitCode: 0 };
|
|
1824
|
+
}
|
|
1825
|
+
catch (error) {
|
|
1826
|
+
return { stdout: '', stderr: 'openssl enc: error encoding/decoding\n', exitCode: 1 };
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Execute openssl rand command
|
|
1831
|
+
*/
|
|
1832
|
+
async function executeOpensslRand(args) {
|
|
1833
|
+
let format = 'hex';
|
|
1834
|
+
let numBytes = 0;
|
|
1835
|
+
for (let i = 0; i < args.length; i++) {
|
|
1836
|
+
const arg = args[i];
|
|
1837
|
+
if (arg === '-hex') {
|
|
1838
|
+
format = 'hex';
|
|
1839
|
+
}
|
|
1840
|
+
else if (arg === '-base64') {
|
|
1841
|
+
format = 'base64';
|
|
1842
|
+
}
|
|
1843
|
+
else if (!arg.startsWith('-') || /^-\d+$/.test(arg)) {
|
|
1844
|
+
const n = parseInt(arg, 10);
|
|
1845
|
+
if (isNaN(n)) {
|
|
1846
|
+
return { stdout: '', stderr: `openssl rand: invalid number: ${arg}\n`, exitCode: 1 };
|
|
1847
|
+
}
|
|
1848
|
+
if (n < 0) {
|
|
1849
|
+
return { stdout: '', stderr: 'openssl rand: invalid count\n', exitCode: 1 };
|
|
1850
|
+
}
|
|
1851
|
+
numBytes = n;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
if (numBytes === 0) {
|
|
1855
|
+
return { stdout: '\n', stderr: '', exitCode: 0 };
|
|
1856
|
+
}
|
|
1857
|
+
const result = randomBytes(numBytes, format);
|
|
1858
|
+
return { stdout: result + '\n', stderr: '', exitCode: 0 };
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Execute openssl passwd command
|
|
1862
|
+
*/
|
|
1863
|
+
async function executeOpensslPasswd(args, ctx) {
|
|
1864
|
+
let algorithm = '6';
|
|
1865
|
+
let salt;
|
|
1866
|
+
let useStdin = false;
|
|
1867
|
+
let password;
|
|
1868
|
+
for (let i = 0; i < args.length; i++) {
|
|
1869
|
+
const arg = args[i];
|
|
1870
|
+
if (arg === '-5') {
|
|
1871
|
+
algorithm = '5';
|
|
1872
|
+
}
|
|
1873
|
+
else if (arg === '-6') {
|
|
1874
|
+
algorithm = '6';
|
|
1875
|
+
}
|
|
1876
|
+
else if (arg === '-salt' && args[i + 1]) {
|
|
1877
|
+
salt = args[++i];
|
|
1878
|
+
}
|
|
1879
|
+
else if (arg === '-stdin') {
|
|
1880
|
+
useStdin = true;
|
|
1881
|
+
}
|
|
1882
|
+
else if (!arg.startsWith('-')) {
|
|
1883
|
+
password = arg;
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
if (useStdin) {
|
|
1887
|
+
password = (ctx.stdin || '').trim();
|
|
1888
|
+
}
|
|
1889
|
+
if (!password) {
|
|
1890
|
+
return { stdout: '', stderr: 'openssl passwd: password required\n', exitCode: 1 };
|
|
1891
|
+
}
|
|
1892
|
+
try {
|
|
1893
|
+
let hash;
|
|
1894
|
+
if (algorithm === '5') {
|
|
1895
|
+
hash = await sha256Crypt(password, salt);
|
|
1896
|
+
}
|
|
1897
|
+
else {
|
|
1898
|
+
hash = await sha512Crypt(password, salt);
|
|
1899
|
+
}
|
|
1900
|
+
return { stdout: hash + '\n', stderr: '', exitCode: 0 };
|
|
1901
|
+
}
|
|
1902
|
+
catch (error) {
|
|
1903
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1904
|
+
return { stdout: '', stderr: `openssl passwd: ${message}\n`, exitCode: 1 };
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
// ============================================================================
|
|
1908
|
+
// COMMAND LIST FOR TIER 1 REGISTRATION
|
|
1909
|
+
// ============================================================================
|
|
1910
|
+
/**
|
|
1911
|
+
* List of crypto commands for Tier 1 native execution
|
|
1912
|
+
*/
|
|
1913
|
+
export const CRYPTO_COMMANDS = new Set([
|
|
1914
|
+
'sha256sum',
|
|
1915
|
+
'sha1sum',
|
|
1916
|
+
'sha512sum',
|
|
1917
|
+
'sha384sum',
|
|
1918
|
+
'md5sum',
|
|
1919
|
+
'uuidgen',
|
|
1920
|
+
'uuid',
|
|
1921
|
+
'cksum',
|
|
1922
|
+
'sum',
|
|
1923
|
+
'openssl',
|
|
1924
|
+
]);
|
|
1925
|
+
/**
|
|
1926
|
+
* Execute a crypto command
|
|
1927
|
+
*/
|
|
1928
|
+
export async function executeCryptoCommand(cmd, args, ctx) {
|
|
1929
|
+
switch (cmd) {
|
|
1930
|
+
case 'sha256sum':
|
|
1931
|
+
return executeSha256sum(args, ctx);
|
|
1932
|
+
case 'sha1sum':
|
|
1933
|
+
return executeSha1sum(args, ctx);
|
|
1934
|
+
case 'sha512sum':
|
|
1935
|
+
return executeSha512sum(args, ctx);
|
|
1936
|
+
case 'sha384sum':
|
|
1937
|
+
return executeHashCommand('sha384', 96, 'SHA384', args, ctx);
|
|
1938
|
+
case 'md5sum':
|
|
1939
|
+
return executeMd5sum(args, ctx);
|
|
1940
|
+
case 'uuidgen':
|
|
1941
|
+
return executeUuidgen(args);
|
|
1942
|
+
case 'uuid':
|
|
1943
|
+
return executeUuid(args);
|
|
1944
|
+
case 'cksum':
|
|
1945
|
+
return executeCksum(args, ctx);
|
|
1946
|
+
case 'sum':
|
|
1947
|
+
return executeSum(args, ctx);
|
|
1948
|
+
case 'openssl':
|
|
1949
|
+
return executeOpenssl(args, ctx);
|
|
1950
|
+
default:
|
|
1951
|
+
return { stdout: '', stderr: `Unknown crypto command: ${cmd}\n`, exitCode: 1 };
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
//# sourceMappingURL=crypto.js.map
|