《Python密码学编程》笔记

本文介绍了多种加密技术,包括凯撒加密、换位加密、仿射加密等,并探讨了其加密原理、应用及破解方法。此外,还涉及了公钥密码学、RSA加密法等高级加密技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

源码地址:https://github.com/StarsAaron/cryptology_python
源码我重新整理和添加注释,方便理解。

这本书很基础,就算不会Python的语法也没关系,每一章都很详细的介绍算法每一步的意思。

第一章:加密纸质工具
做凯撒加密解密用到的工具:
(1)加密轮盘



密钥范围0~25

(2)St.Cyr滑条


第五章:反转加密(Reverse Cipher)

好像把明文水平翻转180度的效果。例如将“Hello World” 加密成 “dlroW olleH”

这是一种非常弱的加密方式。

message = "Three can keep a secret,if two of them are dead."
translated = ''

i = len(message) - 1
while i >= 0:
    translated = translated + message[i]
    i = i - 1
print translated

第六章:凯撒加密法(Caesar cipher)
它根据字母表将消息中的每个字母移动常量位k。
举个例子如果k等于3,则在编码后的消息中,每个字母都会向前移动3位:a会被替换为d;b会被替换成e;依此类推。字母表末尾将回卷到字母表开头。于是,w会被替换为z,x会被替换为a。
message = "this is my secret message"
key = 13

mode = "encrypt"
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

第七章:暴力破解凯撒加密法
对于我们上面那种情况的凯撒加密法,我们可以发现可能的秘钥最多只有26个。于是我们可以尝试暴力破解,即尝试每一个可能的秘钥。
message = "GUVF VF ZL FRPERG ZRFFNTR"
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 += len(LETTERS)
            translated += LETTERS[num]
        else:
            translated += symbol
    print "Key %s : %s"%(key , translated)
message 存储了密文。其余代码对应了上面的 decrypt 模式。

我们打印出了26中可能的解密。


第八章:换位加密法加密

换位加密法不是替换字符,而是搞乱消息符号的顺序。

例如消息 Common sense is not so common.

假设使用数字 8 作为秘钥。也就是我们将在每一行放最多8个字符。(包含空格和标点)

对于上面这条消息,我们可以画出这样一个方格图

Common s
ense is 
not so c
ommon.  

最后一行的两个格子涂黑忽略它们。

正常的阅读方式应该是横向去读。如果我们把消息用列向表示出来,它的混乱程度足以让别人看不清原来的消息

密文是:Cenoonommstmme oo snnio. s s c(表中的空格需要表示,黑色方格直接忽略)

def main():
    myMessage = "Common sense is not so common."
    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()

具体到 encryptMessage 函数。我们首先创建了一个 list ,其中包含了 8(key)个空元素。这对应了上面表格中的8 (key) 列。

我们遍历这 8 列。

在第一列,我们依次拼接 原 message 中的 第 0,8,16,24......个字符。直到超出了 message 的长度。

在第二列,我们依次拼接 原 message 中的 第 1,9,17,25......个字符。直到超出了 message 的长度。

以此类推。

.join 方法将 list 转换为字符串然后 return。

 

第九章:换位加密法的解密

当我们收到密文和秘钥之后。我们需要画一个表格。表格行数等于秘钥,列数等于密文长度除以秘钥然后向上取整。

例如 密文 “Cenoonommstmme oo snnio. s s c”长度30,秘钥key = 8,我们需要画8行4列的表格

从左上角开始向右填。那么从上往下阅读时我们会看到明文(其实这两个表格的关系就类似于矩阵的倒置)

Ceno
onom
mstm
me o
o sn
nio.
 s  
s c 
import math

def main():
    myMessage = "Cenoonommstmme oo snnio. s s c"
    myKey = 8
    
    ciphertext = decryptMessage(myKey , myMessage)
    
    print ciphertext + "|"
    
def decryptMessage(key , message):
    numOfColumns = int(math.ceil(len(message) / float(key)))
    numOfRows = key
    numOfShadeBoxes = (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 - numOfShadeBoxes:
            col = 0
            row += 1
    return ''.join(plaintext)
    
if __name__ == "__main__":
    main()

这个程序完全按照和前面填表格的方式进行。

先从第0行开始,依次填第零列,第一列,第二列,第三列

然后跳到下一行,依次进行

其中。numOfShadedboxes 表示的是黑方格数,也就是默认不填字符的位置。程序会跳过这些地方填字符。

好的。现在让我们来写一个测试程序证明前面的加密和解密程序在对应不同的 message 和 key 时确实能正常工作。
import random,sys,transpositionEncrypt,transpositionDecrypt

def main():
    random.seed(42)
    for i in xrange(20):
        message = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" * random.randint(4,40)
        message = list(message)
        random.shuffle(message)
        message = ''.join(message)
        print "Test #%s : %s..."%(i+1,message[:50])
        
        for key in xrange(1,len(message)):
            if message != transpositionDecrypt.decryptMessage(key , transpositionEncrypt.encryptMessage(key, message)):
                print "Mismatch with key %s and message %s"%(key , message)
                sys.exit()
    print "Transposition cipher test passed."
    
if __name__ == "__main__":
    main()
测试中,我们生成了一个全英文字母的随机字符串并打乱了顺序,通过测试在将一个字符串加密再解密后是否能得到原来的字符串来判断程序是否正常工作。

第14章:取模运算与乘数加密法和仿射加密法
乘数加密法:区别于凯撒加密法,采用乘数运算(凯撒采用移位运算)再对26取模。
缺点:A字母对应的都是A字母,因为A字母对应的是数字0。

仿射加密法乘数加密法+凯撒加密法。
乘数加密法的缺陷,配合凯撒加密移位运算可以解决这个问题。

仿射加密存在的2个问题:
(1)密钥A不能取任何的数字
不同的字符可能被映射成同一个字符。
仿射加密,密钥A数字和符号集的大小必须互质,例如:密钥7跟字符集大小26是互质的,可以使用。
(2)可以有多少个密钥
密钥A也是“回调”的,假设符号集的大小是26,使用密钥27和密钥1加密的文字效果是一样的,3和98,2和97等

加密
仿射加密有两个密钥,第一个密钥A是字母的数字将要乘以的整数。在这个数字对26取模之后,第二个密钥B将加到这个数字再次对26取模。



解密
解密需要乘以密钥的模逆,两个数字a和m的模逆i要满足(a*i)%m=1。
仿射加密的加密密钥和解密密钥是不同的数字。

第17章:简单替代加密法
随机选择字母加密字母表的每个字母。
例如其中的一种:


第18章:破译简单替代加密法
明文单词和它的密文单词具有相同的单词模式。
替代加密法具有很多种可能的密钥,采用暴力的遍历各种可能密钥是很费劲的,这里我们采用复杂一点的算法巧妙实现破译。

计算单词模式,例如加密后的单词
HGHHU
看出:
(1)5个字母长度
(2)第1,3,4个字母一样
(3)有2个不同字母
能跟这些规则匹配的单词有“Puppy” “Mommy”等。再进一步推断出候选的单词列表



密文越长,越可能被破译。

第19章:维吉尼亚加密法
加密密钥PIZZA,循环使用




第20章:破解维吉尼亚加密法
不要使用英语单词作为加密密钥,容易受到字典攻击。


第22章:一次一密加密法
不可破的加密法。
在维吉尼亚加密法基础上增加以下条件:


第23章:寻找质数
质数:大于1且因数只有1和它本身的整数
(1)使用除法判断
(2)埃拉托色尼筛选算法,比上面的算法更快算出是否是质数
算法:把1标记为非质数,然后把所有2的倍数(除2本身)标记为非质数,3的倍数标记为非质数...一直算到8,大于7.071(50的平方根)就可以算出50以内的所有质数



拉宾米勒质数检测算法

埃拉托色尼筛选算法可以快速判断是不是质数,但需要大量内存。
埃拉托色尼筛选算法和简单的isPrime()函数不足以处理大数字的。拉宾米勒质数检测算法就可以算出有数百为长数字是否是质数。

第24章 公钥密码学和RSA加密法
加密区块=明文区块^e取模n
解密区块=密文区块^d取模n




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

繁星点点-

请我喝杯咖啡呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值