Knight1/vanmoof-certificates
GitHub: Knight1/vanmoof-certificates
一款用于获取、解析和签发 VanMoof SA5 及 Series 6 智能自行车蓝牙访问证书的 Go 命令行工具。
Stars: 3 | Forks: 0
# vanmoof-certificates
一个用于获取和解析 VanMoof SA5 及 Series 6 自行车证书的 Go 工具。
该工具通过 VanMoof 的 API 进行身份验证,检索您的自行车,生成 Ed25519 密钥对,并为您的 SA5 或更新型号的自行车创建证书。
目前这包括 SA5 和 SA6 型号的自行车。具体列表为:S5、A5、Series 6、Series 6 Open。
## 功能
- 使用 token 缓存(auth token、app token、refresh token)或用户名/密码与 VanMoof API 进行身份验证
- 从您的账户中检索并筛选 SA5 和 S6 自行车
- 通过 VanMoof 的 Vehicle Registry API 支持共享/访客自行车
- 生成 Ed25519 密钥对
- 创建和解析自行车证书
- 交互式或命令行自行车选择(通过 ID 或车架号)
- 用于故障排除的 debug 模式
## 使用与安装
请参阅 [USAGE.md](USAGE.md)
## 证书结构
VanMoof 自行车证书采用二进制格式,由一个 Ed25519 签名和其后跟随的 CBOR 编码的 payload 组成。
**密钥格式(如 crypto.go 中所用):**
- **Private key**:64 字节,采用 base64 编码(Ed25519 seed 与 public key 拼接)
- **Public key**:32 字节,采用 base64 编码(原始 Ed25519 public key)
- **编码**:标准 base64(Go 中的 `base64.StdEncoding`)
- **无额外前缀**:与某些实现不同,这里使用不带元数据的原始密钥
**重要说明:**
- 某些实现可能会在 public key 前加上 `0x00` 前缀(总共 33 字节) - 这种格式同样被接受
- 来自 `ed25519.GenerateKey()` 的 private key 为 64 字节:32 字节的 seed + 32 字节的 public key
### 整体格式
```
[64 bytes: Ed25519 Signature] + [Variable length: CBOR Payload]
```
### 签名(64 字节)
前 64 个字节包含一个 Ed25519 签名,用于对 CBOR payload 进行加密签名:
- **字节 0-31**:Ed25519 签名的 R 分量
- **字节 32-63**:Ed25519 签名的 S 分量
此签名由 VanMoof 的 Certificate Authority (CA) 创建,可以使用 CA 的 public key 进行验证,以确保证书是真实的且未被篡改。
CA 签名的 public key(从自行车的 BLE 证书中恢复,并且在所有证书中都是相同的)如下:
```
29b1f31c07d1c63b124057ebe75a0bc0796259722e5dd9a9a9302ae2061184a0
```
每个解析出的证书的签名都会根据此密钥进行验证;如果不匹配,
则会标记为错误(成功时静默处理)。使用 `-debug` 运行可查看完整的验证详情。
### CBOR Payload 结构
从第 64 字节开始,证书包含一个 CBOR 编码的 map,具有以下字段:
| Key | Type | Description | Example |
|-----|------|-------------|---------|
| `i` | uint32 | 证书 ID | `1337` |
| `f` | string | Frame Module 序列号 (AFM - Authorized Frame Module) | `"SVTBKLdddddOA"` |
| `b` | string | Bike Module 序列号 (ABM - Authorized Bike Module) | `"SVTBKLdddddOA"` |
| `e` | uint32 | 证书过期时间 (Unix timestamp) | `1767668550` |
| `r` | uint8 | 角色/访问级别 (0-15) | `7` |
| `u` | bytes[16] | 用户 UUID(不含连字符) | `uuid3` |
| `p` | bytes[32] | 用户的 Ed25519 public key | 32 字节的 public key |
### 访问级别(Role 字段)
`r`(角色)字段决定了证书授予的权限:
| Value | Access Level | Description |
|-------|--------------|-------------|
| `0x00` | Guest | 只读访问 |
| `0x01` | Limited Access | 受限权限 |
| `0x03` | Owner | 标准所有者访问 |
| `0x07` | Owner | 完全控制权(解锁、设置、固件) |
| `0x0F` | Service/Admin | 用于服务/维护的扩展权限 |
### 证书绑定
证书在加密上将以下内容绑定在一起:
1. **特定自行车**:frame/bike module 序列号(`f`、`b`)
2. **证书 ID**:`i` 字段在每个证书中各不相同
3. **特定用户**:API 用户 UUID(`u`)
4. **特定 Public Key**:用户的 Ed25519 public key(`p`)
5. **访问级别**:role 字段(`r`)
6. **有效期**:过期时间戳(`e`)
当自行车验证证书时,它会检查:
- Ed25519 签名是否有效(由 VanMoof CA 签署)
- frame/bike module 序列号是否与这辆自行车匹配
- 证书是否已过期
- 用户的 public key 是否与证书中的匹配
### 证书示例解析
解码后的结构:
- **Signature**:`...`(64 字节)
- **Certificate ID**:`1337`
- **Frame Module Serial (AFM)**:`SVTBKLdddddOA`
- **Bike Module Serial (ABM)**:`SVTBKLdddddOA`
- **Expiry**:`1767668550`(2026 年 1 月 6 日 04:02:38 CET)
- **Role**:`7`(Owner - 完全控制权)
- **User UUID**:`1111111-1111-3111-1111-111111111111`(UUIDv3)
- **Public Key**:`KIQtqMxZ9Vdj3YLfNgNHjUB4WN4gLtDX/FwpiyFiUMs=`
### CBOR 编码细节
Payload 使用 CBOR(Concise Binary Object Representation,RFC 8949)编码:
```
0xa7 # Map with 7 entries
0x61 0x69 # Text string "i"
0x1a 0x00 0x02 0xa7 0x66 # uint32: 1337 (Certificate ID)
0x61 0x66 # Text string "f"
0x6d # Text string, 13 bytes
"SVTBKLdddddOA" # Frame Module serial (AFM)
0x61 0x62 # Text string "b"
0x6d # Text string, 13 bytes
"SVTBKLdddddOA" # Bike Module serial (ABM)
0x61 0x65 # Text string "e"
0x1a 0x69 0x5c 0x7b 0x46 # uint32: 1767668550
0x61 0x72 # Text string "r"
0x07 # uint: 7
0x61 0x75 # Text string "u"
0x50 # Byte string, 16 bytes
[16 bytes: user UUIDv3]
0x61 0x70 # Text string "p"
0x58 0x20 # Byte string, 32 bytes
[32 bytes: public key]
```
### 安全说明
- 似乎没有撤销机制或公开日志。如果有人可以访问包含您自行车的 VanMoof 账户,他们就可以在您不知情的情况下生成证书。此外,这些证书是不可撤销的。因此,保护自行车安全的唯一方法就是将其锁在车库或地下室中,直到 7 天过去。
- 目前尚不清楚自行车在断电后是如何知道时间的。这可能是通过 GSM、GPS 或手机实现的。如果存在干扰器或 GPS 时间被欺骗,目前会发生什么尚不清楚。在您可以伪造较旧时间的情况下,如果自行车接受了该新时间作为“正确时间”,理论上您可以使用较旧的证书解锁自行车。
- 7 天后会发生什么?由于 VanMoof 恢复了 10 年的证书有效期,目前如果不与 VanMoof API 通信以签发新证书,就无法控制自行车(backup code 除外)。或者,可以实现一种逻辑,要求进行 2FA 才能签发有效期超过 7 天的证书。
- 此外,VanMoof 可以随时将您锁定在外。
标签:API集成, EVTX分析, Go语言, 可观测性, 密码学, 手动系统调用, 数字证书, 日志审计, 智能自行车, 物联网, 程序破解