编码与密码

一、编码的方式是可以公开获得并理解的。

电报只能发送两种类型的电脉冲:称为“点”的短脉冲和称为线的长脉冲。

通过编码系统,将英语转换成电报发送的点和线的过程称为编码,反之则为解码。电报(和后来的无线电)对消息进行编码和解码的方式称为摩尔斯电码

二、凯撒密码:移位替换法进行加密,例如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的乘法逆元。

  1. a%b = a - (a/b)*b​​​​​​​
  2.  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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值