0

Context

The decryption math formula for the El Gamal method is the following:

m = ab^(-k) mod p

Specifically in Python, I want to compute the following equivalent:

>>> m = (b**(-k) * a) % p

The issue in the above Python code is that the numbers inserted would overflow or result in 0.0 due to precision. Consider the following example:

>>> (15653**(-3632) * 923) % 262643
0.0

The expected answer for the above example is 152015.

More Examples

enter image description here

Attempts

I've tried to research a strategy to deal with this problem and found that using Python's default pow(x,y,z), which differs from math.pow(), can help.

pow(x,y,z) is equivalent to x**y % z

However, I cannot use pow(x,y,z). I tried to use pow(15653, -3632, 262643), but I cannot multiply the result of pow(15653, -3632) by 923 to then, as a final step, mod by 262643.

In other words, instead of x**y % z, I am trying to perform (x**y * a ) % z, but there is clearly a 3-parameter limit or number of operations from pow(x,y,z).

What can I do to compute the math formula in Python?

lattejiu
  • 119
  • 8
  • Welcome to [Stack Overflow.](https://stackoverflow.com/ "Stack Overflow") Please be aware this is not a code-writing or tutoring service. We can help solve specific, technical problems, not open-ended requests for code or advice. Please edit your question to show what you have tried so far, and what specific problem you need help with. See the [How To Ask a Good Question](https://stackoverflow.com/help/how-to-ask "How To Ask a Good Question") page for details on how to best help us help you. – itprorh66 Dec 12 '21 at 18:29
  • @itprorh66 Refer to my ## Attempts ## section. – lattejiu Dec 12 '21 at 18:34

1 Answers1

2

Very easily: just multiply the two, and do an explicit mod:

>>> p = 262643
>>> pow(15653, -3632, p)
86669
>>> 86669 * 923 % p
152015

Done!

Tim Peters
  • 67,464
  • 13
  • 126
  • 132
  • Could you share why this works in terms of the way you pow(15653, -3632, p) * 923 % p ? I am unfamiliar with the math manipulation you just did. – lattejiu Dec 12 '21 at 18:40
  • `a * b % p` groups as `(a * b) % p` - it's so straightforward I'm having a hard time understanding what the confusion could be ;-) Here `a` is `pow(15653, -3632, p)` and `b` is `923`. – Tim Peters Dec 12 '21 at 18:42
  • Yes, that is a very clear explanation, and that the two forms are equivalent and straightforward. However, I'm specifically confused about why `a` was mod by p initially. In my head, I assumed that `a=pow(15653, -3632)` first, then multiple by `b`, so that the product of `a x b` is finally mod by p. Mathematically, your method was also correct. I suppose what I am asking is this: why is it that in `a`, when you mod the result by P, it still works? – lattejiu Dec 12 '21 at 18:49
  • 1
    It's the definition of Python's `pow(a, -b, p)` that it returns the inverse of `a` modulo `p`, raised to `b` power (again modulo `p`). Not a matter of deduction, but of what the language guarantees. Or if that's not the hangup, perhaps it's more fundamental: it's a truth of modular arithmetic that `(a * b) % p = ((a % p) * b) % p = (a * (b % p)) % p = ((a % p) * (b % p)) % p`. Much the same is true of modular `+`, or of mixtures of `+` and `*`. It makes no difference to the final result how many times you apply `% p` to intermediate results. – Tim Peters Dec 12 '21 at 20:17
  • Thank you for the in-depth explanation, I can see my knowledge gap -- particularly with the inverse modulo `-b`. Cheers :) – lattejiu Dec 12 '21 at 20:29