【文章标题】:Hard-Chat – 一款无服务器、仅用RAM的P2P终端聊天工具

【文章正文】: 端到端加密的P2P聊天,直接在浏览器中运行。无需服务器、无需账户、不存储历史记录。 由Hardlint网络安全团队开发 本项目出于教育和安全研究目的分发。它不保证网络层面的匿名性:它保护的是对话内容,而不一定是连接者的身份。在用于敏感通信前,请阅读”攻击面与已知限制”章节。 强烈建议双方设备均使用可信VPN。

  • 🔐 端到端加密 —— AES-GCM 256位,通过PBKDF2(10万次迭代)派生密钥
  • 🌐 真正的P2P连接 —— 设备间直接建立WebRTC链接,无中心服务器中转消息
  • 🚫 零持久化 —— 无cookie、无localStorage、无数据库:关闭标签页即不留痕迹
  • 🔑 单一共享密钥 —— 随机生成的100字符房间密钥,无需手动技术配置
  • 🧹 紧急清除 —— 一键立即擦除密钥、连接状态和可见聊天记录
  • 📡 可靠连接 —— 配置18个STUN/TURN服务器作为后备方案,可在严格NAT环境下工作(4G/5G、企业网络)

使用流程:

  • 打开页面(必须通过HTTPS访问——例如GitHub Pages,不能作为本地文件打开)
  • 主机方:点击[1]初始化房间 → 复制生成的房间密钥
  • 通过其他渠道(当面、语音通话、其他加密应用)将密钥发送给联系人
  • 客机方:点击[2]连接到房间 → 粘贴收到的房间密钥
  • 等待连接(通常数秒)→ 聊天窗口开启
  • 若2分钟内未建立连接,房间密钥自动失效:需使用专用按钮生成新密钥

系统要求:

  • 支持WebRTC和Web Crypto API的现代浏览器(最新版Chrome/Firefox/Edge/Safari)
  • 双方设备均需联网
  • 页面必须通过HTTPS访问(Web Crypto API和WebRTC需要安全上下文)——本地文件打开无效
  • 连接尝试期间双方需同时保持页面打开
  • 必须完整复制100字符房间密钥,不能有额外空格或换行

技术架构: Zero-Trace Terminal是静态Web应用(HTML/CSS/JS,无专有后端),通过WebRTC建立设备间直连,交换端到端加密文本消息。
核心组件:

组件功能技术实现
用户界面复古终端UI纯HTML/CSS
信令系统帮助节点互相发现PeerJS(公共云代理)
数据传输加密P2P通道WebRTC DataChannel
NAT穿透穿越防火墙/NATSTUN + TURN (ICE)
加密模块消息内容保护AES-GCM 256位+PBKDF2
托管服务代码分发GitHub Pages(静态)

无专有应用服务器:代码完全在用户浏览器中运行。唯一涉及的外部基础设施用于设备间初始”介绍”(信令),以及在无法直连时中继流量(TURN)。

密钥生成机制: 当用户点击”初始化房间(主机)“时:

  • 使用加密安全随机数生成器crypto.getRandomValues()(非Math.random())生成100字符随机字符串
  • 字符集包含大小写字母、数字和特殊符号(-_!@#$%

该房间密钥是双方需要通过带外方式(如语音消息、当面传递、其他加密通道)交换的唯一共享密钥。从中派生出两个独立值:

A. 消息加密密钥(PBKDF2→AES-GCM)
PBKDF2(
密码=房间密钥,
盐值=“p2p-zero-trace-salt-v1”(固定硬编码),
迭代=100,000次,
哈希算法=SHA-256
) → 256位AES-GCM密钥

B. PeerJS标识符(截断SHA-256)
SHA-256(房间密钥) → 取前32位十六进制字符,加”ztt-”前缀

该ID仅用于双方通过PeerJS信令代理互相发现,不参与加密过程。

关于固定盐值的说明:由于房间密钥本身具有极高熵值(100随机字符),在此场景下使用固定盐值不会削弱安全性——固定盐值仅在弱密码/重复密码场景下存在风险。

连接建立过程:

  • 主机创建Peer对象,用派生ID注册到公共PeerJS代理
  • 客机粘贴相同房间密钥后,计算相同ID并调用peer.connect(id)
  • PeerJS代理仅中介初始连接(谁要与谁通信)——绝不接触消息内容,消息始终通过加密P2P通道传输