NodeCrypt
Run ephemeral browser chat rooms on Workers and SQLite Durable Objects.
NodeCrypt is a self-hosted Discord/Slack alternative built on Cloudflare (Durable Objects, Workers). Free tier eligible within limits. Inspect the source and license in the linked repository.
Source & license
Upstream license: ISC
License TL;DR
You can use, change, self-host and distribute it, with or without charging money. Keep the original copyright and permission notice with copies. You don’t have to publish your changes. The authors don’t provide a warranty.
Explain ISC in plain English →Summary of the main license. Separate packages and assets can have different terms.
Inspect repository ↗Read this project’s actual license ↗Repository owner
See the upstream repository for the original creator and contributors.
Maintain this project? Maintainer verification →Cloudflare hosting
Free tier eligible within limits
The documented NodeCrypt deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs.
Hosting requirements
- Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits.
- Use the configured SQLite Durable Object classes within 100,000 requests/day, 13,000 GB-s duration/day, 5 million SQL rows read/day, 100,000 written/day and 5 GB storage; active sockets consume duration.
- Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations.
Sources checked 01/10/2026
Repository snapshot: 54ed049. Hosting eligibility reflects the deployment documentation and listed assumptions.
- slack ↗
点击下方按钮即可一键部署到 Cloudflare Workers: [](https://deploy.workers.cloudflare.com/?url=https://github.com/shuaiplus/nodecrypt)
- discord ↗
点击下方按钮即可一键部署到 Cloudflare Workers: [](https://deploy.workers.cloudflare.com/?url=https://github.com/shuaiplus/nodecrypt)
- workers ↗
name = "nodecrypt" main = "worker/index.js" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat"] # 配置静态资源 [assets] directory = "./dist" not_found_handling = "single-page-application" run_worker_first = true binding = "ASSETS" [durable_objects] bindings = [ { name = "CHAT_ROOM", class_name = "ChatRoom" } ] [[migrations]] tag = "v1" new_sqlite_cla
- durable-objects ↗
tory = "./dist" not_found_handling = "single-page-application" run_worker_first = true binding = "ASSETS" [durable_objects] bindings = [ { name = "CHAT_ROOM", class_name = "ChatRoom" } ] [[migrations]] tag = "v1" new_sqlite_classes = ["ChatRoom"]
- free-tier-eligible ↗
name = "nodecrypt" main = "worker/index.js" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat"] # 配置静态资源 [assets] directory = "./dist" not_found_handling = "single-page-application" run_worker_first = true binding = "ASSETS" [durable_objects] bindings = [ { name = "CHAT_ROOM", class_name = "ChatRoom" } ] [[migrations]] tag = "v1" new_sqlite_cla
- free-tier-eligible ↗
tory = "./dist" not_found_handling = "single-page-application" run_worker_first = true binding = "ASSETS" [durable_objects] bindings = [ { name = "CHAT_ROOM", class_name = "ChatRoom" } ] [[migrations]] tag = "v1" new_sqlite_classes = ["ChatRoom"]
- free-tier-eligible ↗
up>1, 2, 3, 4</sup> | Duration | CPU time | | --- | --- | --- | --- | | **Free** | 100,000 per day | No charge for duration | 10 milliseconds of CPU time per invocation | | **Standard** | 10 million included per month <br> +$0.30 per additional million | No charge or limit for duration | 30 million CPU milliseconds included per month<br> +$0.02 per additional million CPU milliseconds<br><br> Max of [5 minutes of CPU time](https://developers.cloudflare.com/workers/platform/limits/#account-plan-limits) per invocation (default: 30 seconds)<br> Max of 15 minutes of CPU time per [Cron Trigger](https://developers.cloudflare.com/workers/configuration/cron-triggers/) or [Queue Consumer](https://developers.cloudflare.co
- free-tier-eligible ↗
jects are available both on Workers Free and Workers Paid plans. - **Workers Free plan**: Only Durable Objects with [SQLite storage backend](https://developers.cloudflare.com/durable-objects/best-practices/access-durable-objects-storage/#create-sqlite-backed-durable-object-class) are available. - **Workers Paid plan**: Durable Objects with the SQLite storage backend are available. The [key-value storage backend](https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/#storage-backends) is only available to accounts that already have a key-value-backed namespace. If you wish to downgrade from a Workers Paid plan to a Workers Free plan, you must first ensure that you have deleted all Durable Object namespaces with the key-value storage backend. On Workers Free plan: - If you exceed any one of the free tier limits, further operations of that type will fail with an error. - Daily free limits reset at 00:00 UTC. ## Compute billing Durable Objects are billed for compute duration (wall-clock time) while the Durable Object is actively running or is idle in memory but unable to [hibernate](https://developers.cloudflare.com/durable-objects/concepts/durable-object-lifecycle/). Durable Objects that are idle and eligible for hibernation are not billed for duration, even before the runtime has hibernated them. Requests to a D
- free-tier-eligible ↗
billed accordingly. | | Free plan | Paid plan | | --- | --- | --- | | Requests | 100,000 / day | 1 million / month, + $0.15/million<br> Includes HTTP requests, RPC sessions<sup>1</sup>, WebSocket messages<sup>2</sup>, and alarm invocations | | Duration<sup>3</sup> | 13,000 GB-s / day | 400,000 GB-s / month, + $12.50/million GB-s<sup>4,5</sup> | <details> <summary> Footnotes </summary> <sup>1</sup> Each <a href="https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/">RPC session</a> is billed as one request to your Durable Object. Every <a href="https://developers.cloudflare.com/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/">RPC method call</a> on a <a href="https://developers.cloudflare.com/durable-objects/">Durable Objects stub</a> is its own RPC session and therefore a single billed request. RPC method calls can return objects (stubs) extending <a href="https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/#lifetimes-memory-and-resource-management"><code>RpcTarget</code></a> and invo
- free-tier-eligible ↗
/). | | Workers Free plan | Workers Paid plan | | --- | --- | --- | | Rows reads <sup>1,2</sup> | 5 million / day | First 25 billion / month included + $0.001 / million rows | | Rows written <sup>1,2,3,4</sup> | 100,000 / day | First 50 million / month included + $1.00 / million rows | | SQL Stored data <sup>5</sup> | 5 GB (total) | 5 GB-month, + $0.20/ GB-month | <details> <summary> Footnotes </summary> <sup>1</sup> Rows read and rows written included limits and rates match <a href="https://developers.cloudflare.com/d1/platform/pricing/">D1 pricing</a>, Cloudflare's serverless SQL database. <sup>2</sup> Key-value methods like <code>get()</code>, <code>put()</code>, <code>delete()</code>, or <code>list(
- ISC ↗
ISC License Copyright (c) 2024, NodeCrypt Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- architecture ↗
name = "nodecrypt" main = "worker/index.js" compatibility_date = "2024-09-23" compatibility_flags = ["nodejs_compat"] # 配置静态资源 [assets] directory = "./dist" not_found_handling = "single-page-application" run_worker_first = true binding = "ASSETS" [durable_objects] bindings = [ { name = "CHAT_ROOM", class_name = "ChatRoom" } ] [[migrations]] tag = "v1" new_sqlite_cla
- architecture ↗
tory = "./dist" not_found_handling = "single-page-application" run_worker_first = true binding = "ASSETS" [durable_objects] bindings = [ { name = "CHAT_ROOM", class_name = "ChatRoom" } ] [[migrations]] tag = "v1" new_sqlite_classes = ["ChatRoom"]
What it can replace
Compare the workflow you need. These mappings describe overlap; full feature parity requires a separate comparison.
Live browser room conversation and file transfer; durable workspaces, administration, moderation, integrations and audited security equivalence are excluded.
See supporting source ↗Live browser room conversation and file transfer; durable workspaces, administration, moderation, integrations and audited security equivalence are excluded.
See supporting source ↗How it works
The shape of NodeCrypt on Cloudflare, and how it stacks up against the rented tools it replaces.
Architecture
Diagram of deployment declarations at the reviewed commit. Each app has its own entrypoint; declared resources do not prove runtime calls. Follow file and line sources below.
View upstream source ↗Configuration and workflow sources
Reviewed commit 54ed04903182. Files were read as data; upstream applications and CI jobs were not executed.
Deployment configuration · 1 files
Cloudflare Workers · compatibility 2024-09-23
nodecrypt · default
Entrypoint: worker/index.js
Static assets: ./dist · single-page-application · Worker first: true
CHAT_ROOM→ Durable Objects · class ChatRoomASSETS→ Static assets
Named environments are separate deployments. Bindings are shown only where declared. Configured routes are URL patterns, not verified application endpoints.
Runtime source · handlers, binding usage and workflow steps
Observed TypeScript/JavaScript declarations from Worker entrypoints and resolved relative imports. Calls and workflow steps may run conditionally; their listed order is not a proven end-to-end request flow. Router declarations may be mounted under a prefix or may not be registered. This shows code wiring, not a successful deployment or runtime test. Dynamic wiring, aliases and generated code may not resolve.
- L4 · fetch handler exported · references CHAT_ROOM, ASSETS · calls request.headers.get, env.CHAT_ROOM.idFromName, env.CHAT_ROOM.get, stub.fetch, url.pathname.startsWith, JSON.stringify, env.ASSETS.fetch
Environment references: env.CHAT_ROOM · env.ASSETS
Build and deployment pipeline · 2 GitHub Actions workflows
Repository CI declarations, separate from runtime request processing. Job dependencies and conditions are shown as written; long commands are shortened with an ellipsis; a workflow file does not prove a recent successful run.
Triggers: push
build · no job dependencies declared
Condition: github.repository == 'shuaiplus/nodecrypt'
- actions/checkout@v4
actions/checkout@v4 - Log in to GitHub Container Registry
docker/login-action@v3 - Build and push Docker image
docker/build-push-action@v4
Triggers: schedule, workflow_dispatch
sync · no job dependencies declared
- actions/checkout@v4
actions/checkout@v4 - Shell command
git remote add upstream https://github.com/shuaiplus/NodeCrypt.git git fetch upstream git checkout main git merge --ff-only upstream/main || git merge upstream/main --no-edit git push origin main
build: vite builddeploy: wrangler deploypublish: wrangler publishbuild:docker: vite build
Repository README
View original on GitHub ↗Full upstream document by @shuaiplus · README.md · snapshot 54ed049
NodeCrypt
🚀 部署说明
一键部署到 Cloudflare Workers
点击下方按钮即可一键部署到 Cloudflare Workers:
- 构建命令:npm run build
- 部署命令:npm run deploy
📝 项目简介
NodeCrypt 是一个真正的端到端加密聊天系统,实现完全的零知识架构。整个系统设计确保服务器、网络中间人、甚至系统管理员都无法获取任何明文消息内容。所有加密和解密操作都在客户端本地进行,服务器仅作为加密数据的盲中继。
系统架构
- 前端:ES6+ 模块化 JavaScript,无框架依赖
- 后端:Cloudflare Workers + Durable Objects
- 通信:WebSocket 实时双向通信
- 构建:Vite 现代化构建工具
🔐 零知识架构设计
核心原则
- 服务器盲转:服务器永远无法解密消息内容,仅负责加密数据中转
- 无数据库存储:系统不使用任何持久化存储,所有数据仅在内存中临时存在
- 端到端加密:消息从发送方到接收方全程加密,中间任何环节都无法解密
- 前向安全性:即使密钥泄露,也无法解密历史消息,因为根本就没有历史消息
- 匿名通信:用户无需注册真实身份,支持临时匿名聊天
- 多样体验:和批量发送图片和文件,可选择主题和语言。
隐私保护机制
- 实时成员提醒:房间在线列表完全透明,内任何人加入或离开都会实时通知所有成员,
- 无历史消息:新加入的用户无法看到任何历史聊天记录
- 私聊加密:点击用户头像可发起端到端加密的私密对话,房间内其他成员完全无法看到私聊内容
房间密码机制
房间密码作为密钥派生因子参与端到端加密:最终共享密钥 = ECDH_共享密钥 XOR SHA256(房间密码)
- 密码错误隔离:不同密码的房间无法解密彼此的消息
- 服务器盲区:服务器永远无法获知房间密码
三层安全体系
第一层:RSA-2048 服务器身份验证
- 服务器启动时生成临时 RSA-2048 密钥对,每24小时自动轮换
- 客户端连接时验证服务器公钥,防止中间人攻击
- 私钥仅在服务器内存中存在,从不持久化存储
第二层:ECDH-P384 密钥协商
- 每个客户端生成独立的椭圆曲线密钥对(P-384曲线)
- 通过椭圆曲线 Diffie-Hellman 密钥交换协议建立共享密钥
- 每个客户端与服务器之间拥有独立的加密通道
第三层:混合对称加密
- 服务器通信:使用 AES-256-CBC 加密客户端与服务器间的控制消息
- 客户端通信:使用 ChaCha20 加密客户端之间的实际聊天内容
- 每条消息使用独立的初始化向量(IV)和随机数(Nonce)
🔄 完整加密流程详解
sequenceDiagram
participant C as 客户端
participant S as 服务器
participant O as 其他客户端
Note over C,S: 阶段1: 服务器身份验证 (RSA-2048)
C->>S: WebSocket连接
S->>C: RSA-2048公钥
Note over C,S: 阶段2: 客户端-服务器密钥交换 (P-384 ECDH)
C->>S: P-384 ECDH公钥
S->>C: P-384公钥 + RSA签名
Note over C: 验证RSA签名并派生AES-256密钥
Note over S: 从P-384 ECDH派生AES-256密钥
Note over C,S: 阶段3: 房间认证
C->>S: 加入请求 (房间哈希,AES-256加密)
Note over S: 将客户端添加到房间/频道
S->>C: 成员列表 (其他客户端ID,加密)
Note over C,O: 阶段4: 客户端间密钥交换 (Curve25519)
Note over C: 为每个成员生成Curve25519密钥对
C->>S: Curve25519公钥包 (AES-256加密)
S->>O: 转发客户端C的公钥
O->>S: 返回其他客户端的Curve25519公钥
S->>C: 转发其他客户端的公钥
Note over C,O: 阶段5: 密码增强密钥派生
Note over C: 客户端密钥 = ECDH_Curve25519(自己私钥, 对方公钥) XOR SHA256(密码)
Note over O: 客户端密钥 = ECDH_Curve25519(自己私钥, 对方公钥) XOR SHA256(密码)
Note over C,O: 阶段6: 身份验证
C->>S: 用户名 (用客户端密钥ChaCha20加密)
S->>O: 转发加密用户名
O->>S: 用户名 (用客户端密钥ChaCha20加密)
S->>C: 转发加密用户名
Note over C,O: 双方客户端现在验证彼此身份 Note over C,O: 阶段7: 安全消息传输 (双层加密)
Note over C: 1. ChaCha20加密(消息内容)<br/>2. AES-256加密(传输层包装)
C->>S: 双层加密消息
Note over S: 解密AES-256传输层<br/>提取ChaCha20加密数据<br/>无法解密消息内容
S->>O: 转发ChaCha20加密数据
Note over O: 解密AES-256传输层<br/>ChaCha20解密获得消息内容
🛠️ 技术实现
- Web Cryptography API:浏览器原生加密实现,提供硬件加速
- elliptic.js:椭圆曲线密码学库,实现 Curve25519 和 P-384
- aes-js:纯 JavaScript AES 实现,支持多种模式
- js-chacha20:ChaCha20 流加密算法的 JavaScript 实现
- js-sha256:SHA-256 哈希算法实现
🔬 安全验证
加密过程验证
用户可通过浏览器开发者工具观察完整的加密解密过程,验证消息在传输过程中确实处于加密状态。
网络流量分析
使用网络抓包工具可以验证所有 WebSocket 传输的数据都是不可读的加密内容。
代码安全审计
所有加密相关代码完全开源,使用标准密码学算法,欢迎安全研究者进行独立审计。
⚠️ 安全建议
- 使用强房间密码:房间密码直接影响端到端加密强度,建议使用复杂密码
- 密码保密性:房间密码一旦泄露,该房间所有通信内容都可能被解密
- 使用最新版本的现代浏览器:确保密码学API的安全性和性能
🤝 安全贡献
欢迎安全研究者报告漏洞和进行安全审计。严重安全问题将在24小时内修复。
📄 开源协议
本项目采用 ISC 开源协议。
⚠️ 免责声明
本项目仅供学习和技术研究使用,不得用于任何违法犯罪活动。使用者应遵守所在国家和地区的相关法律法规。项目作者不承担因使用本软件而产生的任何法律责任。请在合法合规的前提下使用本项目。
Star History
NodeCrypt - 真正的端到端加密通信 🔐
"在数字时代,加密是保护隐私的最后一道防线"
Frequently asked about NodeCrypt
What is NodeCrypt?+
NodeCrypt is a self-hosted Discord/Slack alternative built on the Cloudflare developer platform. Run ephemeral browser chat rooms on Workers and SQLite Durable Objects.
What does NodeCrypt replace?+
NodeCrypt is listed as an alternative to Discord, Slack. Compare the features and tradeoffs before migrating.
What Cloudflare primitives does NodeCrypt use?+
NodeCrypt is built on Durable Objects, Workers.
How much does NodeCrypt cost to run?+
The documented NodeCrypt deployment can use Cloudflare Free allowances for a small workload under the request, CPU and service-specific quotas below. This is conditional eligibility, not a measured zero-cost deployment; optional features, domains and external providers can add costs. Workers Free allows 100,000 requests per day shared across the account and 10 ms CPU per invocation; measure CPU-heavy authentication, parsing and rendering before assuming it fits. Use the configured SQLite Durable Object classes within 100,000 requests/day, 13,000 GB-s duration/day, 5 million SQL rows read/day, 100,000 written/day and 5 GB storage; active sockets consume duration. Use a small personal or team workload; domain registration and optional third-party providers are separate costs. Provision your own IDs, secrets and migrations. Check current Cloudflare pricing before deploying.
Is NodeCrypt open source?+
The upstream repository declares the ISC license. Read its terms at https://raw.githubusercontent.com/shuaiplus/nodecrypt/54ed04903182799895e98af365cf4172f7b2f3f3/LICENSE. Source code and contributor credit are available at https://github.com/shuaiplus/nodecrypt.


Discussion · 0
sign in to comment →