Programming Bitcoin 第四章:序列化技术详解
概述
在区块链开发中,序列化是将复杂数据结构转换为字节流的过程,这对于网络传输和存储至关重要。本章将深入探讨区块链系统中几种关键的序列化格式,包括SEC公钥格式、DER签名格式以及Base58地址编码。
SEC公钥序列化格式
未压缩SEC格式
椭圆曲线数字签名算法(ECDSA)的公钥本质上是曲线上的一个坐标点(x,y)。未压缩SEC格式序列化方法如下:
- 前缀字节固定为0x04
- 追加32字节大端序编码的x坐标
- 追加32字节大端序编码的y坐标
Python实现示例:
def sec(self):
return b'\x04' + self.x.num.to_bytes(32, 'big') + self.y.num.to_bytes(32, 'big')
这种格式总长度为65字节(1+32+32),效率较低但实现简单。
压缩SEC格式
利用椭圆曲线的对称性,y坐标只可能是两个值之一且奇偶性相反。压缩格式仅存储x坐标和y的奇偶性:
- 前缀字节:y为偶数用0x02,奇数用0x03
- 追加32字节大端序编码的x坐标
Python实现关键点:
def sec(self, compressed=True):
if compressed:
prefix = b'\x02' if self.y.num % 2 == 0 else b'\x03'
return prefix + self.x.num.to_bytes(32, 'big')
...
这种格式仅需33字节,节省了近50%的空间。要从压缩格式恢复完整坐标,需要使用有限域平方根计算:
def sqrt(self):
return self**((P + 1) // 4)
DER签名序列化格式
区块链签名(r,s)使用DER(Distinguished Encoding Rules)格式序列化:
- 起始标志0x30
- 后续数据长度
- r值标记0x02
- 大端序编码的r值(必要时补0x00)
- s值标记0x02
- 大端序编码的s值(必要时补0x00)
Python实现示例:
def der(self):
rbin = self.r.to_bytes(32, 'big').lstrip(b'\x00')
if rbin[0] & 0x80:
rbin = b'\x00' + rbin
sbin = self.s.to_bytes(32, 'big').lstrip(b'\x00')
if sbin[0] & 0x80:
sbin = b'\x00' + sbin
result = bytes([2, len(rbin)]) + rbin + bytes([2, len(sbin)]) + sbin
return bytes([0x30, len(result)]) + result
DER格式虽然标准但效率不高,每个签名至少需要6字节额外开销。
Base58地址编码
Base58编码原理
为解决二进制数据可读性问题,区块链采用Base58编码,特点:
- 排除易混淆字符(0/O, l/I)
- 包含校验和
- 比Base64更安全可靠
编码过程:
- 统计前导零字节数量
- 将数值转换为58进制
- 映射到Base58字符集
- 补回前导'1'
Python实现:
def encode_base58(s):
count = 0
for c in s:
if c == 0:
count += 1
else:
break
num = int.from_bytes(s, 'big')
prefix = '1' * count
result = ''
while num > 0:
num, mod = divmod(num, 58)
result = BASE58_ALPHABET[mod] + result
return prefix + result
区块链地址生成
完整地址生成流程:
- 主网前缀0x00,测试网0x6f
- 对SEC格式公钥进行hash160(先sha256再ripemd160)
- 组合前缀和hash160结果
- 计算前4字节校验和(双重sha256)
- Base58编码最终结果
Python实现关键方法:
def hash160(self, compressed=True):
return hash160(self.sec(compressed))
def address(self, compressed=True, testnet=False):
h160 = self.hash160(compressed)
prefix = b'\x6f' if testnet else b'\x00'
return encode_base58_checksum(prefix + h160)
WIF私钥格式
私钥的Wallet Import Format序列化:
- 主网前缀0x80,测试网0xef
- 32字节大端序私钥
- 压缩标志0x01(如使用压缩公钥)
- 4字节校验和
- Base58编码
技术要点总结
-
大端序与小端序:区块链中不同数据采用不同字节序,SEC格式使用大端序而交易版本号使用小端序
-
有限域计算:压缩公钥恢复依赖有限域平方根计算,当p ≡ 3 mod 4时可高效计算
-
编码演进:Base58正逐渐被Bech32取代,后者具有更好的错误检测能力
-
空间优化:压缩SEC格式节省空间,这对区块链 scalability 至关重要
理解这些序列化技术是开发区块链应用的基础,它们影响着交易大小、网络带宽和存储效率等关键指标。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考