离散对数求解

1.实验内容


我们谈谈以下几个基本概念。

1.原根

  原根是一种数学符号,设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根。(其中φ(m)表示m的欧拉函数) 

假设一个数g是P的原根,那么g^i mod P的结果两两不同,且有 1<g<P,0<i<P,归根到底就是g^(P-1) = 1 (mod P)当且仅当指数为P-1的时候成立.(这里P是素数)。
简单来说,g^i mod p ≠ g^j mod p (p为素数),其中i≠j且i, j介于1至(p-1)之间,则g为p的原根。

2.群

基本概念可以看这里。群环域

  • 上图思路是老师给出的思路,我自己实现了下,我跑了两个小时,跑了两个小时跑不出来结果,最后系统崩溃。
/*
* create hash table
*/

void createSearchTable(unordered_map<string,int>& searchTable,const mpz_class& h,const mpz_class& g,const mpz_class& p )
{

    int x_max = pow(2,20);
    mpz_class g_x1 = 1;
    mpz_class hDivGx_1 = h;
    for(int x_1 = 0;x_1<x_max;x_1++)
    {	
        hDivGx_1 = h/g_x1 % p;
        searchTable.insert(make_pair(hDivGx_1.get_str(),x_1));
        g_x1 =g_x1*g;
    }
    cout<<"searchTable size:"<<searchTable.size()<<endl;
	cout<<"create searchTable success"<<endl;

}
/*
* get result x = x0*B + x1
*/
mpz_class solve(unordered_map<string,int>& searchTable,const mpz_class& g,const mpz_class& p,int & result_x_1, int& result_x_0){
    mpz_class result("0",10);
    int x_0;
    int x_max = pow(2,20);
    //计算g**B
    mpz_class gB = 1;
    for(int i = 0; i < x_max; i++) {
        gB = gB *g%p;
    }
    mpz_class gbx = 1;
    for(int x_0 =0;x_0<x_max;x_0++)
    {
        gbx = gbx * gB %p;
        auto it = searchTable.find(gbx.get_str());
        if(it!=searchTable.end()){
            cout<<"find x"<<endl;
            result = it->second + x_0*pow(2,20);
            result_x_1 = it->second;
            result_x_0 = x_0;
            break;
        }
    }
    return result;
}

2.转换思路

  我测试了下计算时间主要用于$g^{x1}$的逆元就算,主要在这一步代码
hDivGx_1 = h/g_x1 % p;
g_x1 =g_x1*g;
  我记得在《区块链》这门课上好像讲到过这个内容,后面我查了下资料,发现这里面是存在小技巧的。

上图给的思路是

\[x = x0B + x1 其中B =2^{20} 0\leq x0,x1\leq 2^{20}-1 \]

当两边同时除以x1时候,需要求\(g^{x1}\)的逆元\(g^{-x1}\),

那么就需要重新思考这个问题。我们假设 \(x = x0B - x1 其中B =2^{20} 0\leq x1\leq 2^{20}-1 0\leq x0\leq 2^{20}+1\),这时候式子就变成了了.

\[h*g^{x1} = g^{x0*B} \]

这时候就不需要求逆元了。

那么我们重新更换代码吧。

/*
* create hash table
*/

void createSearchTable(unordered_map<string,int>& searchTable,const mpz_class& h,const mpz_class& g,const mpz_class& p )
{

    int x_max = pow(2,20);
    mpz_class g_x1 = 1;
    mpz_class hDivGx_1 = h;
    for(int x_1 = 0;x_1<x_max;x_1++)
    {	
        if(x_1 == 0){
            hDivGx_1 = hDivGx_1%p;
            searchTable.insert(make_pair(hDivGx_1.get_str(),x_1));
        }
        else{
            hDivGx_1 = hDivGx_1*g % p;
            searchTable.insert(make_pair(hDivGx_1.get_str(),x_1));
        }  
    }
    cout<<"searchTable size:"<<searchTable.size()<<endl;
	cout<<"create searchTable success"<<endl;

}


/*
* get result x = x0*B - x1
*/
mpz_class solve(unordered_map<string,int>& searchTable,const mpz_class& g,const mpz_class& p,int & result_x_1, int& result_x_0){
    mpz_class result("0",10);
    int x_0;
    int x_max = pow(2,20);
    //计算g**B
    mpz_class gB = 1;
    for(int i = 0; i < x_max; i++) {
        gB = gB *g%p;
    }

    mpz_class gbx = 1;
    for(int x_0 =0;x_0<x_max+1;x_0++)
    {
        
        auto it = searchTable.find(gbx.get_str());
        if(it!=searchTable.end()){
            cout<<"find x"<<endl;
            result = x_0*pow(2,20) - it->second;
            result_x_1 = it->second;
            result_x_0 = x_0;
            break;
        }
        gbx = gbx * gB %p;
    }
    return result;

}

运行结果

模数的运算规则

posted @ 2020-05-26 19:57  cyssmile  阅读(1111)  评论(2编辑  收藏  举报