# 从零实现一个端到端加密的密钥同步工具

Original: <https://lifelonglearn.ing/Implement-end-to-end-encryption-key-synchronization-tool-from-scratch>

Author: [奶爸](https://lifelonglearn.ing/users/3b04650c-8231-499b-8ef0-381fc4d7efb0)

Published: 2020-10-30T14:34:09Z

Updated: 2026-09-27T06:57:43Z

Version: 1

这个端到端加密的工具奶爸已经做出来好多个月了：[cloudssh](https://lifelonglearn.ing/r/go?url=aHR0cHM6Ly9naXRodWIuY29tL25haWJhLWFyY2hpdmUvY2xvdWRzc2g=)，因为最开始没有设计好 `cmd` 命令的模板导致现在奶爸没有优化下去的兴致了，总结一下端到端加密中的设计模式，有意思的细节，就打住了。

## 端到端加密详解

### 名词解释

* MasterKey：明文密码以服务器返回的加密途径加密后的key，此key用来加密个人账户下的所有数据使用
* EncKey：MasterKey 的再hash，hash方法固定，循环次数较小，只是 hash 后提供给服务器当作密码鉴权使用
* 对称密钥：公钥用来加密 Team 的私钥，私钥由 MasterKey 加密后储存在服务器中，需要时解密来用
* Team 密钥：公钥储存在 Team 表，私钥储存在每个成员那里

### 用户注册

sequenceDiagram participant 用户 participant 客户端 participant 服务器 用户->>客户端: 注册账户 客户端->>服务器: 询问加密masterKey的加密方式 服务器->>客户端: 返回masterKey加密方式 用户->>客户端: 提供邮箱、明文密码 客户端->>服务器: 密码为依据明文密码生成 hash 后的 encKey 的 hash，生成对称加密密钥，将对称加密私钥由 encKey 加密后一起提交至后端 服务器-->>客户端: 注册成功

在注册流程中，明文密码不会离开你的电脑。服务器端保存的密码是用来加密数据的 encKey 的 hash 的 bcrypt hash 后的值，和 encKey 的 hash 方式。

### 用户登录

sequenceDiagram participant 用户 participant 客户端 participant 服务器 用户->>客户端: 提供账户邮箱、密码登录 客户端->>服务器: 预询问该账户加密masterKey的加密方式 服务器-->>客户端: 返回masterKey加密方式 客户端->>服务器: 按照加密方式将明文密码加密为 masterKey，然后按照固定模式生成 encKey 进行 hash 提交到服务器鉴权 服务器-->客户端: 登录成功

### 个人数据

#### 读取

sequenceDiagram participant 用户 participant 客户端 participant 服务器 用户->>客户端: 读取 数据1 客户端->>服务器: 请求 数据1 服务器-->>客户端: 返回 数据1 客户端-->>用户: 使用 masterKey 解密然后展示给用户

#### 写入

sequenceDiagram participant 用户 participant 客户端 participant 服务器 用户->>客户端: 写入 数据2 客户端->>服务器: 将 数据2 中除ID外的字段由 masterKey 加密，然后上传至服务器 服务器-->>客户端: 直接存入数据库 服务器-->>客户端: 写入成功

### Team 数据

#### 读取

sequenceDiagram participant 用户 participant 客户端 participant 服务器 用户->>客户端: 读取 数据1 客户端->>服务器: 请求 数据1 服务器-->>客户端: 返回 数据1 客户端-->>用户: 使用 masterKey 解密 Team 的私钥，在用私钥解密数据，然后展示给用户

#### 写入

sequenceDiagram participant 用户 participant 客户端 participant 服务器 用户->>客户端: 写入 数据2 客户端->>服务器: 将 数据2 中除ID外的字段由 Team 公钥加密，然后上传至服务器 服务器-->>客户端: 直接存入数据库 服务器-->>客户端: 写入成功

## 概览

### Team 成员管理

graph TD; 单人-->个人帐户; 个人帐户-->明文密码及ciperString; 明文密码及ciperString-->数据; 多人-->Team账户; Team账户-->对称加密密钥; 对称加密密钥-->数据;

因为 Team 账户为多人服务，既要保证每个人都能读取、修改Team中的数据，又能使个人的数据维持私密安全。同样在添加与删除成员时，只需要操作 添加/删除 的管理员修改 Team 的公钥与私钥，而后便利相关成员，使用成员的公钥将新的 Team 私钥保存在成员处，成员即可使用更新的私钥读取数据，而被提出剔出的成员也无法再解密 Team 数据。

### 目前的缺陷

客户端为方便用户明文储存了用户的明文密码在 `~/.cloudssh.json` 中，这是极不安全的。请看这篇博文 「[Stop saving credential tokens in text files](https://lifelonglearn.ing/r/go?url=aHR0cHM6Ly9tZWRpdW0uY29tL0BjYWxhdmVyYS9zdG9wLXNhdmluZy1jcmVkZW50aWFsLXRva2Vucy1pbi10ZXh0LWZpbGVzLTY1ZTg0MGEyMzdiYg==)」端到端加解密，包括处理多人加解密的流程比较复杂，奶爸的描述能力有限，欢迎与博主进行交流。
