ISC License

技术解读

以下内容由 GitRead 中文社区 编辑团队基于项目 README 与官方资料整理, 结合中文开发者的常见使用场景补充技术选型建议。具体以项目官方文档为准。

深度分析:soatok/rawr-x3dh —— TypeScript 实现 X3DH

项目背景与痛点

X3DH是一种端对端加密协议,适用于即时通讯和用户间的私密通讯。soatok/rawr-x3dh 项目以 TypeScript 实现了 X3DH 协议,为开发者提供了在现代 Web 应用中集成端对端加密功能的能力。这项技术填补了 Web 开发者在不依赖原生支持的情况下构建安全私聊平台的空白,解决了一大痛点:在复杂的网络环境中确保消息传递的安全性和隐私性。

技术核心揭秘

技术架构与实现原理

soatok/rawr-x3dh项目使用TypeScript实现了X3DH协议,确保了代码的可维护性与可读性。更进一步地,它使用了椭圆曲线加密技术来构建其加密功能,这在现代加密技术中是一种标准的方式。

数据流图

下面,我们将使用Mermaid绘制出数据流的基础架构:

graph TD A[用户设备发起连接] --> B[服务器进行X3DH握手] B --> C{"使用会话密钥加密消息?"} C -->|"否"| D[使用一次性密钥加密] C -->|"是"| E[使用会话密钥进行加密] D --> F[发送消息至接收方] E --> F F --> G[接收方设备接收加密消息] G --> H{"验证消息签名?"} H -->|"失败"| I[抛出验证失败错误] H -->|"成功"| J[解密消息并显示] J --> K[本地消息存储]

X3DH握手与椭圆曲线加密技术

在实现过程中,soatok/rawr-x3dh 采用了 X3DH 握手流程,划分为预密钥握手,以及随后的会话密钥创建和交换。整个握手过程中,各设备生成一次性密钥对,使用椭圆曲线加密技术来安全地交换这些密钥。

功能亮点与差异

该项目的核心亮点在于其精简的设计与实现,能够方便地集成至现有的 Web 应用。同时,其TypeScript的封装设计也大大提升了开发者的开发效率。相对于同类实现如Matrix的OpenPGP,该项目以其更简洁的实现路径脱颖而出,更具契合现代web开发模式的优势。

应用场景与落地建议

在生产环境中使用此项目时,开发者应着重关注以下几个方面:

  1. 系统稳定性与性能优化:确保良好的用户交互体验,特别是在使用加密技术进行密集计算时,可能带来一定的性能开销。
  2. 密钥管理:合理管理一次性密钥,防止密钥泄露影响到用户账户的安全性。
  3. 密钥恢复机制:即使加密技术再强,数据丢失的风险也需要有相应的数据恢复机制。

它适合需要保护用户隐私和通信安全的应用场景,如即时通讯工具、社交媒体平台等。

综合评价

优点

  1. 简洁高效:项目采用TypeScript,代码清晰,易于维护。
  2. 安全性高:实现了X3DH协议,保证了消息传递的安全性。
  3. 易于集成:可以直接在现有的Web应用中集成,提升了开发效率。

缺点

  1. 性能瓶颈:在某些情况下加密计算可能会消耗更多的处理器资源,影响应用性能。
  2. 复杂度:对于不熟悉X3DH协议及加密技术的开发人员,可能存在学习曲线较陡的问题。

soatok/rawr-x3dh作为一项X3DH协议的TypeScript实现,无疑为现代Web应用提供了便利的安全通讯解决方案。尽管它存在一些性能上的挑战,但其在加强用户数据安全性方面的贡献是不可忽视的。

关于

GitHub 原始描述(英文)

TypeScript Implementation of X3DH

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
117
价值分
62
活跃状态
活跃

语言占比

TypeScript

Release

README

Rawr X3DH

TypeScript implementation of X3DH, as described in Going Bark: A Furry’s Guide to End-to-End Encryption.

Support me on Patreon

Travis CI npm version

OwO What’s This?

This library implements the Extended Triple Diffie-Hellman key exchange, with a few minor tweaks:

  1. Identity keys are Ed25519 public keys, not X25519 public keys. See this for an explanation.
  2. Encryption/decryption and KDF implementations are pluggable (assuming you implement the interface I provide), so you aren’t married to HKDF or a particular cipher. (Although I recommend hard-coding it to your application!)

Installation

First, you’ll want to install this library via your package manager.

npm install rawr-x3dh

If you’re working server-side, you’ll also want to install sodium-native, so that sodium-plus will run faster.

If you’re working in a browser or browser extension, don’t install sodium-native.

Usage

First, you’ll want to import the X3DH class from our module.

import { X3DH } from 'rawr-x3dh';

const x3dh = new X3DH();

Note: You can pass some classes to the constructor to replace my algorithm implementations for your own.

import { X3DH } from 'rawr-x3dh';

const x3dh = new X3DH(
    sessionKeyManager, /* SessionKeyManagerInterface */
    identityKeyManager, /* IdentityKeyManagerInterface */
    symmetricEncryptionHandler, /* SymmetricEncryptionInterface */
    keyDerivationFunction /* KeyDerivationFunction */
);

Once your X3DH object’s instantiated, you will be able to initialize handshakes either as a sender or as a recipient. Then you will be able to encrypt additional messages on either side, and the encryption key shall ratchet forward.

const firstEncrypted = await x3dh.initSend(
    'recipient@server2',
    serverApiCallFunc,
    firstMessage
); 

The serverApiCallFunc parameter should be a function that sends a request to the server to obtain the identity key, signed pre-key, and optional one-time key for the handshake.

See the definition of the InitClientFunction type in lib/index.ts.

Once this has completed, you can call encryptNext() multiple times to append messages to send.

const nextEncrypted = await x3dh.encryptNext(
    'recipient@server2',
    'This is a follow-up message UwU'
);

On the other side, your communication partner will use the following feature.

const [sender, firstMessage] = await x3dh.initRecv(senderInfo);
const nextMessage = await x3dh.decryptNext(sender, nextEncrypted);

Note: initRecv() will always return the sender identity (a string) and the message (a Buffer that can be converted to a string). The sender identity should be usable for decryptNext() calls.

However, that doesn’t mean it’s trustworthy! This library only implements the X3DH pattern. It doesn’t implement the Gossamer integration.

Should I Use This?

Don’t use it in production until version 1.0.0 has been tagged. The API can break at any moment until that happens (especially if I decide I hate the default key management classes I wrote).

However, feel free to test and play with it.

Questions and Answers

Any Interest in Porting This to $LANG?

I’d love to port this to more languages! That will also allow me to write end-to-end integration tests.

As long as there’s a good libsodium implementation, it should be doable.

However, I don’t have nearly as much free time as I’d like, so I can’t commit to building or supporting multiple implementations right now.

Conversely, if you’ve ported this to another language, let me know and I’ll maintain a list here:

  • (Currently, none.)

Why “Rawr”?

The canonical abbreviation for the eXtended 3-way Diffie Hellman deniable authenticated key exchange is X3DH.

There is a cursed furry copypasta/meme that begins with “rawr x3”. The juxtaposition of “x3” and “X3DH” is too perfect an opportunity for dumb jokes to pass up.

Is this a furry thing?

You betcha!

And remember: It’s not furry trash, it’s yiff-raff.

Why? Just, Why?

I’ve written a lot of words to answer this line of questioning already on my blog.

You will probably find the answer you’re seeking here or here.

Comic by loviesophiee

This is Unprofessional

Folks often say there’s an XKCD for Everything! And thus:

XKCD

Sophie made it.

评论

暂无评论