一、编码的方式是可以公开获得并理解的。
电报只能发送两种类型的电脉冲:称为“点”的短脉冲和称为线的长脉冲。
通过编码系统,将英语转换成电报发送的点和线的过程称为编码,反之则为解码。电报(和后来的无线电)对消息进行编码和解码的方式称为摩尔斯电码
二、凯撒密码:移位替换法进行加密,例如A->D,Y->B字母后移三位进行替换
密码轮:内部是密文和密钥数字,外部A对应数字是几密钥就是几。内部数字0-25和字母A-Z一一对应。
python编码的凯撒加/解密:
#凯撒密码(0~25密钥)
#pyperclip是把消息复制到剪贴板的操作工具
#import pyperclip
#要加解密的字符串
message='7uv6Jv6Jz!Jq2tM'
#加/解密钥
key=13
mode='decrypt'#设置encrypt或者decrypt
#可能被加密的字符
SYMBOLS='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !?.'
symlen=len(SYMBOLS)
#存储消息的字符串
translated=''
for symbol in message:
if symbol in SYMBOLS:
symbolIndex=SYMBOLS.find(symbol)
if mode=='encrypt':
translatedIndex=symbolIndex+key
elif mode=='decrypt':
translatedIndex=symbolIndex-key
if translatedIndex>=symlen:
translatedIndex-=symlen
elif translatedIndex<0:
translatedIndex+=symlen
translated=translated+SYMBOLS[translatedIndex]
else:
translated=translated+symbol
print(translated)
#把字符串贴进剪切板
#pyperclip.copy(translated)
三、反向密码:通过将信息逆序来输出及加密信息的。比如:“Hello,world” 加密后:dlrow,olleH
#反向密码加解密
message=input("请输入需要加密的或者解密的字符:")
translated=''
i=len(message)-1
while i>=0:
translated=translated+message[i]
i=i-1
print(translated)
四、置换密码
原理:通过对原始消息中的字符重新排列,使其变得不可读。口代表空的意思
置换程序加密方法:transpositionDecrypt.py
def main():
myMessage='Cmmon sense is not so common.'
myKey=8
ciphertext=encryptMessage(myKey,myMessage)
print(ciphertext+'|')
def encryptMessage(key,message):
ciphertext=['']*key#給列赋空值
for column in range(key):
currentIndex=column
while currentIndex < len(message):
ciphertext[column]+=message[currentIndex]
currentIndex+=key
return ''.join(ciphertext)
#如果运行本文件不作为模块引用,则调用mian函数
if __name__=='__main__':
main()
置换解密代码:transpositionEncrypt.py
import math
def main():
myMessage="Cnommstmme oo snnio. s s ceno"
myKey=8
plaintext=decryptMessage(myKey,myMessage)
print(plaintext+'|')
def decryptMessage(key,message):
#列表中列的数目
numOfColumns=int(math.ceil(len(message)/float(key)))
#列表行数目
numOfRows=key
#转换表中阴影的数量
numOfShadeBoxes=(numOfColumns*numOfRows)-len(message)
#铭文中每个字符串表示一列
plaintext=['']*numOfColumns
column=0
row=0
for symbol in message:
plaintext[column]+=symbol
column+=1
if(column==numOfColumns)or(column==numOfColumns-1 and row>=numOfRows-numOfShadeBoxes):
column=0
row+=1
return ''.join(plaintext)
if __name__=='__main__':
main()
置换密码测试程序
import random,sys,transpositionEncrypt,transpositionDecrypt
def main():
random.seed(42)#随机种子,设置种子使random.randint生成伪随机数
for i in range(20):
message='ABCDEFGHIJKLMNOPQRSTUVWXYZ'*random.randint(4,40)#指数追加数据
message=list(message)#强制转换成数组
random.shuffle(message)#打散数组
message=''.join(message)#重组字符串
print('Test #%s:"%s..."'%(i+1,message[:50]))#展示前50个字符
for key in range(1,int(len(message)/2)):
encrypted=transpositionEncrypt.encryptMessage(key,message)
decrypted=transpositionDecrypt.decryptMessage(key,encrypted)
if message!=decrypted:
print('Mismatch with key %s and message %s.'%(key,message))
print('Decrypted as:'+decrypted)
sys.exit()
print('Transposition cipher test passed.')
if __name__=='__main__':
main()
置换密码加密文件代码:
import time,os,sys,transpositionEncrypt,transpositionDecrypt
def main():
inputFilename='frankenstein.txt'
outputFilename='frankenstein.encrypted.txt'
myKey=10
myMode='encrypt'
if not os.path.exists(inputFilename):
print('The file %s does not exist.Quitting..'%(inputFilename))
sys.exit()
if os.path.exists(outputFilename):
print('This will overwrite the file %s.(C)ontinue or (Q)uit?'%(outputFilename))
response=input('> ')
if not response.lower().startswith('c'):
sys.exit()
#从输入文件中读取信息
fileObj=open(inputFilename)
content=fileObj.read()
fileObj.close()
print('%sing...'%(myMode.title()))
#测量加解密所需时间
startTime=time.time()
if myMode=='encrypt':
translated=transpositionEncrypt.encryptMessage(myKey,content)
elif myMode=='decrypt':
translated=transpositionDecrypt.decryptMessage(myKey,content)
totalTime=round(time.time()-startTime,2)
print('%ssion time:%s seconds'%(myMode.title(),totalTime))
#将置换后的消息写入输出文件
outputFileObj=open(outputFilename,'w')
outputFileObj.write(translated)
outputFileObj.close()
print('Done %sing %s (%s characters).'%(myMode,inputFilename,len(content)))
print('%sed file is %s.'%(myMode.title(),outputFilename))
if __name__=='__main__':
main()
解密只需要改这几项即可
2、小知识
open('test.txt')打开文件,假如跟程序同一文件夹可以直接写文件名称和后缀,文件的绝对路径
window:C:\\Users\\Aii\\test.txt
mac和linux:/User/AI/text.txt
3、英语检测模块
通过文件的方式呈现英语单词 ,分别进行对比,减少人工对比的吃力
UPPERLETTERS='ABCDEFGHIJKLMNOPQRSTUVVWXYZ'
LETTER_AND_SPACE=UPPERLETTERS+UPPERLETTERS.lower()+' \t\n'
def loadDictionary():
dictionaryFile=open('dictionary.txt')
englishWords={}
for word in dictionaryFile.read().split('\n'):
englishWords[word]=None
dictionaryFile.close()
return englishWords
ENGLISH_WORDS=loadDictionary()
def getEnglishCount(message):
message=message.upper()
message=removeNonLetters(message)
possibleWords=message.split()
if possibleWords==[]:
return 0.0
matches=0
for word in possibleWords:
if word in ENGLISH_WORDS:
matches+=1
return float(matches)/len(possibleWords)
#去除特殊符号
def removeNonLetters(message):
lettersOnly=[]
#分别把字符串的字符都单出来
for symbol in message:
if symbol in LETTERS_AND_SPACE:
lettersOnly.append(symbol)
return ''.join(lettersOnly)
def isEnglish(message,wordPercentage=20,letterPercentage=85):
wordsMatch=getEnglishCount(message)*100>=wordPercentage
numLetters=len(removeNonLetters(message))
messageLettersPercentage=float(numLetters)/len(message)*100
lettersMatch=messageLettersPercentage>=letterPercentage
return wordsMatch and LettersMatch
五、仿射密码的模运算模块
乘法密码和凯撒密码相似,只是加密是通过乘法而非加法进行的。
仿射密码结合了乘法密码和凯撒密码,实现更强、更可靠的加密。
模运算或称时钟运算,是指当数字达到某一特定值时,对其取模。
模(mod)运算符%,可以看成求余运算。例如:当前时间10点,再经过100小时是几点(10+100)%12=2
因子:一个数的因子可以整除这个数而没有余数,因子也称约数
最大公约数(GCD):两个数的公共因子中最大的那个即是最大公约数
多重赋值:key1,key2,key3=['alice','ada','lion']
多重赋值多用于交换值
spam,eggs=eggs,spam
欧几里得算法:用模运算求得两个数的最大公约数。
比如:34,20
余数============除数
34%20(14)=====20
20%14(6)======14
14%6(2)=======6
6%2(0)========2
由以上可知,34和20的最大公约数是2
def gcd(a,b):
while a!=0:
a,b=b%a,a
return b
在乘法密码中,密钥和符号集的大小必须互素(或互质)。换句话说他们的最大公约数(GCD)是1,或者他们没有除了1以外的公因子。
因此66个字符集只有20个不同的密钥可以用于乘法密码,比凯撒密码的密钥还要少
仿射密码有两个密钥A和B
对仿射密码进行解密,需要乘以密钥的模逆,(a*i)%m==1,其中i是模逆,即逆元(密钥)
仿射密码解密需要获取密钥,(密文*密钥)%符号集大小=明文
欧几里得算法:gcd(a,b)=gcd(b,a%b)
欧几里得扩展算法:ax + by = gcd(a,b)=1
则x是a模b的乘法逆元,y则是b模a的乘法逆元。
- a%b = a - (a/b)*b
- gcd(a, b) =gcd(b,a%b)= b*x1 + (a-(a/b)*b)*y1
= b*x1 + a*y1 – (a/b)*b*y1
= a*y1 + b*(x1 – a/b*y1)
结论:x = y1,y = x1 – a/b*y1
欧几里得停止状态:a=1,b=0则b的状态就不会考虑了,x=gcd(a,b)
加:(a+b) mod m = ((a mod m) + (b mod m)) mod m
减:(a-b) mod m = ((a mod m) - (b mod m)) mod m
乘:(a*b) mod m = ((a mod m) * (b mod m)) mod m
#求模逆
def findModInverse(a,m):
#返回a % m的模逆,它是一个数字
#(a*x)%m=1
if gcd(a,m)!=1:
return None#如果a,m不互素,就不进行模逆
#使用欧几里得扩展算法计算逆元u相当于x,v相当于y,因此u1是a模m的逆元
u1,u2,u3=1,0,a
v1,v2,v3=0,1,m
while v3!=0:
q=u3//v3#整除
v1,v2,v3,u1,u2,u3=(u1-q*v1),(u2-q*v2),(u3-q*v3),v1,v2,v3
return u1%m
仿射密码加解密
##仿射密码
import sys,random
SYMBOLS='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !?.'
def main():
myMessage="""5QG9ol3La6QI93!xQxaia6aQL9QdaQG1!!axQARLa!!AuaRL
ADQALQG93!xQxaGaAfaQ1QX3o1RQARQL9Qda!AafARuQLX1LQALQI1iQX3o1RN"
5!1RQP36ARu"""
myKey=2894
myMode='decrypt'
if myMode=='encrypt':
translated=encryptMessage(myKey,myMessage)
elif myMode=='decrypt':
translated=decryptMessage(myKey,myMessage)
print('Key:%s'%(myKey))
print('%sed text:'%(myMode.title()))
print(translated)
def getKeyParts(key):
keyA=key//len(SYMBOLS)#乘法
keyB=key%len(SYMBOLS)#加法
return (keyA,keyB)
def checkKeys(keyA,keyB,mode):
if keyA==1 and mode=='encrypt':
sys.exit('Cipher is weak if key A is 1.Choose a different key.')
if keyB==0 and mode=='encrypt':
sys.exit('Cipher is weak if key B is 0.Choose a different key')
if keyA <0 or keyB<0 or keyB>len(SYMBOLS)-1:
sys.exit('key A must be greater than 0 and Key B must be between 0 and %s.'%(len(SYMBOLS)-1))
if gcd(keyA,len(SYMBOLS))!=1:
sys.exit('Key A (%s) and the sysmbol set size (%s) are not relatiiely prime.Choose a different key.'%(keyA,len(SYMBOLS)))
def encryptMessage(key,message):
keyA,keyB=getKeyParts(key)
checkKeys(keyA,keyB,'encrypt')
ciphertext=''
for symbol in message:
if symbol in SYMBOLS:
symbolIndex=SYMBOLS.find(symbol)
ciphertext+=SYMBOLS[(symbolIndex*keyA+keyB)%len(SYMBOLS)]
else:
ciphertext+=symbol
return ciphertext
def decryptMessage(key,message):
keyA,keyB=getKeyParts(key)
checkKeys(keyA,keyB,'decrypt')
plaintext=''
modInverseOfKeyA=findModInverse(keyA,len(SYMBOLS))
for symbol in message:
if symbol in SYMBOLS:
symbolIndex=SYMBOLS.find(symbol)
plaintext+=SYMBOLS[(symbolIndex-keyB)*modInverseOfKeyA%len(SYMBOLS)]
else:
plaintext+=symbol
return plaintext
def getRandomKey():
while True:
keyA=random.randint(2,len(SYMBOLS))
keyB=random.randint(2,len(SYMBOLS))
if gcd(keyA,len(SYMBOLS))==1:
return KeyA*len(SYMBOLS)+keyB
if __name__=='__main__':
main()
仿射密码黑客:
#仿射密码黑客
SILENT_MODE=False
def main():
myMessage="""
"""
hackedMessage=hackAffine(myMessage)
if hackedMessage!=None:
print(hackedMessage)
else:
print('Failed to hack encryption.')
def hackAffine(message):
print('Hacking..')
for key in range(len(SYMBOLS)**2):#开平方
keyA=getKeyParts(key[0])
if gcd(keyA,len(SYMBOLS))!=1:
continue
decryptedText=decryptMessage(key,message)
if not SILENT_MODE:
print('Tried key %s..(%s)'%(key,decryptedText[:40]))
if detectEnglish.isEnglish(decryptedText):
print()
print('Possible encryption hack:')
print('key:%s'%(key))
print('Decrypted message:'+decyptedText[:200])
response=input('>')
if response.strip().upper().startswith('D'):
return decryptedText
return None
六、简单代换密码
可以防止爆破,密钥种类有无数种
规则:上面有序字母表,下面无序字母表一一对应,密钥长度相对来说就比较长
简单代换密码代码(加密)
import random,sys
LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def main():
myMessage="""ko i aig kz moonhnl
i oiuw frkur tmnz itnikgzw rkz kgzwkguwz,rn fkss zuhpwkgkcn kw usmznsq"""
myKey='IYULNOTRKJBSAGMVDHZWPEFXQC'
myMode='decrypt'
if not keyIsValid(myKey):
sys.exit('There is an error in the key or symbol set.')
if myMode=='encrypt':
translated=encryptMessage(myKey,myMessage)
elif myMode=='decrypt':
translated=decryptMessage(myKey,myMessage)
print('Using key %s'%(myKey))
print('The %sed message is:'%(myMode))
print(translated)
#判断两个是否为同一个字符串
def keyIsValid(key):
keyList=list(key)
lettersList=list(LETTERS)
keyList.sort()
lettersList.sort()
return keyList==lettersList
def encryptMessage(key,message):
return translateMessage(key,message,'encrypt')
def decryptMessage(key,message):
return translateMessage(key,message,'decrypt')
def translateMessage(key,message,mode):
translated=""
charsA=LETTERS
charsB=key
if mode=='decrypt':
charsA,charsB=charsB,charsA
for symbol in message:
if symbol.upper() in charsA:
symIndex=charsA.find(symbol.upper())
if symbol.isupper():
translated+=charsB[symIndex].upper()
else:
translated+=charsB[symIndex].lower()
else:
translated+=symbol
return translated
if __name__=='__main__':
main()
代换的密码破解
#简单代换密码破解
import os,re,copy,simpleSubCipher,wordPatterns,makeWordPatternd
LETTERS="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
nonLettersOrSpacePattern=re.compile('[^A-Z\s]')
def main():
message='''Sy l nlx sr pyyacaol ylwj eiswi upar lulsxrj isr
sxrjsxwjr,ia esmm rwctjsxszasj wmpramh,lxo txmarr jia aqsoaxwa'''
print('Hacking')
letterMapping=hackSimpleSub(message)
#将结果显示给用户
print('Mapping:')
print(letterMapping)
print()
print('Original ciphertext:')
print(message)
print()
print('Copying hacked message to clipboard:')
hackeMessage=decryptWithCiherletterMapping(message,letterMapping)
pyperclip.copy(hackedMessage)
print(hackedMessage)
#获取空映射
def getBlankCipherletterMapping():
return {'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':[]}
#获取映射字母
def addLettersToMapping(letterMapping,cipherword,candidate):
for i in range(len(cipherword)):
if candidate[i] not in letterMapping[cipherword[i]]:
letterMapping[cipherword[i]].append(candidate[i])
#取两个映射的交集
def intersectMappings(mapA,mapB):
intersectedMapping=getBlankCipherletterMapping()
for letter in LETTERS:
if mapA[letter]==[]:
intersectedMaaping[Letter]=copy.deepcopy(mapB[letter])
elif mapB[letter]==[]:
intersectedMapping[letter]=copy.deepcopy(mapA[letter])
else:
for mappedLetter in mapA[letter]:
if mappedLetter in mapB[letter]:
intersectedMapping[letter].append(mappedLetter)
return intersectedMapping
#移除已经确定的映射
def removeSolvedLettersFromMapping(letterMapping):
loopAgain=True
while loopAgain:
loopAgain=False
solvedLetters=[]
for cipherletter in LETTERS:
if len(letterMapping[cipherLetter])==1:
solvedLetters.append(letterMapping[cipherletter][0])
for cipherletter in LETTERS:
for s in solvedLetters:
if len(letterMapping[cipherletter])!=1 and s in letterMapping[cipherletter]:
letterMapping[cipherletter].remove(s)
if len(letterMapping[cipherletter])==1:
loopAgain=True
return letterMapping
def hackSimpleSub(message):
intersectedMap=getBlankCipherletterMapping()
cipherwordList=nonLettersOrSpacePattern.sub('',message.upper()).split()
for cipherword in cipherwordList:
candidateMap=getBlankCipherletterMapping()
wordPattern=makeWordPatterns.getWordPattern(cipherword)
if wordPattern not n wordPatterns.allPatterns:
continue
for candidate in wordPatterns.allPatterns[wordPattern]:
addLettersToMapping(candidateMap,cipherword,candidate)
intersectedMap=intersectMappings(intersectedMap,candidateMap)
return removeSolvedLettersFromMapping(intersectedMap)
#解密
def decryptWithCipherletterMapping(ciphertext,lettermapping):
key=['x']*len(LETTERS)
for cipherletter in LETTERS:
if len(letterMapping[cipherletter])==1:
keyIndex=LETTERS.find(letterMapping[cipherletter[0])
key[keyIndex]=cipherletter
else:
ciphertext=ciphertext.replace(cipherletter.lower(),'_')
ciphertext=ciphertext.replace(cipherletter.upper(),'_')
key=''.join(key)
return simpleSubCipher.decryptMessage(key,ciphertext)
if __name__=='__main__':
main()