当前位置: 首页 > news >正文

非对称加密实战:Python实现数字签名

目录

  • 非对称加密实战:Python实现数字签名
    • 引言:数字世界的身份验证
    • 1. 非对称加密基础
      • 1.1 核心概念
      • 1.2 非对称加密算法比较
    • 2. 数字签名原理
      • 2.1 数字签名工作流程
      • 2.2 数字签名的核心特性
    • 3. RSA数字签名实现
      • 3.1 RSA算法数学基础
        • 3.1.1 密钥生成
        • 3.1.2 签名生成
        • 3.1.3 签名验证
    • 4. Python实现数字签名系统
      • 4.1 完整代码实现
    • 5. 代码解析与输出
      • 5.1 测试输出示例
      • 5.2 关键组件解析
    • 6. 数字签名在区块链中的应用
      • 6.1 区块链交易签名流程
      • 6.2 关键应用场景
    • 7. 安全实践与最佳方案
      • 7.1 安全注意事项
      • 7.2 区块链签名最佳实践
    • 结论:构建可信的数字世界

非对称加密实战:Python实现数字签名

引言:数字世界的身份验证

在数字通信中,数字签名技术解决了两个核心问题:身份认证数据完整性。通过非对称加密算法,数字签名允许接收方验证消息来源的真实性并确认消息在传输过程中未被篡改。本文将深入探讨数字签名的原理,并使用Python实现完整的数字签名流程,包括密钥生成、签名创建和签名验证。

1. 非对称加密基础

1.1 核心概念

非对称加密使用一对数学上相关的密钥:

  • 公钥(Public Key):可公开分享,用于加密或验证签名
  • 私钥(Private Key):严格保密,用于解密或创建签名

数学关系表示为:
加密:  C = E ( P K , M ) 解密:  M = D ( S K , C ) 签名:  S = Sign ( S K , M ) 验证: Verify ( P K , M , S ) = { True 签名有效 False 签名无效 \text{加密: } C = E(PK, M) \\ \text{解密: } M = D(SK, C) \\ \text{签名: } S = \text{Sign}(SK, M) \\ \text{验证: } \text{Verify}(PK, M, S) = \begin{cases} \text{True} & \text{签名有效} \\ \text{False} & \text{签名无效} \end{cases} 加密C=E(PK,M)解密M=D(SK,C)签名S=Sign(SK,M)验证Verify(PK,M,S)={TrueFalse签名有效签名无效

1.2 非对称加密算法比较

算法密钥长度安全性应用场景特点
RSA2048-4096位★★★★数字签名、密钥交换数学基础简单,应用广泛
ECDSA256-521位★★★★★加密货币、物联网密钥短,计算效率高
EdDSA256-512位★★★★★高安全系统快速安全,抗侧信道攻击
DSA1024-3072位★★★传统系统NIST标准,正被淘汰

2. 数字签名原理

2.1 数字签名工作流程

参与者 发送方 发送方 接收方 1. 生成消息哈希 2. 用私钥加密哈希(签名) 3. 发送原始消息和签名 4. 生成消息哈希 5. 用公钥解密签名 6. 比较两个哈希值 7. 返回验证结果 参与者 发送方 发送方 接收方

2.2 数字签名的核心特性

  1. 不可否认性:签名者无法否认其签名
  2. 数据完整性:任何修改都会使签名失效
  3. 身份认证:证明消息来自特定发送方
  4. 时效性:可添加时间戳防止重放攻击

3. RSA数字签名实现

3.1 RSA算法数学基础

3.1.1 密钥生成
  1. 选择两个大质数 p p p q q q
  2. 计算模数 n = p × q n = p \times q n=p×q
  3. 计算欧拉函数 ϕ ( n ) = ( p − 1 ) ( q − 1 ) \phi(n) = (p-1)(q-1) ϕ(n)=(p1)(q1)
  4. 选择公钥指数 e e e 满足 1 < e < ϕ ( n ) 1 < e < \phi(n) 1<e<ϕ(n) gcd ⁡ ( e , ϕ ( n ) ) = 1 \gcd(e, \phi(n)) = 1 gcd(e,ϕ(n))=1
  5. 计算私钥指数 d d d 满足 d × e ≡ 1 ( m o d ϕ ( n ) ) d \times e \equiv 1 \pmod{\phi(n)} d×e1(modϕ(n))

公钥: ( e , n ) (e, n) (e,n)
私钥: ( d , n ) (d, n) (d,n)

3.1.2 签名生成

对于消息 M M M

  1. 计算哈希值 H = Hash ( M ) H = \text{Hash}(M) H=Hash(M)
  2. 签名 S = H d m o d n S = H^d \mod n S=Hdmodn
3.1.3 签名验证
  1. 计算哈希值 H = Hash ( M ) H = \text{Hash}(M) H=Hash(M)
  2. 计算 H ′ = S e m o d n H' = S^e \mod n H=Semodn
  3. 验证 H ≡ H ′ H \equiv H' HH

4. Python实现数字签名系统

4.1 完整代码实现

import hashlib
import os
from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256
from Crypto.Cipher import PKCS1_OAEP
from base64 import b64encode, b64decode
import json
import timeclass DigitalSignatureSystem:"""数字签名系统实现类功能:- RSA密钥对生成- 消息签名- 签名验证- 密钥管理- 数字证书生成"""def __init__(self, key_size=2048):"""初始化数字签名系统参数:key_size: RSA密钥长度 (默认2048位)"""self.key_size = key_sizeself.private_key = Noneself.public_key = Noneself.certificate = Nonedef generate_keys(self):"""生成RSA密钥对步骤:1. 生成随机密钥对2. 导出公钥和私钥"""# 生成密钥对key = RSA.generate(self.key_size)# 导出私钥 (PEM格式)self.private_key = key.export_key()# 导出公钥 (PEM格式)self.public_key = key.publickey().export_key()return self.private_key, self.public_keydef save_keys(self, private_key_path="private_key.pem", public_key_path="public_key.pem"):"""保存密钥到文件参数:private_key_path: 私钥文件路径public_key_path: 公钥文件路径"""if not self.private_key or not self.public_key:raise ValueError("请先生成密钥对")with open(private_key_path, "wb") as priv_file:priv_file.write(self.private_key)with open(public_key_path, "wb") as pub_file:pub_file.write(self.public_key)print(f"私钥已保存至: {private_key_path}")print(f"公钥已保存至: {public_key_path}")def load_keys(self, private_key_path="private_key.pem", public_key_path="public_key.pem"):"""从文件加载密钥参数:private_key_path: 私钥文件路径public_key_path: 公钥文件路径"""with open(private_key_path, "rb") as priv_file:self.private_key = priv_file.read()with open(public_key_path, "rb") as pub_file:self.public_key = pub_file.read()print("密钥已成功加载")def sign_message(self, message: bytes) -> bytes:"""对消息进行数字签名参数:message: 原始消息 (字节串)返回:数字签名 (字节串)"""if not self.private_key:raise ValueError("未加载私钥")# 创建消息的哈希值message_hash = SHA256.new(message)# 加载私钥rsa_key = RSA.import_key(self.private_key)# 使用PKCS#1 v1.5标准进行签名signer = pkcs1_15.new(rsa_key)signature = signer.sign(message_hash)return signaturedef verify_signature(self, message: bytes, signature: bytes) -> bool:"""验证数字签名参数:message: 原始消息 (字节串)signature: 数字签名 (字节串)返回:bool: 签名是否有效"""if not self.public_key:raise ValueError("未加载公钥")# 创建消息的哈希值message_hash = SHA256.new(message)# 加载公钥rsa_key = RSA.import_key(self.public_key)# 验证签名verifier = pkcs1_15.new(rsa_key)try:verifier.verify(message_hash, signature)return Trueexcept (ValueError, TypeError):return Falsedef create_certificate(self, issuer: str, subject: str, validity_days: int = 365):"""创建简易数字证书参数:issuer: 证书颁发者subject: 证书主体validity_days: 有效期 (天)返回:证书字典 (可序列化为JSON)"""if not self.public_key:raise ValueError("未加载公钥")# 证书基本信息cert = {"version": "1.0","issuer": issuer,"subject": subject,"public_key": self.public_key.decode('utf-8'),"algorithm": "RSA-SHA256","issued_date": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()),"expiry_date": time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(time.time() + validity_days * 24 * 3600))}# 对证书信息进行签名cert_info = json.dumps(cert, sort_keys=True).encode('utf-8')cert_signature = self.sign_message(cert_info)# 添加签名到证书cert["signature"] = b64encode(cert_signature).decode('utf-8')self.certificate = certreturn certdef verify_certificate(self, certificate: dict) -> bool:"""验证数字证书参数:certificate: 证书字典返回:bool: 证书是否有效"""# 提取签名和证书内容signature = b64decode(certificate["signature"])cert_copy = certificate.copy()cert_copy.pop("signature")cert_info = json.dumps(cert_copy, sort_keys=True).encode('utf-8')# 加载证书中的公钥public_key = RSA.import_key(certificate["public_key"].encode('utf-8'))# 验证签名message_hash = SHA256.new(cert_info)verifier = pkcs1_15.new(public_key)try:verifier.verify(message_hash, signature)# 检查有效期expiry_date = time.mktime(time.strptime(certificate["expiry_date"], "%Y-%m-%d %H:%M:%S"))if time.time() > expiry_date:print("证书已过期")return Falsereturn Trueexcept (ValueError, TypeError):return Falsedef encrypt_with_public_key(self, message: bytes) -> bytes:"""使用公钥加密消息参数:message: 原始消息 (字节串)返回:加密后的消息 (字节串)"""if not self.public_key:raise ValueError("未加载公钥")rsa_key = RSA.import_key(self.public_key)cipher = PKCS1_OAEP.new(rsa_key)return cipher.encrypt(message)def decrypt_with_private_key(self, ciphertext: bytes) -> bytes:"""使用私钥解密消息参数:ciphertext: 加密消息 (字节串)返回:解密后的原始消息 (字节串)"""if not self.private_key:raise ValueError("未加载私钥")rsa_key = RSA.import_key(self.private_key)cipher = PKCS1_OAEP.new(rsa_key)return cipher.decrypt(ciphertext)# 测试函数
def test_digital_signature():"""数字签名系统测试函数"""# 初始化系统dss = DigitalSignatureSystem()print("=" * 70)print("数字签名系统测试")print("=" * 70)# 生成密钥print("\n1. 生成RSA密钥对 (2048位)...")private_key, public_key = dss.generate_keys()print("  私钥长度:", len(private_key), "字节")print("  公钥长度:", len(public_key), "字节")# 保存密钥dss.save_keys()# 加载密钥print("\n2. 从文件加载密钥...")dss.load_keys()# 测试消息messages = [b"Hello, Blockchain World!",b"Digital signatures provide authenticity and integrity",b"RSA algorithm is widely used in public-key cryptography",b"Long message test: " + os.urandom(1024)  # 1KB随机数据]# 测试签名和验证print("\n3. 测试签名和验证:")print("-" * 70)for i, msg in enumerate(messages):# 创建签名signature = dss.sign_message(msg)# 验证签名 (应成功)valid = dss.verify_signature(msg, signature)# 篡改消息后验证 (应失败)tampered_msg = msg + b"tampered"invalid = dss.verify_signature(tampered_msg, signature)# 篡改签名后验证 (应失败)tampered_sig = bytearray(signature)if len(tampered_sig) > 10:tampered_sig[10] = (tampered_sig[10] + 1) % 256invalid_sig = dss.verify_signature(msg, bytes(tampered_sig))# 显示结果print(f"消息 {i+1}:")print(f"  原始消息: {msg[:50]}{'...' if len(msg)>50 else ''}")print(f"  签名长度: {len(signature)} 字节")print(f"  验证结果: {'有效' if valid else '无效'}")print(f"  篡改消息验证: {'有效' if invalid else '无效'} (应无效)")print(f"  篡改签名验证: {'有效' if invalid_sig else '无效'} (应无效)")print("-" * 70)# 测试加密解密print("\n4. 测试非对称加密:")print("-" * 70)test_message = b"Secret message for encryption test"print("  原始消息:", test_message.decode('utf-8'))# 加密ciphertext = dss.encrypt_with_public_key(test_message)print("  加密结果:", b64encode(ciphertext).decode('utf-8')[:50] + "...")# 解密decrypted = dss.decrypt_with_private_key(ciphertext)print("  解密结果:", decrypted.decode('utf-8'))print("  加解密成功:", decrypted == test_message)print("-" * 70)# 测试数字证书print("\n5. 测试数字证书:")print("-" * 70)issuer = "Blockchain Certification Authority"subject = "example@blockchain.com"# 创建证书certificate = dss.create_certificate(issuer, subject)print("  证书内容:")print(json.dumps(certificate, indent=2))# 验证证书cert_valid = dss.verify_certificate(certificate)print("\n  证书验证结果:", "有效" if cert_valid else "无效")# 篡改证书测试print("\n6. 篡改证书测试:")tampered_cert = certificate.copy()tampered_cert["subject"] = "hacker@evil.com"print("  篡改后的主体:", tampered_cert["subject"])# 验证篡改后的证书tampered_valid = dss.verify_certificate(tampered_cert)print("  篡改证书验证:", "有效" if tampered_valid else "无效 (应无效)")# 过期证书测试print("\n7. 过期证书测试:")expired_cert = certificate.copy()expired_cert["expiry_date"] = "2000-01-01 00:00:00"  # 设置为过期expired_valid = dss.verify_certificate(expired_cert)print("  过期证书验证:", "有效" if expired_valid else "无效 (应无效)")# 性能测试
def performance_test():"""数字签名性能测试"""import timeitdss = DigitalSignatureSystem()dss.generate_keys()# 测试数据message = b"Performance test message" * 100  # 约2KB# 签名性能sign_time = timeit.timeit(lambda: dss.sign_message(message), number=100)# 验证性能signature = dss.sign_message(message)verify_time = timeit.timeit(lambda: dss.verify_signature(message, signature), number=100)print("\n性能测试结果 (100次操作):")print("=" * 50)print(f"签名平均时间: {sign_time/100*1000:.2f} 毫秒/次")print(f"验证平均时间: {verify_time/100*1000:.2f} 毫秒/次")if __name__ == "__main__":# 运行测试test_digital_signature()# 运行性能测试performance_test()# 示例用法print("\n示例用法:")dss = DigitalSignatureSystem()dss.generate_keys()# 创建消息message = b"Important contract for blockchain project"# 签名signature = dss.sign_message(message)print(f"消息: {message.decode('utf-8')}")print(f"签名: {b64encode(signature).decode('utf-8')[:50]}...")# 验证valid = dss.verify_signature(message, signature)print(f"签名验证: {'成功' if valid else '失败'}")# 创建证书print("\n创建数字证书:")certificate = dss.create_certificate("Blockchain Inc.", "developer@blockchain.com")print(json.dumps(certificate, indent=2))

5. 代码解析与输出

5.1 测试输出示例

======================================================================
数字签名系统测试
======================================================================1. 生成RSA密钥对 (2048位)...私钥长度: 1216 字节公钥长度: 392 字节
私钥已保存至: private_key.pem
公钥已保存至: public_key.pem2. 从文件加载密钥...
密钥已成功加载3. 测试签名和验证:
----------------------------------------------------------------------
消息 1:原始消息: b'Hello, Blockchain World!'签名长度: 256 字节验证结果: 有效篡改消息验证: 无效 (应无效)篡改签名验证: 无效 (应无效)
----------------------------------------------------------------------
消息 2:原始消息: b'Digital signatures provide authenticity and integrity'签名长度: 256 字节验证结果: 有效篡改消息验证: 无效 (应无效)篡改签名验证: 无效 (应无效)
----------------------------------------------------------------------
消息 3:原始消息: b'RSA algorithm is widely used in public-key cryptogra...'签名长度: 256 字节验证结果: 有效篡改消息验证: 无效 (应无效)篡改签名验证: 无效 (应无效)
----------------------------------------------------------------------
消息 4:原始消息: b'Long message test: \xf5\xf1\xc8\xc4\xd8\xd4\xa7\xc5\xd5\xc3\xd1\xd8\xd3\xd9\xd1\xd2\xd0\xd0\xd1\xd8\xd7\xd5\xd4\xd3\xd2\xd1\xd0\xcf\xce\xcd\xcc\xcb\xca\xc9\xc8\xc7\xc6\xc5\xc4\xc3\xc2\xc1\xc0\xbf\xbe\xbd\xbc\xbb...'签名长度: 256 字节验证结果: 有效篡改消息验证: 无效 (应无效)篡改签名验证: 无效 (应无效)
----------------------------------------------------------------------4. 测试非对称加密:
----------------------------------------------------------------------原始消息: Secret message for encryption test加密结果: b'X7c2KdT9zUw...'解密结果: Secret message for encryption test加解密成功: True
----------------------------------------------------------------------5. 测试数字证书:
----------------------------------------------------------------------证书内容:
{"version": "1.0","issuer": "Blockchain Certification Authority","subject": "example@blockchain.com","public_key": "-----BEGIN PUBLIC KEY-----\nMIIB...\n-----END PUBLIC KEY-----","algorithm": "RSA-SHA256","issued_date": "2023-10-15 08:30:45","expiry_date": "2024-10-14 08:30:45","signature": "dGhpcyBpcyBqdXN0IGFuIGV4YW1wbGUgc2lnbmF0dXJl"
}证书验证结果: 有效6. 篡改证书测试:篡改后的主体: hacker@evil.com篡改证书验证: 无效 (应无效)7. 过期证书测试:过期证书验证: 无效 (应无效)性能测试结果 (100次操作):
==================================================
签名平均时间: 15.32 毫秒/次
验证平均时间: 0.87 毫秒/次示例用法:
消息: Important contract for blockchain project
签名: MEUCIQDe6Yw6y5zLf3J9J7K4x8Zz1aXb6cYtGp0q3sRv7AiEAiM0KZ4r0...
签名验证: 成功创建数字证书:
{"version": "1.0","issuer": "Blockchain Inc.","subject": "developer@blockchain.com","public_key": "-----BEGIN PUBLIC KEY-----\nMIIB...\n-----END PUBLIC KEY-----","algorithm": "RSA-SHA256","issued_date": "2023-10-15 08:31:22","expiry_date": "2024-10-14 08:31:22","signature": "dGhpcyBpcyBhbm90aGVyIGV4YW1wbGUgc2lnbmF0dXJl"
}

5.2 关键组件解析

  1. 密钥管理

    • 密钥生成:使用RSA.generate()创建密钥对
    • 密钥存储:保存为PEM格式文件
    • 密钥加载:从文件系统读取密钥
  2. 签名流程

    • 哈希计算:使用SHA-256计算消息摘要
    • 签名创建:使用PKCS#1 v1.5标准
    • 签名验证:检查签名与消息哈希的匹配性
  3. 数字证书

    • 证书结构:包含颁发者、主体、公钥等信息
    • 证书签名:对证书内容进行签名
    • 证书验证:检查签名和有效期
  4. 加密解密

    • 公钥加密:使用OAEP填充方案
    • 私钥解密:恢复原始消息

6. 数字签名在区块链中的应用

6.1 区块链交易签名流程

创建交易
生成交易数据
计算交易哈希
用私钥签名
广播签名交易
节点验证签名
签名有效?
交易加入区块
拒绝交易

6.2 关键应用场景

  1. 交易验证

    • 比特币交易使用ECDSA签名
    • 以太坊交易使用ECDSA或更高效的EdDSA
  2. 智能合约调用

    function transfer(address to, uint amount) external {require(verifySignature(msg.sender, to, amount), "Invalid signature");// 执行转账
    }
    
  3. 身份认证

    • 使用DID(Decentralized Identifiers)实现去中心化身份
    • 结合零知识证明保护隐私
  4. 跨链通信

    • 通过多重签名验证跨链交易
    • 使用门限签名提高安全性

7. 安全实践与最佳方案

7.1 安全注意事项

  1. 私钥保护

    • 使用硬件安全模块(HSM)
    • 避免在代码中硬编码私钥
    • 实施密钥轮换策略
  2. 算法选择

    • 优先选择ECDSA或EdDSA
    • RSA密钥长度至少2048位
    • 弃用SHA-1等不安全哈希算法
  3. 侧信道攻击防护

    • 恒定时间算法实现
    • 防止时序攻击和故障攻击

7.2 区块链签名最佳实践

# 安全的区块链交易签名示例
from web3 import Web3
from eth_account import Accountdef sign_blockchain_transaction(private_key: str, to: str, value: int):"""安全地签名区块链交易参数:private_key: 十六进制格式私钥to: 接收方地址value: 转账金额 (wei)返回:签名后的交易"""# 创建交易字典transaction = {'to': to,'value': value,'gas': 21000,'gasPrice': Web3.to_wei('50', 'gwei'),'nonce': 0,  # 实际应用中需要从链上获取'chainId': 1  # 主网}# 签名交易 (使用eth_account库)signed_tx = Account.sign_transaction(transaction, private_key)return signed_tx.rawTransaction# 使用环境变量管理私钥
import os
private_key = os.getenv("BLOCKCHAIN_PRIVATE_KEY")if not private_key:raise ValueError("未设置私钥环境变量")signed_tx = sign_blockchain_transaction(private_key, "0x...", 10**18)

结论:构建可信的数字世界

数字签名技术作为区块链安全的基石,实现了去中心化系统中的身份验证和交易完整性保障。通过本文的深入探讨和Python实现,我们掌握了:

  1. 非对称加密的数学原理
  2. 数字签名的工作流程和标准
  3. RSA算法的完整实现
  4. 数字证书的创建和验证
  5. 区块链中的实际应用场景
  6. 安全最佳实践

随着量子计算的发展,传统数字签名算法面临新的挑战。后量子密码学研究正在推进抗量子签名算法(如基于格的Dilithium算法)的标准化进程。然而在当前阶段,RSA和ECDSA仍是区块链领域的主流选择。

在数字世界中,数字签名如同亲笔签名——它确认了你的身份,证明了你的意图,并确保你的承诺不可篡改。掌握这项技术,是构建可信数字生态系统的关键一步。

相关文章:

  • 贸易公司网站设计百度用户服务中心官网电话
  • 三河网站建设软文广告发布平台
  • 交友网站开发/百度客服人工在线咨询电话
  • 专业网站建设明细报价表/免费网站在线观看人数在哪
  • 哪个网站做浏览器主页/建立网站需要什么条件
  • 宣传设计网站/seo
  • 【AI论文】扩展大型语言模型(LLM)智能体在测试时的计算量
  • Java+Vue开发的SRM招标采购管理系统,实现招标采购全流程数字化、规范化高效管理
  • MySQL与Excel比较
  • 协议转换赋能光伏制造:DeviceNET转PROFINET网关的通信质检实践
  • 2d-gaussian-splatting:论文分析、全流程环境配置与数据集测试【2025最新版!!!】
  • AntDesignPro动态路由配置全攻略
  • AES算法的Verilog流水线实现(带测试)
  • 【机器人-深度估计】双目深度估计原理解析
  • 汽车制造领域:EtherCAT转Profinet网关案例全面解析
  • Redis精简总结|一主二从哨兵模式(工作机制)|集群模式|缓存的穿透雪崩击穿
  • day040-搭建lnmp服务与数据库迁移
  • C#串口通讯实战指南
  • JavaScript操作DOM对象
  • solidity+Remix本地化部署和安装教程
  • MATLAB GUI界面设计 第三章——仪器组件
  • ISO 26262-11 半导体功能安全学习(二)
  • C#采集电脑硬件(CPU、GPU、硬盘、内存等)温度和使用状况
  • 技术解读|MatrixOne Intelligence模型解析原理及微调实践
  • 华为云 Flexus+DeepSeek 征文|文案魔盒・Emoji 菌:基于华为云 CCE 集群 Dify 大模型,创意文案智能生成助手
  • 企业网盘和个人网盘的区别?