Skip to content

密钥命名混乱历史

本文档记录蓝牙门锁协议中密钥命名的历史混乱问题及统一规范过程。

问题背景

由于项目历经多年开发,先后有多位程序员参与,在不同的实现版本中对同一个密钥使用了不同的命名,导致文档和代码中术语混乱,给开发者造成困扰。

历史命名对照

协议中的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_keysign_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'
})

特点:

  • 直接使用privateKeysignKey
  • 无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,
  ...
)

特点:

  • 使用publicKeyprivateKeysignKey
  • 命名与微信小程序一致
  • 无CommKey命名

旧版文档

命名混乱表现:

  1. 加密与签名文档:

    • 使用"锁公钥"、"锁私钥"
    • 将PrivateKey描述为"通讯密钥"
    • 未明确CommKey就是PrivateKey
  2. 设备管理文档:

    • 响应参数表格中使用CommKey
    • 说明文字中使用"通讯密钥和签名密钥"
    • 未统一术语
  3. 命令集文档:

    • 使用"获取锁公钥"、"获取锁私钥"
    • 不规范

统一规范过程

调查阶段

  1. 代码调查:

    • 分析ESP32网关C代码实现
    • 分析微信小程序JavaScript实现
    • 分析Flutter APP Dart实现
  2. 密钥用途确认:

术语统一

确定最终标准:

术语英文禁止使用
公钥PublicKey锁公钥、公用密钥
私钥PrivateKeyCommKey、通信密钥、通讯密钥、锁私钥
签名密钥SignKey-

统一原则:

  1. 禁止使用所有别名
  2. 代码注释中可说明历史别名关系,但变量名必须规范
  3. 文档中只使用标准术语

命名对应关系总结

PrivateKey = CommKey

在代码中:

  • ESP32: 变量名private_key,注释标注(CommKey)
  • 小程序: 使用privateKey
  • Flutter: 使用privateKey

实际用途:

  • SM4-ECB加密/解密所有后续命令的数据包
  • 与SignKey配合使用,PrivateKey负责加密,SignKey负责签名

0x3091命令返回两个密钥

旧理解(错误):

  • 认为是"获取私钥",返回一个私钥

新理解(正确):

  • 命令返回两个独立的密钥: PrivateKey + SignKey
  • PrivateKey用于加密
  • SignKey用于签名
  • 两者配合使用,缺一不可

标准化成果

文档层面

  1. ✅ 所有文档使用统一术语:PublicKey、PrivateKey、SignKey
  2. ✅ 清除所有别名:CommKey、通信密钥、通讯密钥、锁公钥、锁私钥
  3. ✅ 明确密钥用途和使用场景
  4. ✅ 区分两种MD5签名计算方法

代码层面

不修改现有代码,但要求:

  1. 新代码必须使用标准命名

  2. 代码注释可说明历史别名,格式:private_key // PrivateKey (历史别名: CommKey)

  3. API接口文档使用标准术语

  4. 遇到历史代码

    • comm_key / CommKey = PrivateKey
    • 通信密钥 / 通讯密钥 = PrivateKey
    • 锁公钥 = PublicKey
    • 锁私钥 = PrivateKey

鑫泓佳智能硬件通信协议文档