substitution cipher이란 치환 암호를 뜻하며, 카이사르 암호(시저 암호)처럼 단일 치환 암호이지만 대칭되는 알파벳이 무작위이기 때문에 가능한 경우의 수가 기하급수적으로 증가하여 비교적 복잡한 암호이다. 다음은 암호수학 수업시간에 교수님께서 내주신 과제의 내용이다.
APS ZU BMS THAAMT KB SOP CHAAPJ MQ LPUWHKX. K UHJ SM JMZ SMLHJ VJ QXKPBLU -- UM PCPB SOMZDO TP
QHEP SOP LKQQKEZASKPU MQ SMLHJ HBL SMVMXXMT, K USKAA OHCP H LXPHV. KS KU H LXPHV LPPWAJ XMMSPL
KB SOP HVPXKEHB LXPHV. K OHCP H LXPHV SOHS MBP LHJ SOKU BHSKMB TKAA XKUP ZW HBL AKCP MZS SOP SXZP
VPHBKBD MQ KSU EXPPL: "TP OMAL SOPUP SXZSOU SM IP UPAQ-PCKLPBS, SOHS HAA VPB HXP EXPHSPL PGZHA."
K OHCP H LXPHV SOHS MBP LHJ MB SOP XPL OKAAU MQ DPMXDKH SOP UMBU MQ QMXVPX UAHCPU HBL SOP UMBU
MQ QMXVPX UAHCP MTBPXU TKAA IP HIAP SM UKS LMTB SMDPSOPX HS SOP SHIAP MQ IXMSOPXOMML. K OHCP H
LXPHV SOHS MBP LHJ PCPB SOP USHSP MQ VKUUKUUKWWK, H USHSP UTPASPXKBD TKSO SOP OPHS MQ KBFZUSKEP,
UTPASPXKBD TKSO SOP OPHS MQ MWWXPUUKMB, TKAA IP SXHBUQMXVPL KBSM HB MHUKU MQ QXPPLMV HBL
FZUSKEP. K OHCP H LXPHV SOHS VJ QMZX AKSSAP EOKALXPB TKAA MBP LHJ AKCP KB H BHSKMB TOPXP SOPJ TKAA
BMS IP FZLDPL IJ SOP EMAMX MQ SOPKX URKB IZS IJ SOP EMBSPBS MQ SOPKX EOHXHESPX. K OHCP H LXPHV
SMLHJ. K OHCP H LXPHV SOHS MBP LHJ LMTB KB HAHIHVH, TKSO KSU CKEKMZU XHEKUSU, TKSO KSU DMCPXBMX
OHCKBD OKU AKWU LXKWWKBD TKSO SOP TMXLU MQ KBSPXWMUKSKMB HBL BZAAKQKEHSKMB -- MBP LHJ XKDOS
SOPXP KB HAHIHVH AKSSAP IAHER IMJU HBL IAHER DKXAU TKAA IP HIAP SM FMKB OHBLU TKSO AKSSAP TOKSP
IMJU HBL TOKSP DKXAU HU UKUSPXU HBL IXMSOPXU. K OHCP H LXPHV SMLHJ. K OHCP H LXPHV SOHS MBP LHJ
PCPXJ CHAAPJ UOHAA IP PNHASPL, HBL PCPXJ OKAA HBL VMZBSHKB UOHAA IP VHLP AMT, SOP XMZDO WAHEPU
TKAA IP VHLP WAHKB, HBL SOP EXMMRPL WAHEPU TKAA IP VHLP USXHKDOS, HBL SOP DAMXJ MQ SOP AMXL
UOHAA IP XPCPHAPL HBL HAA QAPUO UOHAA UPP KS SMDPSOPX.
위의 암호문을 풀어오는 과제이며 ‘substitution cipher’ 키워드가 힌트로 주어졌다. 이 문제를 자동으로 풀어서 plaintext를 출력해내는 프로그램을 만들고 싶어 pyhton으로 개발하게 되었다.
간략한 복호화 알고리즘은 아래와 같다
1. 입력 값 이어받기(개행 무시)
2. 입력 값 특수문자 제거 및 공백단위로 단어 리스트 만들기
3. 알파벳 빈도 분석 후 최다 빈도 알파벳과 ‘e’ 치환
4. 단어 빈도 분석 후 조건에 맞는 최다 빈도 단어를 ‘the’ ‘that 순으로 치환
5. 치환된 알파벳이 많은 순으로 단어를 정렬
6. 정렬된 리스트 순서대로 사전검색
7. 사전검색 결과가 1개인 경우 치환
8. 5-7을 반복
9. 치환된 글에 대문자가 없으면 루프탈출 및 출력
소스코드는 아래와 같다
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | import string import operator import requests key={} def Input(): text="" #암호문 개행 입력 제거 while True: tmp = input() if tmp == "": break else: text+=tmp+" " #암호문 특수문자 제거 for i in ["\"", ".", ",", "'", "-"]: text = text.replace(i,"") return text def BasicProcess(text): #알파벳 빈도수 정렬 table=[] for alphabet in string.ascii_uppercase: table.append([alphabet,text.count(alphabet)]) table.sort(key=lambda x:x[1], reverse=True) print("\n############### Frequency Count Table ###############") for i in range(len(table)): print("["+table[i][0]+" : "+str(table[i][1])+"]",end=" ") if (i+1)%4 == 0: print("") #최다빈도 알파벳을 'e'로 치환 text = text.replace(table[0][0],'e') key[table[0][0]] = 'e' #최다빈도 단어를 the, that순으로 치환 for word in ["the","that"]: wordList = text.split(' ') words={} for i in wordList: if len(i)==len(word) and i[-1]==word[-1]: if word=="that" and i[:2]!="th": continue if i not in words: words[i] = 1 else: words[i] +=1 if words=={}: continue words = sorted(words.items(), key=operator.itemgetter(1), reverse=True) text = Substitution(text, words[0][0], word) return text def AutoProcess(text): wordList=text.split(" ") words={} #소문자로 이루어진 완결된 단어 필터링 for i in wordList: if i in words: continue else: words[i] = 0 for j in i: if j in string.ascii_lowercase: words[i] +=1 if words[i]==len(i): del words[i] words = sorted(words.items(), key=operator.itemgetter(1), reverse=True) #정렬된 단어순으로 사전검색 possible=[] for i in words: possible = SearchWord(i[0]) if len(possible) ==1: text = Substitution(text, i[0], possible[0]) print("Found > "+possible[0]) break return text def Substitution(text, oldWord, newWord): #치환되지 않은 알파벳만 치환 for i in range(len(newWord)): if oldWord[i] in string.ascii_uppercase: text = text.replace(oldWord[i], newWord[i]) key[oldWord[i]] = newWord[i] return text def SearchWord(word): URL= "https://www.onelook.com" words=[] result="" #검색명령 폼에 맞춤 for i in range(len(word)): if word[i] in string.ascii_uppercase: word=word[:i]+'*'+word[i+1:] #사전 페이지에 요청 및 응답 params = {'w':word, "scwo":1, "sswo":1, "ssbp":1} res = requests.get(URL,params=params) if "Sorry, there are no words matching" not in res.text: for num in range(res.text.count(". <a href")): start=res.text.index(str(num+1)+". ")+15+len(str(num+1)) end=res.text[start:].index("\"") result=res.text[start:start+end] if len(result) == len(word): words.append(result) #단어 싱크로율 체크 for i in words: for j in range(len(word)): if word[j] !='*' and word[j]!=i[j]: words.remove(i) break return words print("Input Ciphertext") print("----------------") ciphertext = BasicProcess(Input()) plaintext=ciphertext #본문 내에 대문자가 없을시 프로그램 종료 print("\n############### decrypt ###############") while(True): complete=0 plaintext = AutoProcess(plaintext) for i in string.ascii_uppercase: if i in plaintext: complete=-1 if complete==0: break print("\n############### Plaintext ###############") print(plaintext) print("\n############### Key Table ###############") key = sorted(key.items(), key=operator.itemgetter(0)) for k,v in key: print("["+k+" : "+v+"]", end=" ") | cs |
실행결과는 다음과 같다
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | ========= RESTART: C:\Users\samsung\Desktop\암호수학 과제\[이재승]decrypt.py ========= Input Ciphertext ---------------- APS ZU BMS THAAMT KB SOP CHAAPJ MQ LPUWHKX. K UHJ SM JMZ SMLHJ VJ QXKPBLU -- UM PCPB SOMZDO TP QHEP SOP LKQQKEZASKPU MQ SMLHJ HBL SMVMXXMT, K USKAA OHCP H LXPHV. KS KU H LXPHV LPPWAJ XMMSPL KB SOP HVPXKEHB LXPHV. K OHCP H LXPHV SOHS MBP LHJ SOKU BHSKMB TKAA XKUP ZW HBL AKCP MZS SOP SXZP VPHBKBD MQ KSU EXPPL: "TP OMAL SOPUP SXZSOU SM IP UPAQ-PCKLPBS, SOHS HAA VPB HXP EXPHSPL PGZHA." K OHCP H LXPHV SOHS MBP LHJ MB SOP XPL OKAAU MQ DPMXDKH SOP UMBU MQ QMXVPX UAHCPU HBL SOP UMBU MQ QMXVPX UAHCP MTBPXU TKAA IP HIAP SM UKS LMTB SMDPSOPX HS SOP SHIAP MQ IXMSOPXOMML. K OHCP H LXPHV SOHS MBP LHJ PCPB SOP USHSP MQ VKUUKUUKWWK, H USHSP UTPASPXKBD TKSO SOP OPHS MQ KBFZUSKEP, UTPASPXKBD TKSO SOP OPHS MQ MWWXPUUKMB, TKAA IP SXHBUQMXVPL KBSM HB MHUKU MQ QXPPLMV HBL FZUSKEP. K OHCP H LXPHV SOHS VJ QMZX AKSSAP EOKALXPB TKAA MBP LHJ AKCP KB H BHSKMB TOPXP SOPJ TKAA BMS IP FZLDPL IJ SOP EMAMX MQ SOPKX URKB IZS IJ SOP EMBSPBS MQ SOPKX EOHXHESPX. K OHCP H LXPHV SMLHJ. K OHCP H LXPHV SOHS MBP LHJ LMTB KB HAHIHVH, TKSO KSU CKEKMZU XHEKUSU, TKSO KSU DMCPXBMX OHCKBD OKU AKWU LXKWWKBD TKSO SOP TMXLU MQ KBSPXWMUKSKMB HBL BZAAKQKEHSKMB -- MBP LHJ XKDOS SOPXP KB HAHIHVH AKSSAP IAHER IMJU HBL IAHER DKXAU TKAA IP HIAP SM FMKB OHBLU TKSO AKSSAP TOKSP IMJU HBL TOKSP DKXAU HU UKUSPXU HBL IXMSOPXU. K OHCP H LXPHV SMLHJ. K OHCP H LXPHV SOHS MBP LHJ PCPXJ CHAAPJ UOHAA IP PNHASPL, HBL PCPXJ OKAA HBL VMZBSHKB UOHAA IP VHLP AMT, SOP XMZDO WAHEPU TKAA IP VHLP WAHKB, HBL SOP EXMMRPL WAHEPU TKAA IP VHLP USXHKDOS, HBL SOP DAMXJ MQ SOP AMXL UOHAA IP XPCPHAPL HBL HAA QAPUO UOHAA UPP KS SMDPSOPX. ############### Frequency Count Table ############### [P : 156] [H : 124] [S : 116] [K : 97] [M : 87] [A : 81] [O : 75] [X : 69] [B : 68] [U : 68] [L : 63] [T : 29] [V : 28] [Q : 27] [J : 26] [C : 24] [I : 24] [E : 20] [D : 18] [Z : 18] [W : 14] [F : 4] [R : 4] [G : 1] [N : 1] [Y : 0] ############### decrypt ############### Found > together Found > brotherhood Found > brothers Found > character Found > interposition Found > mississippi Found > transformed Found > difficulties Found > injustice Found > tomorrow Found > governor Found > exalted Found > valley Found > black Found > equal ############### Plaintext ############### let us not wallow in the valley of despair i say to you today my friends so even though we face the difficulties of today and tomorrow i still have a dream it is a dream deeply rooted in the american dream i have a dream that one day this nation will rise up and live out the true meaning of its creed: we hold these truths to be selfevident that all men are created equal i have a dream that one day on the red hills of georgia the sons of former slaves and the sons of former slave owners will be able to sit down together at the table of brotherhood i have a dream that one day even the state of mississippi a state sweltering with the heat of injustice sweltering with the heat of oppression will be transformed into an oasis of freedom and justice i have a dream that my four little children will one day live in a nation where they will not be judged by the color of their skin but by the content of their character i have a dream today i have a dream that one day down in alabama with its vicious racists with its governor having his lips dripping with the words of interposition and nullification one day right there in alabama little black boys and black girls will be able to join hands with little white boys and white girls as sisters and brothers i have a dream today i have a dream that one day every valley shall be exalted and every hill and mountain shall be made low the rough places will be made plain and the crooked places will be made straight and the glory of the lord shall be revealed and all flesh shall see it together ############### Key Table ############### [A : l] [B : n] [C : v] [D : g] [E : c] [F : j] [G : q] [H : a] [I : b] [J : y] [K : i] [L : d] [M : o] [N : x] [O : h] [P : e] [Q : f] [R : k] [S : t] [T : w] [U : s] [V : m] [W : p] [X : r] [Z : u] | cs |
'Programing > Python' 카테고리의 다른 글
Python :: SyntaxError:EOL while scanning string literal (2) | 2018.04.27 |
---|---|
Python :: 유클리드 알고리즘 #GCD(최대공약수) 구하기 (0) | 2018.04.01 |
Python :: 리스트(list)와 딕셔너리(dictionary) - 연습문제 (0) | 2017.06.12 |
Python :: 리스트(list)와 딕셔너리(dictionary) - 내용 (0) | 2017.06.12 |
Python :: 함수 - 연습문제 (0) | 2017.06.12 |