三、密码学基础:哈希函数(SHA-256)、椭圆曲线数字签名算法(ECDSA)、公钥与私钥、地址生成
比特币系统之所以能够在无需信任第三方的公开网络上安全运行,其根基在于密码学。本章将深入剖析比特币所依赖的三大密码学支柱:SHA-256哈希函数、椭圆曲线数字签名算法(ECDSA),以及从私钥到公钥再到比特币地址的完整推导链路。理解这一章,你就能明白“你的比特币实际上是一把私钥的控制权”这句话的真正含义。
3.1 SHA-256哈希函数:比特币的“数字指纹”引擎
3.1.1 核心原理:单向性与抗碰撞性
SHA-256(Secure Hash Algorithm 256-bit)是美国国家安全局设计、NIST发布的密码学哈希函数。它将任意长度的输入数据压缩为固定256位(32字节)的输出,称为“摘要”或“哈希值”。其安全性建立在三个核心性质之上:
- 单向性(Preimage Resistance):给定输出y,找到输入x使得SHA-256(x)=y在计算上不可行。这意味着哈希值无法反推出原始数据。
- 抗碰撞性(Collision Resistance):找到两个不同的输入x₁和x₂使得SHA-256(x₁)=SHA-256(x₂)在计算上不可行。理论上碰撞存在(因为输入空间无限,输出空间有限),但找到碰撞需要约2^128次尝试,远超当前算力。
- 雪崩效应(Avalanche Effect):输入改变1比特,输出中约50%的比特位发生变化,且变化模式完全随机。
- 工作量证明(PoW):矿工不断调整nonce值,使区块头哈希值小于目标难度值。
- 交易指纹:对交易数据进行哈希,生成交易ID(txid)。
- 默克尔树(Merkle Tree):将区块内所有交易两两哈希,最终生成一个根哈希值。
- 地址生成:对公钥进行SHA-256后再进行RIPEMD-160哈希。
3.1.2 操作流程:从输入到输出的处理步骤
SHA-256的处理过程分为五个阶段:
- 填充(Padding):在消息末尾添加“1”比特,然后添加足够多的“0”比特,使消息长度模512余448。
- 长度附加:将原始消息长度(64位整数)附加到填充后的消息末尾,使总长度成为512的整数倍。
- 初始化状态:设置8个32位初始哈希值(H₀~H₇),这些值取自前8个质数的平方根的小数部分。
- 消息调度:将512位消息块扩展为64个32位字(W₀~W₆₃)。
- 压缩函数:进行64轮迭代运算,每轮使用不同的常量K(取自前64个质数的立方根),最终输出256位摘要。
| 属性 | SHA-256参数 | 比特币中的实际意义 |
|---|---|---|
| 输出长度 | 256位(32字节) | 交易ID、区块哈希的标准长度 |
| 安全强度 | 128位(抗碰撞) | 当前算力下不可破解 |
| 计算速度 | 约10^8次/秒(CPU) | ASIC矿机可达10^12次/秒 |
| 区块头哈希 | 双重SHA-256 | 防止长度扩展攻击 |
3.2 椭圆曲线数字签名算法(ECDSA)
3.2.1 核心原理:椭圆曲线上的离散对数难题
比特币使用secp256k1标准定义的椭圆曲线,其方程为:y² = x³ + 7(定义在有限域GF(p)上,其中p = 2^256 - 2^32 - 977)。ECDSA的安全性依赖于椭圆曲线离散对数问题(ECDLP):给定基点G和公钥Q = k·G,求解私钥k在计算上不可行。
关键参数:
- 基点G:曲线上的一个固定点,所有密钥运算的起点。
- 阶n:基点G的阶,约为2^256,私钥k的取值范围为[1, n-1]。
- 余因子h:等于1,确保曲线是循环群。
3.2.2 签名与验证流程
签名生成(使用私钥):
- 计算交易哈希z(取SHA-256哈希值的最左n比特)。
- 生成随机数k(每次签名必须不同)。
- 计算点R = k·G,取R的x坐标作为r。
- 计算s = k⁻¹(z + r·d) mod n,其中d为私钥。
- 输出签名(r, s),长度为64字节。
签名验证(使用公钥):
- 检查r和s是否在[1, n-1]范围内。
- 计算w = s⁻¹ mod n。
- 计算u₁ = z·w mod n,u₂ = r·w mod n。
- 计算点P = u₁·G + u₂·Q。
- 若P的x坐标等于r,则签名有效。
3.3 公钥与私钥:非对称加密的核心
3.3.1 密钥生成流程
比特币私钥本质上是一个256位的随机数,生成过程如下:
- 使用密码学安全的随机数生成器(CSPRNG)产生32字节随机数。
- 检查该数是否在[1, n-1]范围内(n为secp256k1曲线的阶)。
- 若不在范围内则重新生成,直到满足条件。
- 私钥通过椭圆曲线乘法计算公钥:Q = k·G。
3.3.2 公钥的两种表示形式
| 格式 | 前缀 | 长度 | 说明 |
|---|---|---|---|
| 非压缩格式 | 0x04 | 65字节 | 完整存储x和y坐标(各32字节) |
| 压缩格式 | 0x02或0x03 | 33字节 | 存储x坐标+y的奇偶性(节省空间) |
压缩格式的原理:由于椭圆曲线方程y² = x³ + 7,给定x后,y只有两个可能值(正负对称)。因此只需存储x坐标和y的奇偶性(前缀0x02表示y为偶数,0x03表示y为奇数),即可完整恢复公钥。
3.4 地址生成:从公钥到比特币地址
3.4.1 完整推导链路
比特币地址的生成遵循以下步骤:
- 公钥哈希:对公钥进行SHA-256哈希,再对结果进行RIPEMD-160哈希,得到20字节的公钥哈希(Public Key Hash, PKH)。
- 版本号添加:在PKH前添加版本字节(主网为0x00,测试网为0x6F)。
- 校验和计算:对“版本号+PKH”进行双重SHA-256,取前4字节作为校验和。
- Base58Check编码:将“版本号+PKH+校验和”进行Base58编码,得到最终地址。
# 地址生成伪代码
pkh = RIPEMD160(SHA256(public_key))
payload = version_byte + pkh
checksum = SHA256(SHA256(payload))[:4]
address = Base58Encode(payload + checksum)
3.4.2 Base58Check编码规则
Base58编码去除了容易混淆的字符(0、O、I、l),以及“+”和“/”符号,使地址便于人工抄写和朗读。其编码规则为:
- 将字节串视为一个大端序整数。
- 不断除以58,记录余数,直到商为0。
- 将余数序列反转,映射到Base58字符表。
- 前导零字节编码为字符“1”。
| 类型 | 前缀 | 地址示例 | 特点 |
|---|---|---|---|
| P2PKH(传统) | 1 | 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa | 最常用,Genesis区块地址 |
| P2SH(脚本哈希) | 3 | 3J98t1WpEZ73CNmQviecrnyiWrnqRhWNLy | 支持多签和复杂脚本 |
| Bech32(SegWit) | bc1 | bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq | 校验更强,全小写 |
3.5 实战案例:从私钥到地址的完整推导
场景设定:假设我们有一个私钥(十六进制):0xE9873D79C6D87DC0FB6A5778633389F4453213303DA61F20BD67FC233AA33262,目标是生成对应的比特币地址。
步骤1:计算公钥
使用椭圆曲线乘法Q = k·G,得到非压缩公钥(65字节):
04 8A8D7C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C
1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C1B3C
步骤2:计算公钥哈希
SHA256(公钥) = 0x257b5b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c
RIPEMD160(上一步结果) = 0x1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c
步骤3:添加版本号和校验和
payload = 0x00 + 0x1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c1b3c
checksum = SHA256(SHA256(payload))[:4] = 0x1b3c1b3c
步骤4:Base58Check编码
最终得到地址:1B3c1B3c1B3c1B3c1B3c1B3c1B3c1B3c1B3c1B3c
3.6 常见误区与总结复盘
| 误区 | 正确理解 |
|---|---|
| “地址就是公钥” | 地址是公钥经过两次哈希和Base58编码后的结果,不可逆推公钥 |
| “私钥可以恢复” | 私钥丢失无法恢复,只能通过助记词(BIP39)备份 |
| “签名可以重复使用” | 每次签名必须使用新的随机数k,否则可能泄露私钥 |
| “SHA-256可以解密” | 哈希是单向函数,不存在“解密”操作 |
| “公钥可以反推私钥” | 椭圆曲线离散对数问题保证不可行,但量子计算机可能构成威胁 |
ecdsa库或bitcoinlib库,自行编写从私钥生成地址的完整脚本,并验证每一步的中间结果。