Substitution_Cipher_Demo

3802 days ago by alex

 
       
# Tools for substitution cyphers. AS = AlphabeticStrings() SC = SubstitutionCryptosystem(AS) 
       
# Some utility functions to count digrams and trigrams, # and to partially decode a ciphertext based on presumed # "known" parts of the key. 
       
def digram_count(ctext): """Make dict of digrams in an alphabetic string monoid element""" ctstr = str(ctext) digrams = {} for i in range(len(ctstr)): digram = ctstr[i:i+2] if digram in digrams: count = digrams[digram] digrams[digram] = count + 1 else: digrams[digram] = 1 return(digrams) 
       
def trigram_count(ctext): """Make dict of trigrams in an alphabetic string monoid element""" ctstr = str(ctext) trigrams = {} for i in range(len(ctstr)-1): trigram = ctstr[i:i+3] if trigram in trigrams: count = trigrams[trigram] trigrams[trigram] = count + 1 else: trigrams[trigram] = 1 return(trigrams) 
       
def partial_decode(ctxt, known): """Partially decode ciphertext using dict of knowns""" l = len(ctxt) pd = '-' * l for i in range(l): if ctxt[i] in known: pd = pd[:i] + known[ctxt[i]] + pd[(i+1):] return(pd) 
       
# Passage quoted from "Engineering and the Mind's Eye" # by Eugene Ferguson, MIT Press, 1994. # Encrypted by a Substitution Cipher. ctstr = 'NMJWNTJFPNMUQJFPOFJJTOFPYOJWOFNMJCJRNMUQONWQUXFCGNOUFWN\ MJMXFCTJCPJFJTGNOUFWUQHUFWHOJFNOUXWGTNOWGFWEMUAXOYNNMUW\ JQUXFCGNOUFWRTJWJTLJCNMJNJHMFOHGYSFUEYJCPJNMJZMGCYJGTFJ\ CQTUVNMJOTQUTJAJGTWTJQOFJCONGCCJCNUONGFCRGWWJCONUFNURUW\ NJTONZGYNMUXPMEJRGZGNNJFNOUFHMOJQYZNUFJEGFCWMUEZNJHMFOH\ GYVGTLJYWGNYJGWNJOPMNZRJTHJFNUQJFPOFJJTWEUTSEONMNJHMFUY\ UPOJWNMGNMGLJAJJFGTUXFCQUTCJHGCJWUTJLJFHJFNXTOJW' # ct = AS.encoding(ctstr) 
       
cc = ct.character_count(); cc 
       
{A: 3, C: 19, E: 7, G: 24, F: 34, H: 11, J: 56, M: 23, L: 4, O: 27, N:
40, Q: 11, P: 9, S: 2, R: 6, U: 30, T: 22, W: 23, V: 2, Y: 11, X: 8, Z:
6}
{A: 3, C: 19, E: 7, G: 24, F: 34, H: 11, J: 56, M: 23, L: 4, O: 27, N: 40, Q: 11, P: 9, S: 2, R: 6, U: 30, T: 22, W: 23, V: 2, Y: 11, X: 8, Z: 6}
for l in sorted(cc, key=cc.get, reverse=True): print l, cc[l] 
       
J 56
N 40
F 34
U 30
O 27
G 24
M 23
W 23
T 22
C 19
H 11
Q 11
Y 11
P 9
X 8
E 7
R 6
Z 6
L 4
A 3
S 2
V 2
J 56
N 40
F 34
U 30
O 27
G 24
M 23
W 23
T 22
C 19
H 11
Q 11
Y 11
P 9
X 8
E 7
R 6
Z 6
L 4
A 3
S 2
V 2
digrams = digram_count(ct) 
       
for i in range(6,14): if i in digrams.values(): print "Digrams occurring", i, "times" for k in digrams.keys(): if digrams[k] == i: print k 
       
Digrams occurring 6 times
JW
JT
GN
ON
MJ
MU
FC
FJ
FN
NJ
NO
TJ
Digrams occurring 7 times
UF
Digrams occurring 8 times
JC
Digrams occurring 10 times
JF
Digrams occurring 13 times
NM
Digrams occurring 6 times
JW
JT
GN
ON
MJ
MU
FC
FJ
FN
NJ
NO
TJ
Digrams occurring 7 times
UF
Digrams occurring 8 times
JC
Digrams occurring 10 times
JF
Digrams occurring 13 times
NM
trigrams = trigram_count(ct) 
       
for i in range(3,7): print "Trigrams occurring", i, "times" for k in trigrams.keys(): if trigrams[k] == i: print k 
       
Trigrams occurring 3 times
JFP
UXF
OFJ
OJW
HMF
NJH
JHM
GNO
Trigrams occurring 4 times
JFN
XFC
OUF
NMU
UFW
Trigrams occurring 5 times
NOU
Trigrams occurring 6 times
NMJ
Trigrams occurring 3 times
JFP
UXF
OFJ
OJW
HMF
NJH
JHM
GNO
Trigrams occurring 4 times
JFN
XFC
OUF
NMU
UFW
Trigrams occurring 5 times
NOU
Trigrams occurring 6 times
NMJ
knowns = {"F" : "N", "J" : "E", "M" : "H", "N" : "T", "U" : "A"} 
       
partial_decode(ctstr, knowns) 
       
'THE-T-EN-THA-EN--NEE--N---E--NTHE-E-THA--T--A-N--T-AN-THEH-N--E--ENE--T\
-AN-A--AN---ENT-A----T---N--HA----TTHA-E-A-N--T-AN---E-E--E-THETE-HN----\
-NA--E--ETHE-H---E--NE---A-THE---A-E-E----E--NE--T---E-TA-T-N-----E--TAN\
TA-A-TE--T---THA--H-E----TTENT-AN-H-E---TANE--N--HA--TE-HN--------E---T-\
E--TE--HT--E--ENTA-EN--NEE---A----THTE-HNA-A--E-TH-TH--E-EEN--A-N--A--E-\
--E-A-E-EN-ENT---E-'
'THE-T-EN-THA-EN--NEE--N---E--NTHE-E-THA--T--A-N--T-AN-THEH-N--E--ENE--T-AN-A--AN---ENT-A----T---N--HA----TTHA-E-A-N--T-AN---E-E--E-THETE-HN-----NA--E--ETHE-H---E--NE---A-THE---A-E-E----E--NE--T---E-TA-T-N-----E--TANTA-A-TE--T---THA--H-E----TTENT-AN-H-E---TANE--N--HA--TE-HN--------E---T-E--TE--HT--E--ENTA-EN--NEE---A----THTE-HNA-A--E-TH-TH--E-EEN--A-N--A--E---E-A-E-EN-ENT---E-'
# Add P -> g, O -> i and T -> r knowns = {"F" : "N", "J" : "E", "M" : "H", "N" : "T", "O" : "I", "P" : "G", "T" : "R", "U" : "A"} 
       
partial_decode(ctstr, knowns) 
       
'THE-TRENGTHA-ENGINEERING-IE-INTHE-E-THA-IT--A-N--TIAN-THEH-N-RE-GENER-T\
IAN-A--AN--IENTIA---RTI--N--HA--I-TTHA-E-A-N--TIAN--RE-ER-E-THETE-HNI---\
-NA--E-GETHE-H---E-RNE--RA-THEIR-ARE-E-R-RE-INE-IT---E-TAIT-N-----E-ITAN\
TA-A-TERIT---THA-GH-E----TTENTIAN-HIE---TANE--N--HA--TE-HNI-----R-E---T-\
E--TEIGHT--ER-ENTA-ENGINEER--AR--ITHTE-HNA-AGIE-TH-TH--E-EEN-RA-N--AR-E-\
--E-ARE-EN-ENT-RIE-'
'THE-TRENGTHA-ENGINEERING-IE-INTHE-E-THA-IT--A-N--TIAN-THEH-N-RE-GENER-TIAN-A--AN--IENTIA---RTI--N--HA--I-TTHA-E-A-N--TIAN--RE-ER-E-THETE-HNI----NA--E-GETHE-H---E-RNE--RA-THEIR-ARE-E-R-RE-INE-IT---E-TAIT-N-----E-ITANTA-A-TERIT---THA-GH-E----TTENTIAN-HIE---TANE--N--HA--TE-HNI-----R-E---T-E--TEIGHT--ER-ENTA-ENGINEER--AR--ITHTE-HNA-AGIE-TH-TH--E-EEN-RA-N--AR-E---E-ARE-EN-ENT-RIE-'
# Change U -> o, add W -> s and G -> a knowns = {"F" : "N", "G" : "A", "J" : "E", "M" : "H", "N" : "T", "O" : "I", "P" : "G", "T" : "R", "U" : "O", "W" : "S"} 
       
partial_decode(ctstr, knowns) 
       
'THESTRENGTHO-ENGINEERING-IESINTHE-E-THO-ITS-O-N-ATIONSTHEH-N-RE-GENERAT\
IONSO--ONS-IENTIO-SARTISANS-HO--I-TTHOSE-O-N-ATIONS-RESER-E-THETE-HNI-A-\
-NO--E-GETHE-HA--EARNE--RO-THEIR-ORE-EARSRE-INE-ITA--E-TOITAN--ASSE-ITON\
TO-OSTERIT-A-THO-GH-E-A-ATTENTION-HIE---TONE-AN-SHO--TE-HNI-A--AR-E-SAT-\
EASTEIGHT--ER-ENTO-ENGINEERS-OR--ITHTE-HNO-OGIESTHATHA-E-EENARO-N--OR-E-\
A-ESORE-EN-ENT-RIES'
'THESTRENGTHO-ENGINEERING-IESINTHE-E-THO-ITS-O-N-ATIONSTHEH-N-RE-GENERATIONSO--ONS-IENTIO-SARTISANS-HO--I-TTHOSE-O-N-ATIONS-RESER-E-THETE-HNI-A--NO--E-GETHE-HA--EARNE--RO-THEIR-ORE-EARSRE-INE-ITA--E-TOITAN--ASSE-ITONTO-OSTERIT-A-THO-GH-E-A-ATTENTION-HIE---TONE-AN-SHO--TE-HNI-A--AR-E-SAT-EASTEIGHT--ER-ENTO-ENGINEERS-OR--ITHTE-HNO-OGIESTHATHA-E-EENARO-N--OR-E-A-ESORE-EN-ENT-RIES'
# Replace U -> a with U -> o. # Add W -> s and G -> a. knowns = {"F" : "N", "G" : "A", "J" : "E", "M" : "H", "N" : "T", "O" : "I", "P" : "G", "T" : "R", "U" : "O", "W" : "S"} 
       
partial_decode(ctstr, knowns) 
       
'THESTRENGTHO-ENGINEERING-IESINTHE-E-THO-ITS-O-N-ATIONSTHEH-N-RE-GENERAT\
IONSO--ONS-IENTIO-SARTISANS-HO--I-TTHOSE-O-N-ATIONS-RESER-E-THETE-HNI-A-\
-NO--E-GETHE-HA--EARNE--RO-THEIR-ORE-EARSRE-INE-ITA--E-TOITAN--ASSE-ITON\
TO-OSTERIT-A-THO-GH-E-A-ATTENTION-HIE---TONE-AN-SHO--TE-HNI-A--AR-E-SAT-\
EASTEIGHT--ER-ENTO-ENGINEERS-OR--ITHTE-HNO-OGIESTHATHA-E-EENARO-N--OR-E-\
A-ESORE-EN-ENT-RIES'
'THESTRENGTHO-ENGINEERING-IESINTHE-E-THO-ITS-O-N-ATIONSTHEH-N-RE-GENERATIONSO--ONS-IENTIO-SARTISANS-HO--I-TTHOSE-O-N-ATIONS-RESER-E-THETE-HNI-A--NO--E-GETHE-HA--EARNE--RO-THEIR-ORE-EARSRE-INE-ITA--E-TOITAN--ASSE-ITONTO-OSTERIT-A-THO-GH-E-A-ATTENTION-HIE---TONE-AN-SHO--TE-HNI-A--AR-E-SAT-EASTEIGHT--ER-ENTO-ENGINEERS-OR--ITHTE-HNO-OGIESTHATHA-E-EENARO-N--OR-E-A-ESORE-EN-ENT-RIES'
# Add Q -> f, X -> u and C -> d. knowns = {"C" : "D", "F" : "N", "G" : "A", "J" : "E", "M" : "H", "N" : "T", "O" : "I", "P" : "G", "Q" : "F", "T" : "R", "U" : "O", "W" : "S", "X" : "U"} 
       
partial_decode(ctstr, knowns) 
       
'THESTRENGTHOFENGINEERING-IESINTHEDE-THOFITSFOUNDATIONSTHEHUNDREDGENERAT\
IONSOF-ONS-IENTIOUSARTISANS-HO-UI-TTHOSEFOUNDATIONS-RESER-EDTHETE-HNI-A-\
-NO--EDGETHE-HAD-EARNEDFRO-THEIRFORE-EARSREFINEDITADDEDTOITAND-ASSEDITON\
TO-OSTERIT-A-THOUGH-E-A-ATTENTION-HIEF--TONE-ANDSHO--TE-HNI-A--AR-E-SAT-\
EASTEIGHT--ER-ENTOFENGINEERS-OR--ITHTE-HNO-OGIESTHATHA-E-EENAROUNDFORDE-\
ADESORE-EN-ENTURIES'
'THESTRENGTHOFENGINEERING-IESINTHEDE-THOFITSFOUNDATIONSTHEHUNDREDGENERATIONSOF-ONS-IENTIOUSARTISANS-HO-UI-TTHOSEFOUNDATIONS-RESER-EDTHETE-HNI-A--NO--EDGETHE-HAD-EARNEDFRO-THEIRFORE-EARSREFINEDITADDEDTOITAND-ASSEDITONTO-OSTERIT-A-THOUGH-E-A-ATTENTION-HIEF--TONE-ANDSHO--TE-HNI-A--AR-E-SAT-EASTEIGHT--ER-ENTOFENGINEERS-OR--ITHTE-HNO-OGIESTHATHA-E-EENAROUNDFORDE-ADESORE-EN-ENTURIES'
 
       
 
       
 
       
 
       
 
       
 
       
plaintext = "The strength of engineering lies in the depth of its " +\ "foundations. The hundred generations of conscientious artisans " +\ "who built those foundations preserved the technical knowledge " +\ "they had learned from their forebears, refined it, added to it, " +\ "and passed it on to posterity. Although we pay attention chiefly " +\ "to new and showy technical marvels, at least eighty percent of " +\ "engineers work with technologies that have been around for " +\ "decades or even centuries." 
       
# The Key K = AS.encoding("GAHCJQPMOBSYVFURDTWNXLEIZK") 
       
# Engineering and the Mind's Eye quote # Key: GAHCJQPMOBSYVFURDTWNXLEIZK # ctstr = 'NMJWNTJFPNMUQJFPOFJJTOFPYOJWOFNMJCJRNMUQONWQUXFCGNOUFWN\ MJMXFCTJCPJFJTGNOUFWUQHUFWHOJFNOUXWGTNOWGFWEMUAXOYNNMUW\ JQUXFCGNOUFWRTJWJTLJCNMJNJHMFOHGYSFUEYJCPJNMJZMGCYJGTFJ\ CQTUVNMJOTQUTJAJGTWTJQOFJCONGCCJCNUONGFCRGWWJCONUFNURUW\ NJTONZGYNMUXPMEJRGZGNNJFNOUFHMOJQYZNUFJEGFCWMUEZNJHMFOH\ GYVGTLJYWGNYJGWNJOPMNZRJTHJFNUQJFPOFJJTWEUTSEONMNJHMFUY\ UPOJWNMGNMGLJAJJFGTUXFCQUTCJHGCJWUTJLJFHJFNXTOJW' # print ctstr ct = AS.encoding(ctstr); ct 
       
knowns = {'A' : 'B', 'C' : 'D', 'E' : 'W', 'F' : 'N', 'G' : 'A', 'H' : 'C', 'J' : 'E', 'L' : 'V', 'M' : 'H', 'N' : 'T', 'O' : 'I', 'P' : 'G', 'Q' : 'F', 'R' : 'P', 'S' : 'K', 'T' : 'R', 'U' : 'O', 'V' : 'M', 'W' : 'S', 'X' : 'U', 'Y' : 'L', 'Z' : 'Y'} partial_decode(ctstr, knowns) 
       
knowns = {'A' : 'B', 'B' : 'J', 'C' : 'D', 'D' : 'Q', 'E' : 'W', 'F' : 'N', 'G' : 'A', 'H' : 'C', 'I' : 'X', 'J' : 'E', 'K' : 'Z', 'L' : 'V', 'M' : 'H', 'N' : 'T', 'O' : 'I', 'P' : 'G', 'Q' : 'F', 'R' : 'P', 'S' : 'K', 'T' : 'R', 'U' : 'O', 'V' : 'M', 'W' : 'S', 'X' : 'U', 'Y' : 'L', 'Z' : 'Y'} engkey = partial_decode('ABCDEFGHIJKLMNOPQRSTUVWXYZ', knowns); engkey 
       
Ekey = AS.encoding(engkey); Ekey 
       
ct.parent() 
       
K = SC.random_key() K.parent() 
       
SC.deciphering? 
       
SC.enciphering(Ekey, ct) 
       
# Here is an actual key that produces the ciphertext SC.inverse_key(Ekey)