Files
backend/test/core/sp_trust_sharding.py
2026-01-24 11:02:08 -08:00

113 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import hashlib
import secrets
from mnemonic import Mnemonic # 仅用于标准的助记词转换
class SentinelKeyEngine:
# 使用第 13 个梅森素数 (2^521 - 1),远大于 128-bit 熵,确保有限域安全
PRIME = 2**521 - 1
def __init__(self):
self.mnemo = Mnemonic("english")
def generate_vault_keys(self):
"""
1. 生成原始 12 助记词 (Master Key)
"""
words = self.mnemo.generate(strength=128)
entropy = self.mnemo.to_entropy(words)
return words, entropy
def split_to_shares(self, entropy):
"""
2. SSS (3,2) 门限分片逻辑
公式: f(x) = S + a*x (直线方程S为秘密a为随机斜率)
我们将秘密 S 分成 3 份,任选 2 份即可恢复。
注意:必须在有限域 GF(PRIME) 下进行运算以保证完善保密性。
"""
# 将熵转换为大整数
secret_int = int.from_bytes(entropy, 'big')
# 生成一个随机系数 a (安全性需与秘密强度一致)
# a 必须在 [0, PRIME-1] 范围内
a = secrets.randbelow(self.PRIME)
# 定义 3 个点: x=1, x=2, x=3
# Share = (x, f(x))
def f(x): return (secret_int + a * x) % self.PRIME
share1 = (1, f(1)) # 手机分片
share2 = (2, f(2)) # 云端分片
share3 = (3, f(3)) # 传承卡分片
return [share1, share2, share3]
def recover_from_shares(self, share_a, share_b):
"""
3. 恢复逻辑:拉格朗日插值还原
已知 (x1, y1) 和 (x2, y2),求 f(0) 即秘密 S
公式: S = (x2*y1 - x1*y2) / (x2 - x1)
在有限域下,除法变为乘以模逆: S = (x2*y1 - x1*y2) * (x2 - x1)^-1 mod P
"""
x1, y1 = share_a
x2, y2 = share_b
# 计算分子
numerator = (x2 * y1 - x1 * y2) % self.PRIME
# 计算分母的模逆 (x2 - x1)
denominator = (x2 - x1) % self.PRIME
inv_denominator = pow(denominator, -1, self.PRIME)
# 还原常数项 S
secret_int = (numerator * inv_denominator) % self.PRIME
# 转回字节并生成助记词
# 注意secret_int 可能略小于 16 字节高位为0需要补齐
# 但由于 entropy 原始就是 16 字节,这里直接转换即可
try:
recovered_entropy = secret_int.to_bytes(16, 'big')
except OverflowError:
# 理论上不应发生,除非计算出的 secret_int 大于 128 bit (即原始 entropy 大于 128 bit)
# 这里为了健壮性,如果原始 entropy 是 16 字节,这里应该也是。
# 如果 PRIME 很大secret_int 还是原来的值。
recovered_entropy = secret_int.to_bytes((secret_int.bit_length() + 7) // 8, 'big')
return self.mnemo.to_mnemonic(recovered_entropy)
if __name__ == "__main__":
# --- Sentinel 协议业务流程模拟 ---
engine = SentinelKeyEngine()
# [生前]:初始化金库
master_words, entropy = engine.generate_vault_keys()
print(f"【1. 生成原始助记词】: {master_words}")
shares = engine.split_to_shares(entropy)
print(f"【2. SSS 分片完成】:")
print(f" - 分片1 (手机安全区): {shares[0]}")
print(f" - 分片2 (Sentinel云): {shares[1]}")
print(f" - 分片3 (传承卡单词): {shares[2]}")
print("-" * 50)
# [死后/传承]:模拟用户失联,触发被动验证
# 假设继承人拿着卡片 (Share 3),向服务器请求分片 (Share 2)
successor_share = shares[2]
server_share = shares[1]
# 执行恢复
recovered_words = engine.recover_from_shares(shares[0], shares[1])
print(f"【1. 手机+云 : {recovered_words}")
recovered_words = engine.recover_from_shares(shares[0], shares[2])
print(f"【2. 手机+传承卡 : {recovered_words}")
recovered_words = engine.recover_from_shares(shares[1], shares[2])
print(f"【3. 云+传承卡 : {recovered_words}")
# 校验一致性
assert recovered_words == master_words
print("\n结果:恢复出的助记词与原始完全一致。")
with open("words.txt", "w") as f:
f.write("%s\n"%master_words)