数字签名(Digital Signatures)

数字签名是一种基于公钥密码学的技术,用于验证数字消息或文档的真实性和完整性,提供身份认证、数据完整性和不可否认性


什么是数字签名

数字签名是基于非对称加密的一种技术,它使用私钥对数据进行”签名”,任何人都可以使用对应的公钥来验证签名的有效性。

数字签名的基本流程

签名方                              验证方
  │                                  │
  │  1. 准备要签名的消息             │
  ├─[消息]                           │
  │  2. 计算消息哈希                │
  ├─[哈希函数]                       │
  │  3. 使用私钥对哈希签名           │
  ├─[私钥签名]                       │
  │  4. 发送消息和签名               │
  ├─────────────────────────────────→│
  │                                  │
  │                                  │  5. 计算消息哈希
  │                                  ├─[哈希函数]
  │                                  │  6. 使用公钥验证签名
  │                                  ├─[公钥验证]
  │                                  │  7. 比较哈希值
  │                                  ├─[比较]
  │                                  │  8. 验证结果

数字签名的特点

  1. 身份认证:验证签名者的身份
  2. 数据完整性:确保数据未被篡改
  3. 不可否认性:签名者不能否认已签名的内容
  4. 不可伪造性:私钥保密,签名不可伪造

数字签名的数学原理

数字签名基于非对称加密算法的数学性质,主要利用公钥和私钥之间的数学关系。

基本原理

  1. 密钥对生成:生成数学上相关的公钥和私钥
  2. 签名生成:使用私钥对数据哈希进行数学运算
  3. 签名验证:使用公钥验证签名的数学有效性

数学模型

以RSA为例:

签名过程:S ≡ H(M)^d mod n
验证过程:M' ≡ S^e mod n
比较:H(M) == H(M')

其中:

  • M:原始消息
  • H(M):消息的哈希值
  • d:私钥指数
  • e:公钥指数
  • n:模数
  • S:数字签名
  • M’:验证得到的哈希值

常见数字签名算法

1. RSA签名算法

RSA签名生成与验证

  1. 密钥生成:与RSA加密相同的密钥对生成过程
  2. 签名生成
    S ≡ H(M)^d mod n
    
  3. 签名验证
    H(M) ≡ S^e mod n
    

RSA签名变体

  • RSA-PSS:概率签名方案,提供更高安全性
  • RSA-PKCS#1 v1.5:较早的填充方案,存在一些安全问题

2. 数字签名算法(DSA)

DSA由美国国家安全局(NSA)设计,是数字签名标准(DSS)的一部分。

DSA参数

  • 全局参数:p、q、g(可公开共享)
  • 私钥:x(随机数)
  • 公钥:y = g^x mod p

DSA签名生成

  1. 选择随机数:k,且0 < k < q
  2. 计算r:r = (g^k mod p) mod q
  3. 计算s:s = (H(M) + x·r)·k^(-1) mod q
  4. 签名:(r, s)

DSA签名验证

  1. 计算w:w = s^(-1) mod q
  2. 计算u1:u1 = H(M)·w mod q
  3. 计算u2:u2 = r·w mod q
  4. 计算v:v = ((g^u1·y^u2) mod p) mod q
  5. 验证:v == r

3. 椭圆曲线数字签名算法(ECDSA)

ECDSA是DSA在椭圆曲线上的实现,提供与DSA相同安全性下更小的密钥长度。

ECDSA优势

安全强度DSA/RSA密钥长度ECC密钥长度
80位1024160
112位2048224
128位3072256
192位7680384
256位15360512

ECDSA签名生成

  1. 选择随机数:k
  2. 计算点:(x1, y1) = k·G
  3. 计算r:r = x1 mod n
  4. 计算s:s = k^(-1)(H(M) + d·r) mod n
  5. 签名:(r, s)

ECDSA签名验证

  1. 计算w:w = s^(-1) mod n
  2. 计算u1:u1 = H(M)·w mod n
  3. 计算u2:u2 = r·w mod n
  4. 计算点:(x1, y1) = u1·G + u2·Q
  5. 计算v:v = x1 mod n
  6. 验证:v == r

4. EdDSA

EdDSA是一类基于扭曲爱德华兹曲线的数字签名算法,具有高效和安全的特点。

EdDSA变体

  • Ed25519:基于Curve25519,128位安全强度
  • Ed448:基于Curve448,224位安全强度

EdDSA特点

  • 确定性:签名过程不依赖随机数生成器
  • 高效:签名和验证速度快
  • 安全:抗侧信道攻击

证书与数字签名

数字证书使用数字签名将公钥与身份信息绑定。

X.509证书结构

Certificate:
    Version: 3 (0x2)
    Serial Number: [序列号]
    Signature Algorithm: [签名算法]
    Issuer: [颁发者]
    Validity:
        Not Before: [生效时间]
        Not After : [失效时间]
    Subject: [所有者]
    Subject Public Key Info:
        Public Key Algorithm: [公钥算法]
        Public Key: [公钥]
    X509v3 extensions:
        [扩展字段]
    Signature Value: [签名值]

证书签名验证

  1. 证书链验证:验证颁发者的签名直到根证书
  2. 有效期检查:检查证书是否在有效期内
  3. 撤销检查:检查证书是否已被撤销

数字签名应用

1. 软件签名

软件开发商使用数字签名验证软件的真实性和完整性。

Windows代码签名

# 使用signtool对可执行文件签名
signtool sign /f certificate.pfx /p password /t http://timestamp.digicert.com application.exe

代码签名验证

  • 操作系统检查:Windows、macOS检查代码签名
  • 浏览器验证:下载文件时的签名验证
  • 安全软件:杀毒软件的签名检查

2. 电子文档签名

对PDF、Office等文档进行数字签名。

PDF签名

# 使用PyPDF2和PyPDF2的签名功能
from PyPDF2 import PdfFileReader, PdfFileWriter
from endesive import pdf
 
def sign_pdf(input_pdf, output_pdf, cert_path, key_path):
    # 读取PDF
    with open(input_pdf, 'rb') as f:
        pdf_data = f.read()
    
    # 加载证书和密钥
    with open(cert_path, 'rb') as f:
        cert = f.read()
    with open(key_path, 'rb') as f:
        key = f.read()
    
    # 签名PDF
    signed_pdf = pdf.cms.sign(pdf_data, cert, key, [], 'sha256')
    
    # 保存签名后的PDF
    with open(output_pdf, 'wb') as f:
        f.write(signed_pdf)

3. 电子邮件签名

使用S/MIME或PGP对电子邮件进行签名和加密。

S/MIME签名

S/MIME使用X.509证书对邮件进行签名和加密。

PGP签名

PGP(Pretty Good Privacy)使用信任网络模型进行签名。

4. 区块链交易

区块链系统使用数字签名验证交易的有效性。

比特币交易签名

# 简化的比特币交易签名示例
import hashlib
import ecdsa
 
def sign_transaction(private_key, transaction_data):
    # 计算交易哈希
    transaction_hash = hashlib.sha256(transaction_data.encode()).digest()
    
    # 使用私钥签名
    sk = ecdsa.SigningKey.from_string(private_key, curve=ecdsa.SECP256k1)
    signature = sk.sign(transaction_hash)
    
    return signature
 
def verify_transaction(public_key, transaction_data, signature):
    # 计算交易哈希
    transaction_hash = hashlib.sha256(transaction_data.encode()).digest()
    
    # 使用公钥验证
    vk = ecdsa.VerifyingKey.from_string(public_key, curve=ecdsa.SECP256k1)
    try:
        vk.verify(signature, transaction_hash)
        return True
    except:
        return False

数字签名实现

1. RSA签名实现

import hashlib
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
 
def rsa_sign(private_key_path, message):
    # 加载私钥
    with open(private_key_path, 'rb') as f:
        private_key = RSA.import_key(f.read())
    
    # 计算消息哈希
    h = SHA256.new(message.encode())
    
    # 创建签名器并签名
    signer = pkcs1_15.new(private_key)
    signature = signer.sign(h)
    
    return signature
 
def rsa_verify(public_key_path, message, signature):
    # 加载公钥
    with open(public_key_path, 'rb') as f:
        public_key = RSA.import_key(f.read())
    
    # 计算消息哈希
    h = SHA256.new(message.encode())
    
    # 创建验证器并验证
    verifier = pkcs1_15.new(public_key)
    try:
        verifier.verify(h, signature)
        return True
    except:
        return False

2. ECDSA签名实现

import hashlib
from ecdsa import SigningKey, VerifyingKey, NIST256p
 
def ecdsa_sign(private_key_path, message):
    # 加载私钥
    with open(private_key_path, 'rb') as f:
        private_key = SigningKey.from_pem(f.read())
    
    # 计算消息哈希
    h = hashlib.sha256(message.encode()).digest()
    
    # 签名
    signature = private_key.sign(h, hashfunc=hashlib.sha256)
    
    return signature
 
def ecdsa_verify(public_key_path, message, signature):
    # 加载公钥
    with open(public_key_path, 'rb') as f:
        public_key = VerifyingKey.from_pem(f.read())
    
    # 计算消息哈希
    h = hashlib.sha256(message.encode()).digest()
    
    # 验证
    try:
        public_key.verify(signature, h, hashfunc=hashlib.sha256)
        return True
    except:
        return False

安全考虑

1. 哈希算法选择

  • 避免使用:MD5、SHA-1(已发现碰撞)
  • 推荐使用:SHA-256、SHA-3
  • 安全性:选择抗碰撞性强的哈希算法

2. 随机数安全

  • DSA/ECDSA:需要安全的随机数生成器
  • 随机数泄露:会导致私钥泄露
  • 确定性签名:EdDSA等算法不依赖随机数

3. 侧信道攻击

  • 时序攻击:基于签名/验证时间的攻击
  • 功耗分析:基于设备功耗的攻击
  • 防御方法:常量时间实现、添加噪声

4. 密钥管理

  • 私钥保护:私钥必须安全存储
  • 密钥备份:安全备份私钥
  • 密钥轮换:定期更新密钥

数字签名算法比较

算法密钥长度签名大小验证速度安全性特点
RSA2048+256+应用广泛
DSA2048+320+美国标准
ECDSA256+320+密钥小
EdDSA256+320+确定性

未来趋势

1. 后量子密码学

随着量子计算机的发展,传统数字签名算法面临威胁,后量子数字签名算法正在研究:

  • 基于哈希的签名:Lamport签名、Merkle树签名
  • 基于格的签名:NTRU签名、Ring-LWE签名
  • 基于编码的签名:McEliece签名
  • 基于多变量的签名:Rainbow签名

2. 区块链应用

区块链技术推动数字签名广泛应用:

  • 智能合约:使用数字签名验证交易
  • 去中心化身份:自管理身份系统
  • 资产追踪:数字资产所有权验证

🔗 相关链接


最后更新:2025-01-26 维护规范:详见 笔记规范文档

数字签名 RSA ECDSA 证书 代码签名