密钥命名混乱历史
本文档记录蓝牙门锁协议中密钥命名的历史混乱问题及统一规范过程。
问题背景
由于项目历经多年开发,先后有多位程序员参与,在不同的实现版本中对同一个密钥使用了不同的命名,导致文档和代码中术语混乱,给开发者造成困扰。
历史命名对照
协议中的3个密钥
| 标准命名 | 历史别名 | 长度 | 获取命令 |
|---|---|---|---|
| PublicKey (公钥) | 锁公钥、公用密钥 | 16字节 | 0x3090 |
| PrivateKey (私钥) | CommKey、通信密钥、通讯密钥、锁私钥 | 16字节 | 0x3091 |
| SignKey (签名密钥) | 签名密钥 | 16字节 | 0x3091 |
混乱来源
问题1: PrivateKey与CommKey混用
- 0x3091命令返回两个密钥,但早期文档将PrivateKey称为"锁私钥"
- C代码注释中使用
private_key // CommKey的形式 - 导致开发者不清楚CommKey和PrivateKey的关系
问题2: "通信密钥"与"通讯密钥"混用
- 部分文档使用"通信密钥"
- 部分文档使用"通讯密钥"
- 实际都指PrivateKey
问题3: "锁公钥"、"锁私钥"等口语化表述
- 文档中使用"获取锁公钥"、"获取锁私钥"
- 过于口语化,不规范
各实现版本中的使用情况
ESP32网关 (C/C++)
位置: git@code.star-lock.cn:StarlockTeam/fdesp.git
命名方式:
c
typedef struct {
uint8_t private_key[16]; // 注释: (CommKey)
uint8_t sign_key[16]; // 注释: (SignKey)
} xhjlock_get_private_key_response_t;特点:
- 变量名使用
private_key和sign_key - 注释中标注CommKey别名
- 代码中使用
manager->private_key进行SM4加密 - 使用
manager->sign_key计算MD5签名
微信小程序 (JavaScript)
位置: git@code.star-lock.cn:StarlockTeam/wx-starlock.git
命名方式:
javascript
// 获取私钥命令
export async function getPrivateKey(params = {}) {
// ...
}
// 保存到lockInfo
this.updateLockInfo({
bluetooth: {
publicKey: result.data.publicKey,
privateKey: result.data.privateKey, // 对应CommKey
signKey: result.data.signKey
}
})
// 使用privateKey进行SM4加密
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})特点:
- 直接使用
privateKey和signKey - 无CommKey命名
- 清晰明了
Flutter APP (Dart)
位置: git@code.star-lock.cn:StarlockTeam/app-starlock.git
命名方式:
dart
// 方法参数
static void getPrivateKey(
{String? lockId,
List<int>? publicKeyData, // 公钥
...}
)
// 方法参数传递
addUser(
List<int>? publicKey,
List<int>? privateKey, // 对应CommKey
...
)
// openLock使用
openLock(
List<int>? signKey,
List<int>? privateKey,
...
)特点:
- 使用
publicKey、privateKey、signKey - 命名与微信小程序一致
- 无CommKey命名
旧版文档
命名混乱表现:
加密与签名文档:
- 使用"锁公钥"、"锁私钥"
- 将PrivateKey描述为"通讯密钥"
- 未明确CommKey就是PrivateKey
设备管理文档:
- 响应参数表格中使用
CommKey - 说明文字中使用"通讯密钥和签名密钥"
- 未统一术语
- 响应参数表格中使用
命令集文档:
- 使用"获取锁公钥"、"获取锁私钥"
- 不规范
统一规范过程
调查阶段
代码调查:
- 分析ESP32网关C代码实现
- 分析微信小程序JavaScript实现
- 分析Flutter APP Dart实现
密钥用途确认:
- PublicKey: 用于计算AuthCode(场景1),详见加密与签名 - 关于"公钥"命名的历史说明
- PrivateKey: 用于SM4私钥模式加密/解密所有命令
- SignKey: 用于计算MD5签名验证
术语统一
确定最终标准:
| 术语 | 英文 | 禁止使用 |
|---|---|---|
| 公钥 | PublicKey | 锁公钥、公用密钥 |
| 私钥 | PrivateKey | CommKey、通信密钥、通讯密钥、锁私钥 |
| 签名密钥 | SignKey | - |
统一原则:
- 禁止使用所有别名
- 代码注释中可说明历史别名关系,但变量名必须规范
- 文档中只使用标准术语
命名对应关系总结
PrivateKey = CommKey
在代码中:
- ESP32: 变量名
private_key,注释标注(CommKey) - 小程序: 使用
privateKey - Flutter: 使用
privateKey
实际用途:
- SM4-ECB加密/解密所有后续命令的数据包
- 与SignKey配合使用,PrivateKey负责加密,SignKey负责签名
0x3091命令返回两个密钥
旧理解(错误):
- 认为是"获取私钥",返回一个私钥
新理解(正确):
- 命令返回两个独立的密钥: PrivateKey + SignKey
- PrivateKey用于加密
- SignKey用于签名
- 两者配合使用,缺一不可
标准化成果
文档层面
- ✅ 所有文档使用统一术语:PublicKey、PrivateKey、SignKey
- ✅ 清除所有别名:CommKey、通信密钥、通讯密钥、锁公钥、锁私钥
- ✅ 明确密钥用途和使用场景
- ✅ 区分两种MD5签名计算方法
代码层面
不修改现有代码,但要求:
新代码必须使用标准命名
代码注释可说明历史别名,格式:
private_key // PrivateKey (历史别名: CommKey)API接口文档使用标准术语
遇到历史代码
comm_key/CommKey= PrivateKey通信密钥/通讯密钥= PrivateKey锁公钥= PublicKey锁私钥= PrivateKey
