Day 7
消息签名与加密通信
高级阶段 · 预计学习时间 90 分钟
学习目标
- 理解区块链消息签名原理
- 使用私钥签名任意消息
- 验证消息签名
- 实现端到端加密通信
签名与加密原理
数字签名
数字签名使用私钥对消息进行签名,任何人都可以用对应的公钥验证签名的有效性。
签名过程:
┌─────────┐ 私钥签名 ┌─────────────┐
│ 消息 │ ───────────────→ │ 签名数据 │
└─────────┘ └─────────────┘
验证过程:
┌─────────┐ ┌───────────┐ 公钥验证 ┌─────────┐
│ 消息 │ + │ 签名数据 │ ────────────→ │ 有效/无效│
└─────────┘ └───────────┘ └─────────┘
应用场景
| 场景 | 说明 |
|---|---|
| 身份验证 | 证明消息来自特定账户 |
| 授权操作 | 离线签名授权 |
| 数据完整性 | 确保数据未被篡改 |
| 不可抵赖性 | 签名者无法否认签名 |
加密通信
使用非对称加密,发送方用接收方的公钥加密,只有接收方的私钥能解密。
加密通信:
发送方 ──[接收方公钥加密]──→ 密文 ──[接收方私钥解密]──→ 接收方
特点:
- 只有接收方能解密
- 公钥可公开分发
- 保证消息机密性
crypto 模块
Python SDK 的 crypto 模块提供了完整的加密功能。
模块导入
from aeternity.crypto import (
sign_message,
verify_message,
encrypt,
decrypt,
hash_message
)
核心函数
| 函数 | 功能 | 参数 |
|---|---|---|
sign_message() | 消息签名 | 私钥, 消息 |
verify_message() | 验证签名 | 公钥, 消息, 签名 |
encrypt() | 公钥加密 | 公钥, 明文 |
decrypt() | 私钥解密 | 私钥, 密文 |
hash_message() | 消息哈希 | 消息, 算法 |
实践任务
任务 7.1: 消息签名
from aeternity.signing import Account
from aeternity.crypto import sign_message
# 创建账户
account = Account.generate()
print(f"地址: {account.get_address()}")
# 待签名的消息
message = "Hello, Aeternity!"
message_bytes = message.encode('utf-8')
# 使用私钥签名
signature = sign_message(
private_key=account.get_secret_key(),
message=message_bytes
)
print(f"消息: {message}")
print(f"签名: {signature.hex()}")
print(f"签名长度: {len(signature)} 字节")
任务 7.2: 签名验证
from aeternity.crypto import verify_message
# 验证签名
is_valid = verify_message(
public_key=account.get_address(),
message=message_bytes,
signature=signature
)
print(f"签名验证: {'✅ 有效' if is_valid else '❌ 无效'}")
# 尝试验证篡改的消息
tampered_message = "Hello, Ethereum!".encode('utf-8')
is_valid_tampered = verify_message(
public_key=account.get_address(),
message=tampered_message,
signature=signature
)
print(f"篡改消息验证: {'✅ 有效' if is_valid_tampered else '❌ 无效'}")
任务 7.3: 结构化消息签名
import json
import hashlib
import time
def sign_structured_message(account, data: dict) -> dict:
"""签名结构化数据"""
# 添加时间戳和签名者
message = {
'data': data,
'timestamp': int(time.time()),
'signer': account.get_address()
}
# 序列化并哈希
message_json = json.dumps(message, sort_keys=True)
message_hash = hashlib.sha256(message_json.encode()).digest()
# 签名
signature = sign_message(
private_key=account.get_secret_key(),
message=message_hash
)
return {
'message': message,
'signature': signature.hex()
}
# 使用示例
data = {
'action': 'transfer',
'amount': 100,
'to': 'ak_recipient...'
}
signed = sign_structured_message(account, data)
print(json.dumps(signed, indent=2))
任务 7.4: 端到端加密
from aeternity.crypto import encrypt, decrypt
# 创建两个账户 (Alice 和 Bob)
alice = Account.generate()
bob = Account.generate()
print(f"Alice: {alice.get_address()}")
print(f"Bob: {bob.get_address()}")
# Alice 给 Bob 发送加密消息
secret_message = "This is a secret message!"
print(f"\n原始消息: {secret_message}")
# 使用 Bob 的公钥加密
encrypted = encrypt(
public_key=bob.get_address(),
message=secret_message.encode('utf-8')
)
print(f"加密后: {encrypted.hex()[:64]}...")
# Bob 使用私钥解密
decrypted = decrypt(
private_key=bob.get_secret_key(),
ciphertext=encrypted
)
print(f"解密后: {decrypted.decode('utf-8')}")
任务 7.5: 消息哈希
from aeternity.crypto import hash_message
# 计算消息哈希
message = "Aeternity Blockchain"
# SHA-256 哈希
sha256_hash = hash_message(message.encode(), algorithm='sha256')
print(f"SHA-256: {sha256_hash.hex()}")
# Blake2b 哈希
blake2b_hash = hash_message(message.encode(), algorithm='blake2b')
print(f"Blake2b: {blake2b_hash.hex()}")
# 哈希用于消息摘要和完整性验证
def verify_integrity(original: bytes, hash_value: bytes) -> bool:
"""验证数据完整性"""
computed_hash = hash_message(original, algorithm='sha256')
return computed_hash == hash_value
# 使用示例
data = b"Important data"
data_hash = hash_message(data, algorithm='sha256')
# 验证
print(f"完整性验证: {verify_integrity(data, data_hash)}")
实际应用
登录认证
import time
import secrets
class SignatureAuth:
"""基于签名的认证系统"""
def __init__(self):
self.challenges = {}
def create_challenge(self, address: str) -> str:
"""创建登录挑战"""
nonce = secrets.token_hex(16)
timestamp = int(time.time())
challenge = f"Login to MyApp\nAddress: {address}\nNonce: {nonce}\nTime: {timestamp}"
# 存储挑战(实际应用中使用 Redis/数据库)
self.challenges[address] = {
'challenge': challenge,
'expires': timestamp + 300 # 5分钟有效期
}
return challenge
def verify_login(self, address: str, signature: bytes) -> bool:
"""验证登录签名"""
if address not in self.challenges:
return False
stored = self.challenges[address]
# 检查是否过期
if time.time() > stored['expires']:
del self.challenges[address]
return False
# 验证签名
is_valid = verify_message(
public_key=address,
message=stored['challenge'].encode(),
signature=signature
)
if is_valid:
del self.challenges[address]
return is_valid
# 使用示例
auth = SignatureAuth()
# 1. 获取挑战
challenge = auth.create_challenge(account.get_address())
print(f"挑战:\n{challenge}")
# 2. 用户签名
user_signature = sign_message(
private_key=account.get_secret_key(),
message=challenge.encode()
)
# 3. 验证登录
is_logged_in = auth.verify_login(account.get_address(), user_signature)
print(f"\n登录结果: {'成功' if is_logged_in else '失败'}")
授权委托
def create_delegation(delegator: Account, delegate: str,
permissions: list, expires: int) -> dict:
"""创建授权委托"""
delegation = {
'type': 'delegation',
'delegator': delegator.get_address(),
'delegate': delegate,
'permissions': permissions,
'expires': expires,
'created': int(time.time())
}
# 序列化并签名
message = json.dumps(delegation, sort_keys=True)
signature = sign_message(
private_key=delegator.get_secret_key(),
message=message.encode()
)
return {
'delegation': delegation,
'signature': signature.hex()
}
# 使用示例
delegation = create_delegation(
delegator=alice,
delegate=bob.get_address(),
permissions=['transfer', 'stake'],
expires=int(time.time()) + 86400 * 7 # 7天后过期
)
print(json.dumps(delegation, indent=2))
常见问题
可能原因:
- 消息编码不一致(需统一使用 UTF-8)
- 签名时使用了不同的消息
- 公钥地址格式错误
解决方案:对于长消息,使用混合加密
- 生成随机对称密钥
- 用对称密钥加密消息
- 用公钥加密对称密钥
知识检查点
完成 Day 7 后,你应该能够:
相关模块
aeternity.crypto
aeternity.signing