0

Given a arbitrary integers p, g, and r and given y such that y = gx mod p where x is an unknown integer quantity, how would one solve for C where C = gr• (gx)-1 mod p?

My math is below, but when I input it in a verifier function, it says the answer is incorrect.

    y•u = 1 mod p

    y•u = 1 + mp
    uy - mp = 1

where u is the inverse of y and m is the set of natural numbers (as inverse of mod requires this)

c6695610
  • 1
  • 2
  • I'm voting to close this question as off-topic because it's about math, not programming. Try math.stackexchange.com. Or, really, just go here: https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm – Matt Timmermans Oct 30 '19 at 03:14
  • @MattTimmermans That's what I used to find the actual value of `u` from the last equation, but that doesn't help me determine if the actual equation is incorrect. – c6695610 Oct 30 '19 at 04:25
  • you should change the title a bit as modular inverse usually implies division instead of **inverse modpow**. the `C,r` part makes no sense and your not using it in your math nor the `C = gr• (gx)-1 mod p` is it second condition? or just your attempt to solve `imodpow` ? – Spektre Oct 30 '19 at 10:02
  • @Spektre It's my first time exploring this topic, hence the lack of knowledge. I can try to explain as best as I can. I have to calculate `C` for the given function. The problem is, I do not have an `x` value. Instead, I have a `y` value where `y = g^x mod p`. Thus, I am trying to find `(g^x)^-1 mod p` using the `y` value in my math. I believe you are right in that the function I am looking for is `imodpow`. – c6695610 Oct 30 '19 at 20:32
  • Yep I fully understand as number theory and modular arithmetic and finite fields of Galloa are not my usual cup of tea ... so I am similarly lost in dark as you are ... this is more advanced math then programming and people knowing the stuff usually cant code and people that can code usually cant understand the math ... (at least to my experience) – Spektre Oct 30 '19 at 22:09

1 Answers1

0

If I see it right you are looking for Inverse modpow. The math is like this:

ab = a^b % p
ab + c*p = a^b
log(ab+c*p)/log(a) = b
(ab+c*p)^(1/b) = a

where c is integer c={ 0,1,2,3,4... } converting between normal and modular arithmetic. So in your case you want to compute b. The problem is that log(ab+c*p)/log(a) grows very slow with increasing c if p is not much bigger than a. So in such case it's faster to use all combinations of b instead until a fit is found something like this in C++:

//---------------------------------------------------------------------------
ALU32 alu;
DWORD modmul(DWORD a,DWORD b,DWORD p)   //  ans = a*b % p
    {
    DWORD ch,cl,c,d;
    alu.mul(ch,cl,a,b);
    alu.div(c,d,ch,cl,p);
    return d;
    }
//---------------------------------------------------------------------------
DWORD modinv(DWORD a,DWORD p)   //  a * ans % p = 1
    {
    DWORD b,c,db,dc,i=0;
    db=p/a;
    dc=db*a;
    for (b=1,c=a;b<p;i++)
        {
        if (c==1) return b;
        b+=db; c+=dc;
        while (c<p){ b++; c+=a; }
        c-=p;
        }
    return 0;
    }
//---------------------------------------------------------------------------

DWORD modpow(DWORD a,DWORD b,DWORD p)   //  ans = a^b % p
    {   // b is not mod(p) !
    DWORD i,d=1;
    for (a%=p,i=0;i<32;i++,b<<=1)
        {
        d=modmul(d,d,p);
        if (DWORD(b&0x80000000)) d=modmul(d,a,p);
        }
    return d;
    }
//---------------------------------------------------------------------------
DWORD imodpow(DWORD ab,DWORD a,DWORD p) // ab = a^ans % p
    { // ans is not mod(p) !
    DWORD b,AB;
    for (AB=1,b=0;;)
        {
        if (AB==ab) return b;
        b++; if (!b) return  0;
        AB=modmul(AB,a,p);
        }
    }
//---------------------------------------------------------------------------

Of coarse this is SLOOOOW, which is why is this used for cryptography. Also beware there are multiple valid solutions and the first one found might not be the one you're seeking so you need to add additional conditions ...

The ALU32.h can be found in here Can't make value propagate through carry

And the modular arithmetic is based on this: Modular arithmetics and NTT (finite field DFT) optimizations

Here a sample for comparison (ignore VCL and tbeg/tend/tstr functions):

DWORD a=87654321,b=12345678,p=0xC0000001,ab,bb;
tbeg(); ab=modpow(a,b,p); tend();   mm_log->Lines->Add(AnsiString().sprintf("%8u^%8u mod %u = %u ",a,b ,p,ab)+tstr(1));
tbeg(); bb=imodpow(ab,a,p); tend(); mm_log->Lines->Add(AnsiString().sprintf("%8u^%8u mod %u = %u ",a,bb,p,ab)+tstr(1));

and output:

87654321^12345678 mod 3221225473 = 3038293251 [   0.002 ms]
87654321^12345678 mod 3221225473 = 3038293251 [ 421.910 ms]

PS.

There might be some more advanced approaches from number theory if the p is special like prime, composite of two primes or even n-th root of unity ... but that is in galaxy far far away from mine reach of expertise.

Edit 1

From your newly posted question it's finally clearer that you really just wanted modular inverse and has nothing to do with imodpow. So what you want is this:

a*b % p = 1

where b is unknown so simply try all b in increasing manner where a*b % p is just truncated by p towards zero and if the result is 1 you found your answer. I updated the code above with modinv function doing exactly that + some optimization. However I think there are even faster approaches for this using GCD or something.

Here another test sample:

DWORD a=87654321,b=12345678,p=0xC0000001,ab,bb;

        ab=modmul(a,b,p);
tbeg(); bb=modinv(b,p);     tend(); mm_log->Lines->Add(AnsiString().sprintf("       1/%8u mod %u = %u ",b,p,bb)+tstr(1));
tbeg(); a =modmul(b,bb,p);  tend(); mm_log->Lines->Add(AnsiString().sprintf("%8u*%8u mod %u = %u ",b,bb,p,a)+tstr(1));
tbeg(); a =modmul(ab,bb,p); tend(); mm_log->Lines->Add(AnsiString().sprintf("%8u*%8u mod %u = %u ",ab,bb,p,a)+tstr(1));

And output:

       1/12345678 mod 3221225473 = 165081805  [   4.999 ms]
12345678*165081805 mod 3221225473 = 1         [   0.000 ms]
652073126*165081805 mod 3221225473 = 87654321 [   0.000 ms]
halfer
  • 19,824
  • 17
  • 99
  • 186
Spektre
  • 49,595
  • 11
  • 110
  • 380
  • This solution calculates the value of `x` (in this case `b`) which would render the problem trivial. The problem is how do we calculate `C` without calculating `x`. – c6695610 Oct 30 '19 at 22:18
  • @c6695610 I updated my answer according to your new question which is duplicate btw. You should add the info in here instead of posting new question about the same problem – Spektre Oct 31 '19 at 07:25