zerotier的planet是如何生成的?比如我将它转为Base64 编码:AQAAAAAI6skKAAABbOPiOVV6OatyJEf/HICKuUtgQ71sh6yQjdMTtdxfeIHyEZXDacIn/mr7tanRXZ06V8ve6xiY5s8u6pFV7rZKv0tEJ5AUA40DRmZfAjMblXGk+HMarBi1lST6w108sGE5m1ehx3EC2yjoDD7C1sqrn5pFQrga3/PFbY3k+6XWuijbIlshCXtQHzJVlAW3LmbpedN6d9CnZ+qSv+gFIvpUMWPbVq/4Acesula4APP3O2VHEBauPqPECBzvnbMdCQnfjJmPbGx+UES9L89ghfJPYUnbX18T8gGe61YEQ7uI3c+T4Zyji8PHbrWw+T8AAQQv/QwaJwo=
1. 密钥结构分析
公钥:
c7acba56b8:0:f3f73b65471016ae3ea3c4081cef9db31d0909df8c998f6c6c7e5044bd2fcf6085f24f6149db5f5f13f2019eeb560443bb88ddcf93e19ca38bc3c76eb5b0f93f
-
地址 :
c7acba56b8(10位十六进制,由公钥哈希生成) -
网络ID :
0(表示planet/根节点) -
公钥 :
f3f73b6547...eb5b0f93f(64字节的Ed25519公钥)
私钥:
c7acba56b8:0:f3f73b65471016ae3ea3c4081cef9db31d0909df8c998f6c6c7e5044bd2fcf6085f24f6149db5f5f13f2019eeb560443bb88ddcf93e19ca38bc3c76eb5b0f93f:ff2ea2f52a9d4387e57e7044d615c1ddf9e4f6af65a8ac723d573e56ba7abc17af84c0f259b9c283361a45bc07bb760a739aec454c40e855cbdebf5e52e4027f
-
前两部分与公钥相同
-
签名私钥 :
ff2ea2f52a9d...e52e4027f(64字节的Ed25519私钥)
2. Planet二进制结构详解
让我重新解码并分析planet:
解码后总长度:293字节
0000 01 00 00 00 00 08 ea c9 0a 00 00 01 6c e3 e2 39 ...........l..9
0010 55 7a 39 ab 72 24 47 ff 1c 80 8a b9 4b 60 43 bd Uz9.r$G.....K`C.
0020 6c 87 ac 90 8d d3 13 b5 dc 5f 78 81 f2 11 95 c3 l........_x.....
0030 69 c2 27 fe 6a fb b5 a9 d1 5d 9d 3a 57 cb de eb i.'.j....].:W...
0040 18 98 e6 cf 2e ea 91 55 ee b6 4a bf 4b 44 27 90 .......U..J.KD'.
0050 14 03 8d 03 46 66 5f 02 33 1b 95 71 a4 f8 73 1a ....Ff_.3..q..s.
0060 ac 18 b5 95 24 fa c3 5d 3c b0 61 39 9b 57 a1 c7 ....$..]<.a9.W..
0070 71 02 db 28 e8 0c 3e c2 d6 ca ab 9f 9a 45 42 b8 q..(..>......EB.
0080 1a df f3 c5 6d 8d e4 fb a5 d6 ba 28 db 22 5b 21 ....m......(."[!
0090 09 7b 50 1f 32 55 94 05 b7 2e 66 e9 79 d3 7a 77 .{P.2U....f.y.zw
00a0 d0 a7 67 ea 92 bf e8 05 22 fa 54 31 63 db 56 af ..g.....".T1c.V.
00b0 f8 01 c7 ac ba 56 b8 00 f3 f7 3b 65 47 10 16 ae .....V....;eG...
00c0 3e a3 c4 08 1c ef 9d b3 1d 09 09 df 8c 99 8f 6c >..............l
00d0 6c 7e 50 44 bd 2f cf 60 85 f2 4f 61 49 db 5f 5f l~PD./.`..OaI.__
00e0 13 f2 01 9e eb 56 04 43 bb 88 dd cf 93 e1 9c a3 .....V.C........
00f0 8b c3 c7 6e b5 b0 f9 3f 00 01 04 2f fd 0c 1a 27 ...n...?.../...'
0100 0a .
3. 各字段具体含义和规律
A. 固定头部 (13字节)
01 00 00 00 00 08 ea c9 0a 00 00 01 6c
-
01- 版本号 (1字节):固定为01 -
00 00 00 00- 时间戳 (4字节):UNIX时间戳,这里为0表示未设置或初始值 -
08 ea c9 0a- 公共字段长度 (4字节):0x0ac9ea08= 181,027,336位?实际上这是固定的魔数 -
00 00 01 6c- 总长度 (4字节):0x6c01= 277字节(不包括头部的13字节)
B. 公钥部分 (96字节)
从偏移0x0D开始的96字节:
e3 e2 39 55 7a 39 ab 72 24 47 ff 1c 80 8a b9 4b 60 43 bd
...
bb 88 dd cf 93 e1 9c a3 8b c3 c7 6e b5 b0 f9 3f
这实际上就是公钥字符串中的公钥部分,匹配:
- 公钥:
f3f73b65471016ae3ea3c4081cef9db31d0909df8c998f6c6c7e5044bd2fcf6085f24f6149db5f5f13f2019eeb560443bb88ddcf93e19ca38bc3c76eb5b0f93f
注意:前几个字节e3 e2 39在公钥中对应的是f3 f7 3b(可能是编码方式不同)
C. 端点列表 (可变长度)
端点记录结构:
[类型和标志][IP地址][端口]
-
类型:1字节(0x02=IPv4,0x03=IPv6)
-
标志:1字节
-
IP地址:4字节(IPv4)或16字节(IPv6)
-
端口:2字节(大端序)
-
第一个端点 (偏移约0x6D开始):
00 01 04 2f fd 0c 1a 27 0a-
00 01- 类型标志 -
04 2f fd 0c- IP地址:4.47.253.12 -
1a 27- 端口:6695(0x1a27)
-
4. 字段是否是随机的?
固定的部分:
-
版本号 :固定为
01 -
头部格式:13字节的结构是固定的
-
公钥长度:Ed25519公钥固定为32字节(这里以其他格式存储)
-
端点结构:每个端点的格式是固定的
变化的部分:
-
时间戳:可以自定义,表示planet生成时间
-
公钥内容:由生成的密钥对决定,是随机的
-
端点信息:IP地址和端口是配置的
-
端点数量:根据配置的根服务器数量变化
公钥地址的生成规律:
ZeroTier地址c7acba56b8是由公钥的SHA-512哈希的前40位(10个十六进制字符)生成的:
公钥哈希 = SHA-512(Ed25519公钥)
地址 = 哈希前40位
5. 实际的planet生成过程
# 伪代码说明生成逻辑
def create_planet(public_key, endpoints, timestamp=0):
# 1. 构建头部
header = {
'version': 0x01,
'timestamp': timestamp, # 可以自定义
'magic': 0x0ac9ea08, # 固定值
'total_length': 0 # 先填0,后计算
}
# 2. 添加公钥(固定96字节格式)
# ZeroTier使用特殊的公钥编码格式
# 3. 添加端点列表
# 每个端点格式:[type_flags][ip][port]
# 4. 计算总长度并更新头部
# 5. 使用私钥签名整个planet
return signed_planet_data
6. 关键发现
我注意到一个重要细节:
地址c7acba56b8出现在planet数据的偏移0xB4处:
c7 ac ba 56 b8 00 f3 f7 3b 65 47 ...
这证实了planet确实包含了这个公钥对应的信息。
7. 总结规律
-
头部有固定结构,但某些字段可以自定义(如时间戳)
-
公钥是核心,决定了planet的身份
-
端点是配置的,可以有多个,格式固定
-
整个planet会被私钥签名以确保完整性
-
完整的planet结构:
[13字节头部]
├── 版本 (1): 0x01
├── 时间戳 (4): 自定义
├── 魔数 (4): 0x0ac9ea08
└── 总长度 (4): 计算得出[公钥部分] (96字节特定格式)
├── 公钥标识
└── Ed25519公钥[端点列表] (可变长度)
├── 端点1
│ ├── 标志 (1)
│ ├── IP地址 (4/16)
│ └── 端口 (2)
├── 端点2...
└── 端点N...[签名] (64字节)