Chapter 1 Intro to Cryptography

Section 1 Simple Substitiution Ciphers

These examples are related to the notes: http://webbuild.knu.ac.kr/~mhs/classes/2019/spring/crypt/notes.pdf

There is a simple way to convert a character to and from its ASCII equivalent.

In [20]:
ord('F')
Out[20]:
70
In [21]:
ord('A'), ord('Z'), ord('a'), ord('z'),  ord(' ')
Out[21]:
(65, 90, 97, 122, 32)
In [22]:
chr(70), chr(71), chr(231)
Out[22]:
('F', 'G', '\xe7')
In [23]:
[(i,chr(i)) for i in range(90,97)]
Out[23]:
[(90, 'Z'), (91, '['), (92, '\\'), (93, ']'), (94, '^'), (95, '_'), (96, '`')]

But this will be a bit troublesome.  Lets make our own encoding of a smaller alphabet.

In [24]:
myAlphabet = [chr(i) for i in range(65,91)]; 
In [25]:
myAlphabet.insert(0, chr(32)); myAlphabet.append(chr(46));
In [26]:
myAlphabet[5], myAlphabet.index('T')
Out[26]:
('E', 20)

Now lets make some nicely named functions for encoding and decoding.

In [27]:
def encode(lCharacter):
    return myAlphabet.index(lCharacter);
In [28]:
def decode(lNumber):
    return myAlphabet[lNumber];
In [29]:
decode(5); encode('Y');

Now we want to take a message, and convert it into a LIST of letters, so we can convert each to a number.

In [30]:
message = list('TOMORROW AT LUNCH.'); message
Out[30]:
['T',
 'O',
 'M',
 'O',
 'R',
 'R',
 'O',
 'W',
 ' ',
 'A',
 'T',
 ' ',
 'L',
 'U',
 'N',
 'C',
 'H',
 '.']

Yuck. I don't like reading it like that. I won't print out all of the lists from now on. Just a slice of them.

In [31]:
message = list('WHEN I FIND MYSELF IN TIMES OF TROUBLE MOTHER MARY COMES TO ME SPEAKING WORDS OF WISDOM LET IT BE.'); message[0:4]
Out[31]:
['W', 'H', 'E', 'N']

Now lets ENCODE this to some simple numerical PLAINTEXT so that we can work with it.

In [32]:
plaintext = [encode(i) for i in message]; plaintext[0:5]
Out[32]:
[23, 8, 5, 14, 0]

Or we could use the map function.

In [33]:
plaintext = map(encode, message); plaintext[0:5]
Out[33]:
[23, 8, 5, 14, 0]

Now lets permute the numbers  in our alphabet to make a simple substitiution cipher.

In [2]:
myPermutation=list(Permutations(26).random_element()); myPermutation[0:10]
Out[2]:
[23, 15, 25, 21, 13, 24, 8, 12, 19, 20]
In [35]:
myPermutation.insert(0, 0); myPermutation.append(27); myPermutation[0:10]
Out[35]:
[0, 5, 4, 6, 19, 7, 24, 1, 12, 25]

Notice I'm not permuting the space ' ' or the period '.'.

In [36]:
def encrypt(lNumber):
    return myPermutation[lNumber];
In [37]:
def decrypt(lNumber):
    return myPermutation.index(lNumber);
In [38]:
encrypt(10), decrypt(7), decrypt(encrypt(9))
Out[38]:
(21, 5, 9)
In [39]:
codeword =  map(encrypt, plaintext); codeword[0:10]
Out[39]:
[13, 12, 7, 26, 0, 25, 0, 24, 25, 26]
In [40]:
encrypt(27)
Out[40]:
27
In [41]:
code = map(decode,codeword); code[0:10]
Out[41]:
['M', 'L', 'G', 'Z', ' ', 'Y', ' ', 'X', 'Y', 'Z']
In [42]:
code = map(decode,map(encrypt, map(encode, list("I AM GOING TO KILL YOU")))); code[0:10]
Out[42]:
['Y', ' ', 'E', 'W', ' ', 'A', 'B', 'Y', 'Z', 'A']

Now. I don't want this as a list. I want it as a string.

In [43]:
def join(code):
  message = ""
  for i in range(len(code)):
     message = message + code[i]
  return message
In [44]:
join(code)
Out[44]:
'Y EW ABYZA VB IYCC TBR'
In [45]:
join(map(decode, map(decrypt, codeword)))
Out[45]:
'WHEN I FIND MYSELF IN TIMES OF TROUBLE MOTHER MARY COMES TO ME SPEAKING WORDS OF WISDOM LET IT BE.'

Lets package that all up into some convenient functions.

In [46]:
def MyEncrypt(plaintext):
    return join(map(decode, map(encrypt, map(encode, list(plaintext)))))
In [47]:
cyphertext = MyEncrypt('WHO TOOK MY GUM.'); cyphertext
Out[47]:
'MLB VBBI WT ARW.'
In [48]:
def MyDecrypt(cyphertext):
    return join(map(decode, map(decrypt, map(encode, list(cyphertext)))))
In [49]:
MyDecrypt(cyphertext)
Out[49]:
'WHO TOOK MY GUM.'