LCG 线性同余生成器
2023/6/2大约 2 分钟LCG流密码
概念
LCG既属于 伪随机数 发生器,也属于流密码。参考文章: https://goodapple.top/archives/404
递推公式
参数:
- S 是伪随机序列;
表示模量; 表示乘数; 表示增量; 表示初始值。
阶
成立的最小正整数 x 称为a模n的阶,记为
原根
如果有
称 a 为模 n 的原根
若 gcd(a,n)=1,则周期 T=ordm(a),所以选取系数时应尽量使得 a 为模 n 的原根,以此尽量延长 LCG 周期。
常见推导公式
公式一
此公式用于从
推导过程如下
进而
公式二
此公式用于求 a,公式如下
推导过程如下
两式相减
进而得到
公式三
此公式用于求b,公式如下
公式四
此公式用于求m,公式如下
推导过程如下:
令
即
实现程序
from Crypto.Util.number import long_to_bytes
from sympy import *
from gmpy2 import *
# 还原初始种子
def restore_seed_S0(states, modulus, multiplier, increment):
seed = (states[0] - increment) * invert(multiplier, modulus) % modulus
return seed, modulus, multiplier, increment
# 计算增量
def crack_unknown_increment(states, modulus, multiplier):
increment = (states[1] - states[0] * multiplier) % modulus
return restore_seed_S0(states, modulus, multiplier, increment)
# 计算乘数
def crack_unknown_multiplier(states, modulus):
multiplier = (states[2] - states[1]) * invert(states[1] - states[0], modulus) % modulus
return crack_unknown_increment(states, modulus, multiplier)
# 计算模数
def crack_unknown_modulus(S):
t4 = S[5] - S[4]
t3 = S[4] - S[3]
t2 = S[3] - S[2]
t1 = S[2] - S[1]
modulus = gcd(t4 * t2 - t3 ** 2, t3 * t1 - t2 ** 2)
return crack_unknown_multiplier(states, modulus)
states = [6473702802409947663, 7762911616316678361, 8778349545254661087, 2182563361653435704, 1383751637647655272,
4512576578889812021, 4322633144718249958, 3959701111371594748, 7676663421477866678, 5009230933212388616,
3780469426700690705]
seed, modulus, multiplier, increment = crack_unknown_modulus(states)
print("模数n =", modulus)
print("乘数a =", multiplier)
print("增量b =", increment)
print("初始S0 =", seed)