離散對數求解


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;

}

運行結果

模數的運算規則


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM