[Python密码学]--凯撒加密及换位加密法

凯撒加密法

所谓凯撒加密是一种替换加密的技术,明文中的所有字母都在字母表上向后(或向前)按照一个固定数目进行偏移后被替换成密文。
例如,当偏移量是3的时候,所有的字母A将被替换成D,B变成E,以此类推。
明: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
密:D E F G H I J K L M N O P Q R S T U V W X Y Z A B C

message = 'hello world! Nice to meet you.'
key = 13
mode = 'encrypt'   # encrypt or decrypt  选择加密或解密
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
translated = ''
message = message.upper()  #字母转为大写
for symbol in message:
    if symbol in letters:
        num = letters.find(symbol)
        if mode == 'encrypt':
            num = num + key
        elif mode == 'decrypt':
            num = num - key

        if num >= len(letters):
            num = num - len(letters)
        elif num < 0:
            num = num + len(letters)

        translated = translated + letters[num]
    else:
        translated = translated + symbol

print(translated)

首先创建了一个名为letters的字符集,然后将需要加密的内容按照字符集中的顺序偏移进行加密。如:
H在字符集中是第7位(从0开始数)偏移13位(密匙)则是U(第20位)
O在字符集中是第14位偏移13位则是27位,但是字符集只有26位,便减去26等于1(B)

明文字母 明文数字 密匙 结果 密文字母
H 7 13 20 20=U
E 4 13 17 17=R
L 11 13 24 24=Y
L 11 13 24 24=Y
O 14 13 27>26 27-26=1=B

所以最后的结果为:URYYB JBEYQ! AVPR GB ZRRG LBH.
解密的方法也是如此,若所得的结果小于0时,则相应的加上26。

暴力破解

message = 'URYYB JBEYQ! AVPR GB ZRRG LBH.'
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

for key in range(len(letters)):
    translated = ''
    for symbol in message:
        if symbol in letters:
            num = letters.find(symbol)
            num = num - key

            if num < 0:
                num = num + len(letters)

            translated = translated +letters[num]
        else:
            translated = translated + symbol
    print('key #%s: %s ' %(key,translated))

我们只需要尝试26种不同密匙就能将凯撒加密法破译,而计算机能够轻而易举的完成这件工作。显然为了确保信息的安全,这种密匙少容易破解的加密法是不适合的。

换位加密法

换位加密法很好的解决了密匙少易破解的缺陷

加密方法

换位加密法不是把字符替换成其他字符,而是搞乱消息符号的顺序,使原来的的消息不可读。
假设我们的密匙为8,则先画出8个格子,依次放入一个字符。如果不够再添加一行
在这里插入图片描述
最后两个灰色的格子是为了提醒我们忽略他们。密文是从左上往下读:Hretel ldtyl!ooo u Nm.wieoce (最后两个灰色格子不算入其内)

#transpositionEncrypt.py

def main():
    myMessage = 'Hello world! Nice to meet you.'
    myKey = 8

    ciphertext = encryptMessage(myKey,myMessage)
    print(ciphertext + '|')  #密文末尾加上 | 符号是为了方便看出密文末尾是否有空格符

def encryptMessage(key,message):
    ciphertext = [''] * key
    for col in range(key):
        pointer = col
        
        while pointer < len(message):
            ciphertext[col] += message[pointer]
            pointer += key

    return ''.join(ciphertext)
if __name__ == '__main__':
    main()

在while循环中,我们会把每隔key个字符挑选出来放入ciphertext[col]中
如果我们将while循环改为:在这里插入图片描述
运行结果为:
在这里插入图片描述

join()方法
在shell做个小测试
在这里插入图片描述
join()方法的用途就是接受一个字符串列表,返回一个字符串
调用join()方法的字符串会放在列表字符串的中间,如’00’.join(h)

解密

解密方法和加密其实是差不多的(这里密匙同样是8)

  1. 在这里密文有30个字符,计算30/8=3.75 向上取整则为4。所以需要画出一个8行4列的网格
  2. 再算出最后一列需要涂灰(忽略)多少个网格(8 x 4 - 30 = 2)
    在这里插入图片描述
  3. 依次从左上开始向右填入密文’Hretel ldtyl!ooo u Nm.wieoce’ 记住忽略的地方不填入
    在这里插入图片描述
  4. 左上角向下读出明文‘Hello world! Nice to meet you.’
#transpositionDecrypt.py

import math

def main():
    myMessage = 'Hretel  ldtyl!ooo  u Nm.wieoce'
    myKey = 8

    plaintext = decryptMessage(myKey,myMessage)
    print(plaintext + '|')

def decryptMessage(key,message):
    numOfColumns = math.ceil(len(message) / key)  #求出所需列数
    numOfRows = key
    numOfShadeedBoxes = (numOfColumns * numOfRows) - len(message)  #计算灰格子个数 

    plaintext = [''] * numOfColumns  #创建列表
 
    col = 0
    row = 0
    for symbol in message:
        plaintext[col] += symbol
        col += 1

        if(col == numOfColumns) or (col == numOfColumns - 1 and row >= numOfRows - numOfShadeedBoxes):
            col = 0
            row += 1
    return ''.join(plaintext)

if __name__ == '__main__':
    main()

在这里插入图片描述
在这个循环中,第一步是把symbol连接到plaintext列表中col位置的字符串。接着就是col自增,以便symbol会被连接到下一个字符串。

在这里插入图片描述
有两种情况我们会把col重新设为0。一、col超过plaintext的最后一个索引(即col=numOfColumns)二、col等于最后一个索引,且row指向的行在最后一列有灰色格子。
在这里插入图片描述
在这里插入图片描述
见详细过程:
在这里插入图片描述
这里其实就可以发现换位加密法的密匙与需要加密的密文长度有关,如果需要加密的只有十几个字符,但是密匙确实二十,显而易见这样的加密是毫无意义的。但是如果你的密文是长篇大论,那么就会有成千上万个密匙。

换位加密法加密文件

import os,time,sys,transpositionEncrypt,transpositionDecrypt

def main():
    inputFilename = 'hello.txt'
    outputFilename = 'hello.encrypted.txt'

    myKey = 10
    myMode = 'encrypt'  #encrypt or decrypt


    #检查待读文件是否存在
    if not os.path.exists(inputFilename):
        print('%s 文件不存在' %(inputFilename))
        sys.exit()
    if os.path.exists(outputFilename):
        print('%s 文件已存在,将会覆盖原文件。是否继续? YES or NO?' %(outputFilename))
        response = input('>')
        if not response.lower().startswith('y'):
            sys.exit()
    
    #读文件
    fileObj = open(inputFilename)
    content = fileObj.read()
    fileObj.close()

    print('%sing...' %(myMode.title()))
    
    if myMode == 'encrypt':
        translated = transpositionEncrypt.encryptMessage(myKey,content)
    elif myMode == 'decrypt':
        translated = transpositionDecrypt.decryptMessage(myKey,content)
        
    outputFileObj = open(outputFilename,'w')
    outputFileObj.write(translated)
    outputFileObj.close()

    print('over')
if __name__ == '__main__':
    main()

Al Sweigart《Python密码学编程》读后笔记

猜你喜欢

转载自blog.csdn.net/qq_41853244/article/details/89017492
今日推荐