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)