高级 #crypto#signature#pki

数字签名与证书

数字签名用私钥签名、公钥验签——保证数据的完整性和来源可信。数字证书(X.509)把公钥和身份绑定起来,由 CA 签发

✍️ 现实中的签名——和数字签名

你在一份合同上签上自己的名字——这表示”我同意这份内容”、“是我本人的意愿”。

现实签名有三大作用:

  1. 真实性:签名是你写的,不是别人伪造的
  2. 不可否认:你签了就赖不掉
  3. 完整性:签完后合同内容不能改

数字签名(Digital Signature) 就是电子世界的”签名”——它用密码学的方式实现同样的三个目标。

📐 数字签名的核心

  • 签名方:用私钥对消息签名
  • 验证方:用公钥验证签名是否有效
  • 只有私钥持有者能签名——但所有人都能用公钥验证

🔄 签名和加密——方向相反

加密:用公钥加密 → 只有私钥持有者能解密(保密)
签名:用私钥签名 → 所有人都能用公钥验证(认证)

加密:公钥锁 → 私钥开
签名:私钥锁 → 公钥开

签名过程

# 数字签名的简化流程

import hashlib

def sign(message, private_key):
    # 1. 计算消息的哈希值
    h = hashlib.sha256(message.encode()).digest()
    
    # 2. 用私钥加密哈希值(这就是"签名")
    signature = rsa_sign(h, private_key)
    
    return message + signature

def verify(message_with_sig, public_key):
    message = message_with_sig[:-256]  # 去掉签名
    signature = message_with_sig[-256:]  # 提取签名
    
    # 1. 重新计算消息的哈希值
    h = hashlib.sha256(message.encode()).digest()
    
    # 2. 用公钥解密签名,对比哈希值
    return rsa_verify(h, signature, public_key)

关键点:先哈希再签名——不是对整个消息签名(消息可能很大,RSA 也加密不了大数据),而是对消息的”指纹”签名。

为什么数字签名能保证三个目标?

1. 真实性: 
   签名是用私钥生成的——只有私钥持有者能产生有效签名
   用公钥验证通过 → 一定是私钥持有者签的

2. 不可否认: 
   只有你知道私钥——你不能说"这不是我签的"

3. 完整性:
   签名包含消息的哈希值
   消息改了 → 哈希值和签名不一致 → 验证失败

🏛️ PKI——谁来保证公钥是真的?

数字签名依赖公钥——但你怎么确定某个公钥确实是”张三”的,而不是攻击者的?

这就是PKI(Public Key Infrastructure,公钥基础设施) 解决的问题。

CA(证书机构)

CA(Certificate Authority)是”公钥的公证处”——它验证申请人的身份,然后签发一个数字证书(Digital Certificate)

数字证书(X.509 格式)包含:
├── 主体信息:谁(域名、组织名)
├── 公钥:这个主体的公钥
├── 签发者:哪个 CA 签发的
├── 有效期:从 X 到 Y
└── CA 的数字签名:证明上述信息是真实的
# 证书验证链:
# 当你访问 https://example.com:
# 1. 服务器发给你它的证书(包含它的公钥,由 CA 签名)
# 2. 你的浏览器检查 CA 的签名是否有效
# 3. 如果有效——你信任这个公钥确实是 example.com 的
# 4. 用这个公钥建立加密连接

证书链

CA 自己也需要被验证——所以有根 CA(Root CA)

Root CA(自签名——预装在操作系统中)
    ↓ 签发
中间 CA
    ↓ 签发
服务器证书(example.com)

操作系统和浏览器里预装了几十个根 CA 的证书——它们自己签自己(自签名),是世界公认的信任锚点。

🏪 **类比:身份证”

你拿出一张身份证给警察看——警察怎么知道身份证是真的?

因为:身份证由公安局(CA) 签发,公安局的印章(CA 签名)无法伪造,警察信任公安局。

如果警察不认识你所在的公安局——他可以追溯到”公安部(根 CA)“确认。


🔒 实际应用:HTTPS

当你访问 https://example.com:

1. 你在浏览器输入 https://example.com
2. 服务器把证书发给你
3. 浏览器检查证书:
   a. 是不是在有效期内?
   b. 是不是被吊销了?
   c. CA 的签名对不对?
   d. 域名是不是 example.com?
4. 验证通过 → 地址栏出现 🔒
5. 建立加密连接
# 用 OpenSSL 查看网站的证书
openssl s_client -connect example.com:443

# 输出包含:
# Certificate chain
#  0 s:/CN=example.com    ← 服务器证书
#  1 s:/CN=R3             ← 中间 CA
#  2 s:/CN=ISRG Root X1   ← 根 CA

📝 小结

概念一句话
数字签名私钥签名 + 公钥验签——认证、不可否认、完整性
签名 = 对哈希签名先哈希再签名——高效且无大小限制
数字证书把公钥绑定到身份——由 CA 签发
CA(证书机构)受信任的第三方——验证身份后签发证书
根 CA预装在操作系统中的信任锚点
证书链Root CA → 中间 CA → 服务器证书——逐级验证

🎯 思考题:如果某个根 CA 被攻击者攻破了(私钥泄露了)——攻击者能做什么?这对整个互联网安全意味着什么?

为什么先学这个? 签名和证书是 SSL/TLS 的基础——密码协议(SSL/TLS)