Cracking a monoalphabetic substitution cipher
Command line:
msc1 ciphertextfile dictionary [screenwidth]
screenwidth defaults to 80. Linux console users will
(a) wish to override this and
(b) ask why I didn't use SIGWINCH! (Answer: not portable)
ciphertextfile contains a monoalphabetic substitution cipher
dictionary contains words (Latin alphabet only - i.e. a through z),
one per line. Linux users: /usr/dict/words or /usr/shared/dict/words
will be fine. DOS/Windows users: er, make up your own dictionary, or
get hold of a /usr/dict/words !
Here's a sample run, where the ciphertext has no spaces to separate
words. Note that the ciphertext was prepared by my children, which
explains not just its content but also the typo.
msc1 cipher c:\usr\dict\words
(some startup stuff appears here)
> cipher
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
> freq
Ch Count %age Ch Count %age
b 35 16.667 t 5 2.381
a 26 12.381 l 5 2.381
e 17 8.095 g 5 2.381
v 16 7.619 u 4 1.905
r 15 7.143 i 4 1.905
k 13 6.190 p 3 1.429
w 12 5.714 d 1 0.476
q 9 4.286 x 1 0.476
f 9 4.286 s 1 0.476
c 9 4.286 h 0 0.000
z 9 4.286 o 0 0.000
m 6 2.857 j 0 0.000
y 5 2.381 n 0 0.000
> map b e
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
___________E_______E__________E________
__E___E___E___EEE_____E____E_____E____E
________E_EE______E______________E_____
___EE____E___E___E___E__________E______
_E_E_E__EE_____________E____E_______E__
____________E_E
> map a r
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
___________ER__R___E__________ER_______
_RE___E___E__REEE____RER__RE_R___E____E
R_R_____E_EE______ER__R__________E_____
__REE____E___ER__E___E________R_ER____R
RE_ERE__EE_R___________E_R__E_R_____E_R
________R___ERE
> map c h
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
_H_____H___ER__R___E__________ER_______
_RE___E___E_HREEE____RER__RE_R___E____E
R_R_____E_EE__H___ER__R__________E_____
_HREE____E___ER_HE___E________R_ER____R
RE_ERE__EE_R__________HE_R_HE_R_____E_R
________R__HERE
> both 40 80
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
_RE___E___E_HREEE____RER__RE_R___E____E
> map v t
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
TH____TH___ER__R___E_________TER__T____
_RE___E___ETHREEE____RER__RETR___E____E
R_R_____E_EE_TH___ER__R_T__T_____E_T___
THREE____E___ERTHE___ET_T_____R_ER____R
RE_ERE__EE_R__________HE_RTHE_RT____E_R
________R__HERE
> both 0 10
vckmkmvcfr
TH____TH__
> guess km is
> both 0 10
vckmkmvcfr
THISISTH__
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTH___ER_IR___E____I__I_TER__TI___
_RES__E__SETHREEE____RERS_RETR___E____E
R_R_____E_EE_TH___ER_IR_T__T_____E_T___
THREE____E_I_ERTHE___ET_T_____R_ER____R
RE_ERE__EE_RI______I__HE_RTHEIRT___IESR
____I___R__HERE
> both 25 35
rikrvbarqv
__I_TER__T
> map r n
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTH_N_ER_IR__NE____IN_INTERN_TI_N_
_RES__E__SETHREEE____RERS_RETR___E__N_E
R_R__N__ENEE_TH_N_ER_IR_T__T_____E_T___
THREE_N__E_I_ERTHE___ET_T_____R_ER____R
RE_EREN_EE_RIN_____I_NHE_RTHEIRT___IESR
____IN__R__HERE
> both 25 41
rikrvbarqvkerq
N_INTERN_TI_N_
> map q a
> map o e
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTH_N__R_IR__N__A__IN_INT_RNATI_NA
_R_S____AS_THR_______R_RSAR_TRA_____N__
R_R__N___N___TH_N__R_IR_T__T_______T___
THR__AN____I__RTH_____T_T_____R__R____R
R___R_N____RIN_____IANH_ARTH_IRT___I_SR
____IN__R__H_R_
> map b e
> map e o
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTH_N_ER_IR_ONE_A__IN_INTERNATIONA
_RES__E_ASETHREEE___ORERSARETRA__E__N_E
R_RO_N__ENEE_TH_N_ER_IR_T_OTO_O__E_T_O_
THREEAN__E_I_ERTHE_O_ETOT_O_O_R_ERO_O_R
RE_EREN_EE_RIN__OO_IANHEARTHEIRT___IESR
____IN__RO_HERE
> map z l
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTH_N_ER_IR_ONE_ALLIN_INTERNATIONA
LRES__E_ASETHREEE__LORERSARETRA__E__N_E
R_RO_N__ENEE_TH_N_ER_IR_T_OTO_OLLE_T_O_
THREEAN__ELI_ERTHE_OLETOT_O_O_R_ERO_O_R
RE_EREN_EE_RIN__OO_IANHEARTHEIRT___IESR
___LIN__RO_HERE
> both 80 120
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvue
R_RO_N__ENEE_TH_N_ER_IR_T_OTO_OLLE_T_O
> map y c
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTH_N_ER_IR_ONECALLIN_INTERNATIONA
LRESC_E_ASETHREEE__LORERSARETRA__E__N_E
R_RO_N__ENEE_TH_N_ER_IR_T_OTOCOLLECT_O_
THREEAN__ELI_ERTHE_OLETOT_O_O_R_ERO_O_R
RE_ERENCEE_RIN__OO_IANHEARTHEIRT___IESR
___LIN__RO_HERE
> map i g
> map d x
> map u p
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTH_N_ER_IR_ONECALLINGINTERNATIONA
LRESC_E_ASETHREEEXPLORERSARETRAPPE__N_E
RGRO_N__ENEE_TH_N_ER_IR_T_OTOCOLLECTPO_
THREEAN__ELI_ERTHE_OLETOT_O_O_R_ERO_O_R
RE_ERENCEE_RING_OO_IANHEARTHEIRT___IESR
___LING_RO_HERE
> both 68 110
bvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpev
ETRAPPE__N_E
RGRO_N__ENEE_TH_N_ER_IR_T_OT
> map w d
> map f u
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTHUNDER_IRDONECALLINGINTERNATIONA
LRESCUE_ASETHREEEXPLORERSARETRAPPEDUNDE
RGROUND_ENEEDTHUNDER_IRDT_OTOCOLLECTPOD
THREEANDDELI_ERTHE_OLETOT_O_OUR_ERO_OUR
RE_ERENCEE_RING_OODIANHEARTHEIRTU__IESR
U__LING_RO_HERE
> map g b
> map p w
> both
vckmkmvcfrwbagkawerbyqzzkrikrvbarqvkerq
zabmyfbgqmbvcabbbduzeabamqabvaquubwfrwb
aiaefrwpbrbbwvcfrwbagkawvpeveyezzbyvuew
vcabbqrwwbzksbavcbtezbvevpelefaxbaelefa
ablbabrybbgakrileewkqrcbqavcbkavfttkbma
ftgzkrilaetcbab
THISISTHUNDERBIRDONECALLINGINTERNATIONA
LRESCUEBASETHREEEXPLORERSARETRAPPEDUNDE
RGROUNDWENEEDTHUNDERBIRDTWOTOCOLLECTPOD
THREEANDDELI_ERTHE_OLETOTWO_OUR_ERO_OUR
RE_ERENCEEBRING_OODIANHEARTHEIRTU__IESR
U_BLING_RO_HERE
Well, you get the idea. Once this is finished off, we can
>save plaintext.txt
which will save the plaintext to a file.
Now, what if there were spaces in the ciphertext? This makes our
life a LOT easier.
> both
vckm km vcfrwbagkaw erb yqzzkri krvbarqvkerqz
abmyfb gqmb vcabb bduzeabam qab vaquubw frwbaiaefrw
pb rbbw vcfrwbagkaw vpe ve yezzbyv uew
vcabb qrw wbzksba vcb tezb ve vpe lefa xbae lefa
ablbabryb b gakri leew k qr cbqa vcbka vfttkbm
aftgzkri laet cbab
____ __ ___________ ___ _______ _____________
______ ____ _____ _________ ___ _______ ___________
__ ____ ___________ ___ __ _______ ___
_____ ___ _______ ___ ____ __ ___ ____ ____ ____
_________ _ _____ ____ _ __ ____ _____ _______
________ ____ ____
First, we try out "vcfrwbagkaw":
> match vcfrwbagkaw
counterpart monasteries
2 words matched.
Well, we could carry on with either of those, but let's not,
at least for now. How about the other long word on the first
line?
> match krvbarqvkerqz
international
1 word matched.
Ah, that's more promising... let's plug that entire word in, and see
what we get.
> guess krvbarqvkerqz international
> both
vckm km vcfrwbagkaw erb yqzzkri krvbarqvkerqz
abmyfb gqmb vcabb bduzeabam qab vaquubw frwbaiaefrw
pb rbbw vcfrwbagkaw vpe ve yezzbyv uew
vcabb qrw wbzksba vcb tezb ve vpe lefa xbae lefa
ablbabryb b gakri leew k qr cbqa vcbka vfttkbm
aftgzkri laet cbab
T_I_ I_ T__N_ER_IR_ ONE _ALLIN_ INTERNATIONAL
RE___E _A_E T_REE E__LORER_ ARE TRA__E_ _N_ER_RO_N_
_E NEE_ T__N_ER_IR_ T_O TO _OLLE_T _O_
T_REE AN_ _ELI_ER T_E _OLE TO T_O _O_R _ERO _O_R
RE_EREN_E E _RIN_ _OO_ I AN _EAR T_EIR T___IE_
R___LIN_ _RO_ _ERE
Well, the second word doesn't look like either "counterpart" or
"monasteries" so we have to conclude that it's a word not in our
dictionary. Oh well... let's try that E__LORER_ word...
> lookup e??lorer?
explorers
1 word found.
> guess bduzeabam explorers
> both
vckm km vcfrwbagkaw erb yqzzkri krvbarqvkerqz
abmyfb gqmb vcabb bduzeabam qab vaquubw frwbaiaefrw
pb rbbw vcfrwbagkaw vpe ve yezzbyv uew
vcabb qrw wbzksba vcb tezb ve vpe lefa xbae lefa
ablbabryb b gakri leew k qr cbqa vcbka vfttkbm
aftgzkri laet cbab
T_IS IS T__N_ER_IR_ ONE _ALLIN_ INTERNATIONAL
RES__E _ASE T_REE EXPLORERS ARE TRAPPE_ _N_ER_RO_N_
_E NEE_ T__N_ER_IR_ T_O TO _OLLE_T PO_
T_REE AN_ _ELI_ER T_E _OLE TO T_O _O_R _ERO _O_R
RE_EREN_E E _RIN_ _OO_ I AN _EAR T_EIR T___IES
R___LIN_ _RO_ _ERE
As you can see, progress is much quicker this time, because we were
able to get a whole bunch of matches in one single word.
You are visitor number
- call again soon!