Pohlig-Hellman

Pohlig-Hellman

一种解决离散对数问题的方法,针对循环群的阶光滑的情况

这里我们考虑模p的乘法群下Pohlig-Hellman的应用

对于同余方程ax=b(mod p),其中p-1光滑

设p-1=\(p_1^{α_1}p_2^{α_2}...p_n^{α_n}\)

对于pi

设x=\(\sum_{j=0}^{α_i-1}a_jp_i^j(mod p_i^{α_i})\)

由同余方程ax=b(mod p)=>\(a^{\frac{p-1}{p_i^s}*x}=b^{\frac{p-1}{p_i^s}}(mod p)\)

记A=\(a^{\frac{p-1}{p_i^s}}\),B=\(b^{\frac{p-1}{p_i^s}}\)

=>Ax=B(mod p)

\(A^{p_i^s}=1(mod p)\)=>\(A^{\sum_{j=0}^{s-1}a_jp_i^j}=B(mod p)\)(※)

对(※)我们从s=1开始计算直到αi,可知每次在复杂度为O(p)下枚举aj的取值即可

最后可得\(x(mod p_i^{α_i})\)的值(i=0,1,...,n)

中国剩余定理即可求得x(mod p-1)

代码实现

def Polig_Hellman(g,y,p):
    factors, exponents = zip(*factor(p-1))
    temp=[]
    for i in range(len(factors)):
        q=factors[i]
        a=[]
        for j in range(1,exponents[i]+1):
            gg=pow(g,((p-1)//q^j),p)
            yy=pow(y,((p-1)//q^j),p)
            for k in range(q):
                s=0
                for t in range(len(a)):
                    s+=a[t]*q^t
                s+=k*q^(len(a))
                if pow(gg,s,p)==yy:
                    a.append(k)
                    break
        x_q=0
        for j in range(len(a)):
            x_q+=a[j]*q^j
        temp.append(x_q)
    f=[]
    for i in range(len(factors)):
        f.append(factors[i]^exponents[i])
    return crt(temp,f)

p=176473303538524259200554324953336384726672109110665668162293282699973540848874702767584458062843333942678732811932897476909679289489853667242704250498709920215500564359945126566451281262283662096646326724094693217360879121741192532765498098061185923631716696944607478088126741032221004102364580340388512170139
G=GF(p)
g=3
y=pow(3,1561654659848997911129,p)
print(discrete_log(G(y),G(g)))
x=Polig_Hellman(g,y,p)
print(pow(g,x,p)-y)

这里有个神奇的事情就是我自己写的p-h算出来的x和我初设的不同,实际上满足的是在g模p的阶下同余,sage自带的discrete_log是会自动约化到小于阶的情况

summary

总的来说,p-h算法在解决光滑阶循环群的dlp问题是一个十分有力的工具,所反映的思想也很值得学习,上述代码在计算O(p)时可以采用bsgs进一步降低复杂度

posted @ 2022-04-15 00:09  hash_hash  阅读(700)  评论(0编辑  收藏  举报