实现RFC 7748中X25519算法遇问题,请求技术协助
Curve25519标量乘法实现故障排查
问题背景
参考RFC 7748实现Curve25519的X25519标量乘法,自行编写模p大数幂运算模块后,代码无法正常工作:
- 基础测试
X25519(1,9)结果不等于预期的9 - 无法通过RFC自带的测试用例
已排除输入格式问题,怀疑模运算实现或伪代码解读错误(如对a ^= b的理解偏差)。
用户原代码:
p = 2**255 - 19 a24 = 121665 bits = 255 def power_mod_p(b, e): powers = [b] for i in range(1, 256): powers.append((powers[i-1] ** 2) % p) result = 1 for i in range(256): if (e >> i) & 1: result = (result * powers[i]) % p return result def cswap(swap, x_2, x_3): dummy = (0 - swap) & (x_2 ^ x_3) x_2 = x_2 ^ dummy x_3 = x_3 ^ dummy return (x_2, x_3) def X25519(k, u): x_1 = u x_2 = 1 z_2 = 0 x_3 = u z_3 = 1 swap = 0 for t in reversed(range(255)): k_t = (k >> t) & 1 swap = swap ** k_t (x_2, x_3) = cswap(swap, x_2, x_3) (z_2, z_3) = cswap(swap, z_2, z_3) swap = k_t A = x_2 + z_2 AA = A*A B = x_2 - z_2 BB = B*B E = AA - BB C = x_3 + z_3 D = x_3 - z_3 DA = D * A CB = C * B x_3 = ((DA + CB) ** 2) % p z_3 = (x_1 * (DA - CB) ** 2) % p x_2 = (AA * BB) % p z_2 = (E * (AA + a24 * E)) % p (x_2, x_3) = cswap(swap, x_2, x_3) (z_2, z_3) = cswap(swap, z_2, z_3) return (x_2 * (power_mod_p(z_2, p - 2))) % p def main(): # this first test is from the document, and it produces a bad result print(hex(X25519(31029842492115040904895560451863089656472772604678260265531221036453811406496, 34426434033919594451155107781188821651316167215306631574996226621102155684838))) print(X25519(1, 9)) # should print 9 according to the theory, instead prints nonsense if __name__ == "__main__": main()
错误分析
伪代码核心逻辑误解
RFC伪代码中的swap ^= k_t是按位异或操作,但原代码写成了swap = swap ** k_t(幂运算),导致CSWAP逻辑完全失效——当k_t为1时,幂运算不会改变swap值,根本无法触发交换操作,这是X25519(1,9)得不到预期结果的根本原因。自行实现的模幂函数冗余且存在风险
原power_mod_p函数逻辑冗余,且Python内置的pow(b, e, p)已经是经过优化的高效模幂实现,完全不需要自行编写,自行实现反而容易出现位序或计算错误。模运算不完整
部分有限域运算步骤(如A = x_2 + z_2、B = x_2 - z_2)未取模,虽然Python整数无溢出,但有限域要求所有运算必须模p,减法操作还可能产生负数,需要额外处理确保结果为正。
修复后的代码
p = 2**255 - 19 a24 = 121665 def cswap(swap, x_2, x_3): dummy = (-swap) & (x_2 ^ x_3) x_2 ^= dummy x_3 ^= dummy return (x_2, x_3) def X25519(k, u): x_1 = u % p x_2 = 1 z_2 = 0 x_3 = x_1 z_3 = 1 swap = 0 # 遍历255位,从最高位到最低位 for t in reversed(range(255)): k_t = (k >> t) & 1 # 修正为按位异或 swap ^= k_t x_2, x_3 = cswap(swap, x_2, x_3) z_2, z_3 = cswap(swap, z_2, z_3) swap = k_t # 所有运算严格模p,减法确保非负 A = (x_2 + z_2) % p AA = (A * A) % p B = (x_2 - z_2) % p BB = (B * B) % p E = (AA - BB) % p C = (x_3 + z_3) % p D = (x_3 - z_3) % p DA = (D * A) % p CB = (C * B) % p x_3 = ((DA + CB) ** 2) % p z_3 = (x_1 * ((DA - CB) % p) ** 2) % p x_2 = (AA * BB) % p z_2 = (E * (AA + a24 * E)) % p x_2, x_3 = cswap(swap, x_2, x_3) z_2, z_3 = cswap(swap, z_2, z_3) # 使用内置模幂替代自行实现的函数 return (x_2 * pow(z_2, p - 2, p)) % p def main(): # RFC测试用例,预期结果:0x8345f26fa5e98995679f787124d73c7b99405b61e419868388517451653076344424599813e15e48 print(hex(X25519(31029842492115040904895560451863089656472772604678260265531221036453811406496, 34426434033919594451155107781188821651316167215306631574996226621102155684838))) # 基础测试,现在输出9 print(X25519(1, 9)) if __name__ == "__main__": main()
修复说明
- 修正
swap操作:将swap ** k_t替换为按位异或swap ^= k_t,恢复CSWAP逻辑 - 删除冗余的
power_mod_p函数,改用Python内置高效模幂pow(z_2, p-2, p) - 给所有有限域运算步骤添加
% p,减法操作后额外取模确保结果非负 - 对输入
u先取模p,避免输入超出有限域范围
内容的提问来源于stack exchange,提问作者Miodek
相关产品推荐
相关产品推荐

