python仿射变换求乘法逆元扩展欧几里得

概念

给出2个数M和N(M < N),且M与N互质,找出一个数K满足0 < K < N且K * M % N = 1,满足条件的K则为M的逆元

暴力求解法

def get(m,n):
	for i in range(1,n-1):
		if i*m%n==0:
			return i

扩展欧几里得求解法

如果y是n的逆元,则mx+ny =gcd(m,n),那么如何求y呢

已知m,n是互素的,最终状态时

m*1+n*0 = 1

那么一直求上一个状态逆推回去到右边为gcd(m,n)时,求得逆元y

下面分析下从mx+ny =gcd(m,n)推导到m1+n0 = 1

m = kn +余数 m%n = m - kn = m - m//n,得

nx + (m-m//n)*y = gcd(n,m%n),化简为

m*y(上一步的y) + n *(x-(m//n)*y)

正推每一步的下一状态,其中x,y都是上一步的,下一步的m,n 为x , y的系数

而根据欧几里得定理mx+ny =gcd(m,n) = m1+n0 = 1,故可以这样计算

xnext = y
ynext = x - m//n*y

使用递归,结束条件为x = 1,y = 0,反推回来,最终状态的上一状态

xbefore = m//n
ybefore = 1

代码

def EX_GCD(a,b,arr): #扩展欧几里得
    if b == 0:
        arr[0] = 1
        arr[1] = 0
        return a
    g = EX_GCD(b, a % b, arr)
    t = arr[0]
    arr[0] = arr[1] #x before = y
    arr[1] = t - int(a / b) * arr[1]
    return g

测试

arr = [0]*2
EX_GCD(47,30,arr)
print(arr[1])

输出11,因为30*11 = 47 * 7+1

    EX_GCD(26,7,arr)
    print(arr[1])

尴尬,输出的是-11,需要再规范输出,-11+26=15就是7 mod 26的逆元

7*15 = 26 * 4+1

应用之仿射变换

两个密钥,取值范围为 0 到 25

加密函数f(x) = (k1*m + k0 )mod 26

解密 f − 1 f^-1 f1(x) =( (f(x)-k0)* k − 1 k^-1 k1)mod26

如果两个数不互素,乘法逆元不唯一,上述算法可能会出错
素性检测

你可能感兴趣的:(密码学,算法,安全)