标签:todo partial 密钥 for world 欧几里得 isp log 个数
属于替换密码
技术的一种
乘法密码技术的加密变换:\[ Ek(Ai)=Aj \]\[j=ik(mod n) ,gcd(k,n)=1\]
0<k<n
k
与n
互素,即要满足gcd(k, n)=1
,否则不存在模逆元,不能正确解密设明文消息为M
,消息元素为m
元素下标为i
;
则密文消息为C
,密文元素为c
元素下标为j
; \[c=i*k mod n\]
乘法密码的密码空间大小,即小于n
且与n
互素的非负整数的个数,是\(φ(n)\),\(φ(n)\)是欧拉函数。
当n
为26
字母,则与26
互素的数是\[{1、3、5、7、9、11、15、17、19、21、23、25}\]
,即\(φ(n)=12\) 因此乘法密码的密钥空间为12
。
注意:k=1
时 加密变换为恒等变换(即无变化)
乘法密码也称采样密码
,因为密文字母表是将明文字母按照下标每隔k
位取出一个字母排列而成。
例如对26
个字母生成密码表(下标由0
开始,0-25
)
取k=9
正如上所述,从下标0
开始, 明文a
: 0X9%26=0 -->[0]=a
明文b
: 1X9%26=9 -->[9]=j
其实即是通过公式算出密文密码表,其意义与明文表相一一对应。
乘法密码技术的解密变换: \[Dk(Aj)=Ai\]
\[i=jX(mod n)\]
? \(X\)为\(k\)的逆元(最小正整数)
对于正整数 k
和n
,如果有\(kX≡1(mod n)\),那么把这个同余方程中\(X\)的最小正整数解叫做\(k模n\)的逆元。
由于\(k\)的取值是从\(φ(n)\) 密码空间中获得,则必定k123 = 1*123+ 0*11
11 = 0*123+ 1*11 |11
2 = 1*123+ (-11)*11 |5
1 = (-5)*123+ 56*11
聪明的你, 一定看出来了吧. 对! 我们将123和11都表示成 x * 123 + y * 11 的 格式, 然后相减, 在最右侧一栏写上每次减去的被减数的倍数. 依次进行, 知道减数变为1为止. 然后我们取第三列的最下面的一个数, 再对123 取模 即得11 对123的模逆.
Python实现求逆元:
from math import floor
def inverseElement(k2, Z=26):
'''
to get the inverse element for k2 % Z
'''
a = [Z, 1, 0]
b = [k2, 0, 1]
while(1):
if b[0] == 1:
break
temp = b
q = floor(a[0] / b[0])
b = [i * q for i in b]
b = [a[i] - b[i] for i in range(len(b))]
a = temp
return b[-1] % Z
完整的加密解密代码:
# -*- coding:utf-8 -*-
from math import floor
def gcd(x, y):
if x < y:
t = x
x = y
y = t
if y == 0:
return x
if y != 0:
return gcd(y, x % y)
else:
# print(x)
return x
def str2num(str):
'''
TODO:transfermation between the unicode num and str
'''
strL = list(str)
numL = [ord(i) - 97 for i in strL]
return numL
def num2str(num):
numL = [i + 97 for i in num]
strL = ''.join([chr(int(i)) for i in numL])
return strL
def inverseElement(k2, Z=26):
'''
to get the inverse element for k2 % Z
'''
a = [Z, 1, 0]
b = [k2, 0, 1]
while(1):
if b[0] == 1:
break
temp = b
q = floor(a[0] / b[0])
b = [i * q for i in b]
b = [a[i] - b[i] for i in range(len(b))]
a = temp
return b[-1] % Z
def encrypted(m, k2, Z=26):
if m not in range(26):
return m
else:
return (k2 * m) % Z
def decrypted(c, k2, Z=26):
if c not in range(26):
return c
else:
return (inverseElement(k2, Z) * (c)) % Z
if __name__ == '__main__':
# 加密部分
str0 = 'hello the cruel world!'
num0 = str2num(str0.lower())
num1 = [encrypted(i, 11) for i in num0]
str1 = num2str(num1)
print('密文 %s' % str1)
# 解密部分
str0 = str1
num0 = str2num(str0.lower())
num1 = [decrypted(i, 11) for i in num1]
str1 = num2str(num1)
print('明文 %s' % str1)
标签:todo partial 密钥 for world 欧几里得 isp log 个数
原文地址:http://www.cnblogs.com/oneTOinf/p/7927827.html