码迷,mamicode.com
首页 > 编程语言 > 详细

Python乘法密码

时间:2017-11-30 12:14:26      阅读:566      评论:0      收藏:0      [点我收藏+]

标签:todo   partial   密钥   for   world   欧几里得   isp   log   个数   

乘法密码

属于替换密码技术的一种
乘法密码技术的加密变换:\[ Ek(Ai)=Aj \]\[j=ik(mod n) ,gcd(k,n)=1\]

  • 0<k<n
  • kn互素,即要满足gcd(k, n)=1,否则不存在模逆元,不能正确解密

设明文消息为M,消息元素为m元素下标为i;
则密文消息为C,密文元素为c元素下标为j; \[c=i*k mod n\]

乘法密码的密码空间大小,即小于n且与n互素的非负整数的个数,是\(φ(n)\)\(φ(n)\)是欧拉函数。
n26字母,则与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

  • 明文字母 \[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z\]
  • 数组下标 \[0 ,1 ,2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 \]
  • 密文字母 \[a ,j, s, b, k, t, c, l, u, d, m, v, e, n, w, f, o, x, g, p, y, h, q, z, i, r, \]
  • 数组下标 \[0 ,9, 18, 1, 10, 19, 2, 11, 20, 3, 12, 21, 4, 13, 22, 5, 14, 23, 6, 15, 24, 7, 16, 25, 8, 17 \]

正如上所述,从下标0开始, 明文a: 0X9%26=0 -->[0]=a 明文b: 1X9%26=9 -->[9]=j
其实即是通过公式算出密文密码表,其意义与明文表相一一对应。

乘法密码技术的解密变换: \[Dk(Aj)=Ai\]
\[i=jX(mod n)\]

? \(X\)\(k\)的逆元(最小正整数)
对于正整数 kn,如果有\(kX≡1(mod n)\),那么把这个同余方程中\(X\)的最小正整数解叫做\(k模n\)的逆元。

由于\(k\)的取值是从\(φ(n)\) 密码空间中获得,则必定k 123 = 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)

Python乘法密码

标签:todo   partial   密钥   for   world   欧几里得   isp   log   个数   

原文地址:http://www.cnblogs.com/oneTOinf/p/7927827.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!