离散对数求解算法

本文介绍了离散对数问题的解决算法——baby_step_giant_step,以及其扩展形式用于处理非素数模的情况。通过预处理、二分查找和快速幂等技术,实现了O(sqrt(P)*log(sqrt(P)))时间复杂度的求解过程。同时,讨论了原根和扩展小步大步攻击算法,包括原根的定义、性质、判定定理及求解步骤,最后给出了相关样题和代码模板。
摘要由CSDN通过智能技术生成


求解一个最小的x满足给定的方程Bx == N (mod P)

使用baby_step_giant_step算法。也就是先小步后大步算法。

1、令x=i*m+j  (m=ceil(sqrt(p))),

那么原式化为 B^(i*m)*B^j==N(MOD P)

B^j==N*B^(-i*m)(MOD P)---------->B^j==N*B^m^(-i)(MOD P)

2、先预处理B^0,B^1,B^2……B^(m-1),存入HASH表,我使用结构体排序然后二分查找,这一步就是baby_step,每次移动1

3、然后快速幂求出B^-m,枚举i,如果存在N*B^(-i*m)存在于HASH表中,说明存在解x=i*m+j,这一步为giant_step,每次移动m

注意以上解法是最基本的,只能对于gcd(B,P)==1,算法的时间复杂度是O(sqrt(P)*log(sqrt(P)))

样题:poj2417

ps:参考cxlove博客,密码学里面貌似叫做shanks算法 点击打开链接

模板:

///大步小步算法
struct baby///小步算法预存的结构体定义
{
    long long b,j;
    bool operator < (const baby &other)const{
        if(b==other.b)return j<other.j;
        return b<other.b;
    }
}babyv[100005];
///快速幂,x^y%mod
long long q_pow(long long x,long long y,long long mod)
{
    long long ans=1;
    while(y>0)
    {
        if(y&1)ans=(ans*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return ans;
}
///小步预存的个数为m的结构体里面查找num
long long find(long long num,long long m)
{
    long long l=0,r=m-1,ans=-1;
    while(r>=l)
    {
        long long mid=(r+l)/2;
        if(babyv[mid].b>=num){
            if(babyv[mid].b==num)
                ans=babyv[mid].j;
            r=mid-1;
        }
        else l=mid+1;
    }
    return ans;
}
///B^x=N(modP)求解x,无解返回-1
long long babystep_giantstep(long long B,long long N,long long P)
{
    long long m=ceil(sqrt(P)),ans=1;
    for(long long j=0;j<m;j++)///预存操作
    {
        babyv[j].b=ans;
        babyv[j].j=j;
        ans=(ans*B)%P;///递推
    }
    ans=1;
    sort(babyv,babyv+m);///预存排序
    long long _Bm=q_pow(q_pow(B,P-2,P),m,P);///算出B^(-m)%P的值
    for(long long i=0;i<m;i++)
    {
        long long j=find(N*ans%P,m);///二分查找
        if(j!=-1)return i*m+j;///找到返回答案
        ans=(ans*_Bm)%P;///继续递推
    }
    return -1;///找不到答案
}

poj2417代码:点击打开链接

#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstdlib>
#include<utility>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Inf (1<<29)
#define LL long long
using namespace std;
const int MM=110;
const long long MOD=1000000007;
///大步小步算法
struct baby///小步算法预存的结构体定义
{
    long long b,j;
    bool operator < (const baby &other)const{
        return b<other.b;
    }
}babyv[100005];
///快速幂,x^y%mod
long long q_pow(long long x,long long y,long long mod)
{
    long long ans=1;
    while(y>0)
    {
        if(y&1)ans=(ans*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return ans;
}
///小步预存的个数为m的结构体里面查找num
long long find(long long num,long long m)
{
    long long l=0,r=m-1;
    while(r>=l)
    {
        long long mid=(r+l)/2;
        
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
椭圆曲线离散对数问题是基于椭圆曲线群的一个数学难题。它是在椭圆曲线上找到从一组点到另一组点之间的线性映射的问题。更精确地讲,在椭圆曲线 \(E\) 上,给定两个点 \(P\) 和 \(Q = [k]P\) (其中 \(k\) 是一个整数),椭圆曲线离散对数问题就是寻找 \(k\) 的计算过程。 椭圆曲线离散对数问题通常用于加密技术中,因为它被认为是计算上困难的,因此可以作为构建安全协议的基础。例如,在椭圆曲线密码学(Elliptic Curve Cryptography, ECC)中,这一问题被用来生成公钥和私钥,保证数据传输的安全性。 目前存在几种解决椭圆曲线离散对数问题的方法,包括但不限于: 1. **指数搜索**:一种简单的暴力破解方法,通过尝试所有可能的 \(k\) 值直到找到正确的解。这种方法在大数情况下效率极低,不适合实际应用。 2. **Pollard's rho算法**:这是在随机情况下解决离散对数问题的一种有效方法,特别适合于椭圆曲线离散对数问题。该算法利用概率论原理,通过构造一个伪随机序列并在序列中查找周期点,从而逼近离散对数的解。 3. **Schoof算法**:主要用于计算椭圆曲线的素数阶数,即曲线上有多少个不同点。了解曲线阶数对于解决椭圆曲线离散对数问题有重要帮助。 4. **Miller-Rabin素性测试结合快速指数求模算法**:这是一种现代的、高效的椭圆曲线离散对数问题求解策略,尤其当处理的是大数时。首先使用素性测试验证某个大数是否为素数,然后在素数域内应用快速指数求模算法来加速求解过程。 5. **Gallant-Lambert-Vanstone算法**:这是一种改进的指数搜索算法,通过提前预处理减少搜索空间,适用于某些特定情况下的优化求解。 值得注意的是,尽管这些算法在理论上有一定的进展和改进,但对于实际使用的椭圆曲线参数集而言,椭圆曲线离散对数问题仍然被认为是非常难以求解的,这也保证了椭圆曲线密码系统的安全性。然而,随着量子计算机的发展,现有的椭圆曲线密码系统面临着潜在的风险,因为量子计算机运行的Shor算法能够有效地解决这类离散对数问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值