【问题标题】:How to find reverse of pow(a,b,c) in python?如何在python中找到pow(a,b,c)的反向?
【发布时间】:2018-04-13 13:39:39
【问题描述】:

pow(a,b,c) python 中的运算符返回 (a**b)%c 。如果我有bc的值,以及此操作的结果(res=pow(a,b,c)),我如何找到a的值?

【问题讨论】:

  • 我认为没有明确的解决方案。考虑一下:(4**2)%2(6**2)%2 都计算为 0。因此,只要 b = 2 和 c = 2 和 a^b%c=0,你不知道 a 是 4 还是 6 或任何其他偶数那件事。
  • 我相信这被称为“离散对数问题”?如果我错了,请纠正我。
  • 我推荐暴力破解。用于密码学是有原因的。
  • Azsgy 是正确的。有关这方面的更多信息,请谷歌“离散对数”。
  • @Azsgy 不是要求指数,而不是求底吗?

标签: python math encryption cryptography modulus


【解决方案1】:

尽管在 cmets 中有陈述,这不是离散对数问题。这更类似于RSA problem,其中c 是两个大素数的乘积,b 是加密指数,a 是未知明文。我总是喜欢让x 成为你想要求解的未知变量,所以你有y= xb mod c 其中ybc 是已知的,你想解决x。求解它涉及与 RSA 中相同的基本数论,即您必须计算 z=b-1 mod λ(c),然后您可以通过 x = 求解 x yz mod c. λ 是Carmichael's lambda function,但您也可以改用欧拉的 phi(totient)函数。我们已将原始问题简化为计算逆模 λ(c)。如果c 容易因式分解或者我们已经知道c 的因式分解,这很容易做到,否则很难。如果c 很小,那么暴力破解是一种可接受的技术,您可以忽略所有复杂的数学运算。

这里是一些显示这些步骤的代码:

import functools
import math


def egcd(a, b):
    """Extended gcd of a and b. Returns (d, x, y) such that
    d = a*x + b*y where d is the greatest common divisor of a and b."""
    x0, x1, y0, y1 = 1, 0, 0, 1
    while b != 0:
        q, a, b = a // b, b, a % b
        x0, x1 = x1, x0 - q * x1
        y0, y1 = y1, y0 - q * y1
    return a, x0, y0


def inverse(a, n):
    """Returns the inverse x of a mod n, i.e. x*a = 1 mod n. Raises a
    ZeroDivisionError if gcd(a,n) != 1."""
    d, a_inv, n_inv = egcd(a, n)
    if d != 1:
        raise ZeroDivisionError('{} is not coprime to {}'.format(a, n))
    else:
        return a_inv % n


def lcm(*x):
    """
    Returns the least common multiple of its arguments. At least two arguments must be
    supplied.
    :param x:
    :return:
    """
    if not x or len(x) < 2:
        raise ValueError("at least two arguments must be supplied to lcm")
    lcm_of_2 = lambda x, y: (x * y) // math.gcd(x, y)
    return functools.reduce(lcm_of_2, x)


def carmichael_pp(p, e):
    phi = pow(p, e - 1) * (p - 1)
    if (p % 2 == 1) or (e >= 2):
        return phi
    else:
        return phi // 2


def carmichael_lambda(pp):
    """
    pp is a sequence representing the unique prime-power factorization of the
    integer whose Carmichael function is to be computed.
    :param pp: the prime-power factorization, a sequence of pairs (p,e) where p is prime and e>=1.
    :return: Carmichael's function result
    """
    return lcm(*[carmichael_pp(p, e) for p, e in pp])

a = 182989423414314437
b = 112388918933488834121
c = 128391911110189182102909037 * 256
y = pow(a, b, c)
lam = carmichael_lambda([(2,8), (128391911110189182102909037, 1)])
z = inverse(b, lam)
x = pow(y, z, c)
print(x)

【讨论】:

    【解决方案2】:

    你能做的最好的事情是这样的:

    a = 12
    b = 5
    c = 125
    
    def is_int(a):
        return a - int(a) <= 1e-5
    
    # ============= Without C ========== #
    print("Process without c")
    rslt = pow(a, b)
    
    print("a**b:", rslt)
    
    print("a:", pow(rslt, (1.0 / b)))
    
    # ============= With C ========== #
    print("\nProcess with c")
    rslt = pow(a, b, c)
    
    i = 0
    while True:
    
        a = pow(rslt + i*c, (1.0 / b))
    
        if is_int(a):
            break
        else:
            i += 1
    
    print("a**b % c:", rslt)
    print("a:", a)
    

    您永远无法确定是否找到了正确的模值,它是与您的设置兼容的第一个值。该算法基于 a、b 和 c 是整数这一事实。如果不是,则您无法找到原始组合的可能组合。

    输出:

    Process without c
    a**b: 248832
    a: 12.000000000000002
    
    Process with c
    a**b % c: 82
    a: 12.000000000000002
    

    【讨论】:

    • “你能做到的最好的” [需要引用]
    • 抱歉,这不仅不是你能做的最好的,而且是不正确的。这假设参数是浮点数,但 python 中的 pow(a,b,c) 仅在 所有参数都是整数时才有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多