Skip to content

Instantly share code, notes, and snippets.

@hyperreality
Last active December 27, 2018 04:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyperreality/32cfaf45fc2731c4f8307c68f3497b6b to your computer and use it in GitHub Desktop.
Save hyperreality/32cfaf45fc2731c4f8307c68f3497b6b to your computer and use it in GitHub Desktop.
#!/usr/bin/python3
from collections import Counter
import operator
import string
def ic(ctext):
num = 0.0
den = 0.0
for val in Counter(ctext).values():
i = val
num += i * (i - 1)
den += i
if den == 0.0:
return 0.0
else:
return num / (den * (den - 1))
def partition(text, num):
cols = [""] * num
for i, c in enumerate(text):
cols[i % num] += c
return cols
def find_keylen_ics(ctext, low=3, high=10, rows=5):
if high > len(ctext) / 2:
high = len(ctext) / 2
results = {}
for length in range(low, high + 1):
ics = [ic(col) for col in partition(ctext, length)]
results[length] = sum(ics) / len(ics)
best = sorted(results.items(), key=lambda kv: -kv[1])
print("%8s %8s" % ("keylen", "ic"))
for k, v in best[:rows]:
print("%8d %8.3f" % (k, v))
return best
def freq_score(text):
freqs = {
'a': 8167,
'b': 1492,
'c': 2782,
'd': 4253,
'e': 12702,
'f': 2228,
'g': 2015,
'h': 6094,
'i': 6966,
'j': 153,
'k': 772,
'l': 4025,
'm': 2406,
'n': 6749,
'o': 7507,
'p': 1929,
'q': 95,
'r': 5987,
's': 6327,
't': 9056,
'u': 2758,
'v': 978,
'w': 2360,
'x': 150,
'y': 1974,
'z': 74
}
score = 0
for c in text:
if c == ' ':
score += 10000
elif c.lower() in freqs:
score += freqs[c.lower()]
elif ord(c) >= 128:
score -= 5000
else:
score -= 1000
return score
def find_key(ctext, keylen, alph=string.ascii_lowercase):
key = ""
for col in partition(ctext, keylen):
scores = {}
for i, letter in enumerate(alph):
transposed = [alph[(alph.index(c.lower()) - i) % len(alph)] for c in col if c != " "]
scores[letter] = freq_score(transposed)
key += max(scores.items(), key=operator.itemgetter(1))[0]
return key
def decrypt(ctext, key, alph=string.ascii_lowercase):
return ''.join(alph[(alph.index(c.lower()) - alph.index(key[i % len(key)])) % len(alph)] for i, c in enumerate(ctext) if c != " ")
if __name__ == "__main__":
ciphertext = """NSWOG EONOB IJBIVQ W IWXP YOYP GGI BL EKGLI TAMD XKSU XSOGAM BUK TDE ZMEEGXDJM OHEG WZHWM CVZ KASE ZVP OHVTQ HSDL XPRE LUW WUNXHPU MLIA SGHJRSVR WGH TPENEG ZGGHMEKR ZZTX FKDLUSMIA SS IJHQ GNCDH ZYGF KSDL QIXKG DUMYIY GXDJM XRUDWH LQIEZ T YNIAF WEV T YHKGELGG WS GPPSGXQPY LW MLQF DZLFM BUK LQKPIZ JCPVFM MKOGE TXGIHYS WZX YHKGELGG LBKGYW FESR GPQKX QAZSWOAZIVPK TV CYAG O KMFEV ICYVLKYKG OYG TPT GBO LASAR DPRHEI VT TDEOIZLYALUL NCFZ YHWW BB UPW EEQQ CC YXX N UTUDYVQRTR WG QMYRCH VHAV ZVPLJ MTYAGTRFL WS UCDFWICE UCDFMIL O ORFM PNBS D ZMZYLFTHFW UNEPP KHSV HIE AEPCFOCYV HJ TXOYGWNV QU T ZTZM ZVLW B BRTR WG AWEXM WGH UHIV DK CWH QLQ MITY W WWGH GU EKAGO GNOE A EU G MDV TMEYCY LAEB O LP VEXNHZP GY LBOBR WOMT GFP LASAR HSRMZLBF XFVL MVGXIDLNX QEXOELGGET UF ZJHRO UF LK XPNZ L KBKV ZVLW B PNBS D LXZBTU PGKET ICXSSLW OE EKW AIL WQ QHY NXS UWTHQAM EKAL GBA AUGUEJYE HRFM ARK LQQ TCAIHFDLBSVF RZQL EAFAAP AF KEGNJ TXGIHYS RX XPNZ TP TGBHGZWB PVQGOBR AM EVZV SMGGBHGHTRFL IAJ DWJBT GNSX TXGIHYS PQ IVPXMAWAHR NRUZUAMLU OG KWEPI JIXE MLIG WE OBPT LINN NT CABNWMTXQBTG DFW Q GA WGH TNFM WG JQK HSDL M JUBOHJ MN VSZSDX EBAZO UTVM KBZXYA IOUIE EX BB RPFJRTB ZVPVW QMFYORHK AQYR T TX QZVCCWSGX RTCFJZ JWE GZPWHRM ZC GWOSBR OY ZHYZ UF WOH BB UPW MS EKOO LAMA O ORFM SAUK ZAEP NTMZQW GWZK ER FC SABPUSE WE GEDFW WIKF PQ HMNZVMHV M JOZW FXZME YYRO EVQ HSLK MA MSEWAGK GUC HVZC UGVL GDEG LCC KHQM XSLO IVWORSXV B URZ EKAL OVXZ RFEMVR OYG B LBTH NFHA VS DWSKXQAM ER ZMDR IA GG BUK TGWT WS ZZYW YVGOZ ZW HQR WEV CYAG BZW LYAGGWYDTEI VT XB HTQAOCY ETCJR WX EBWAVTU VGFIBUOBR MLYIYRM WZTXA ZVP UTWM O XLKL BUOBRV B JRICXH LLWEZ DLYAXMQ CC A XMAJ ER YSKHY ERG QCPN ZQ HRM ZVTQY WPVZ T KTC GNOE S PWG W GGGX XTCH AL BUKFP SGCBUOBR LKYM ZVLW B KNT DDQ FMFORPV B LBTH NFHA V RZQL OVBC EKSMW ZE XRLMS V VZSW CWH VLYW E TUCO VTC SXWPQV HWAZ OR WVCTY LQV OMRV JRMKWMYL SHSEXPL"""
keylen = find_keylen_ics(ciphertext)
key = find_key(ciphertext, keylen[0][0])
print(key)
print(decrypt(ciphertext, key))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment