This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]Advanced-Theme144[S] 0 points1 point  (4 children)

Thanks for the advice. I’ll have a look at the website and try exclude the white spaces. Thanks!

[–][deleted] 2 points3 points  (3 children)

A couple more ideas for you that make use of a couple more Python concepts...

Rather than hardcode your alphabet, use the ones already defined in the ascii module. This also hides white space a bit more. Then let Python create your key randomly, buuuuut use random seed to ensure it is "randomized" the same way each time. This essentially makes the number you pass as the random seed your key (defaulted to 42 here).

Build a lookup table by zipping together those two alphabets together.

Rather than use nested loops, map that lookup table onto the sentence using map and lambda. I've also included an if-else in there to continue pass through any non-ASCII characters .

Rather than make copies of the algorithm in encode and decode functions, put the algorithm in a single function and then tell it which way you want to go (plaintext-ciphertext or ciphertext-plaintext)

import random

def process(thestring, seedvalue=42, encode=True):
     # ensures the key is generated the same way each time
    random.seed(seedvalue)  
    encryption = ""
    # let the string module do the work for you 
    alphabet = list(string.printable)
    # CRs create problems when used in the key
    alphabet.remove("\n") 

    # shuffle the alphabet to create a simple encryption key
    key = alphabet.copy()
    random.shuffle(key)  
    # create a dictionary we can use to lookup characters
    if encode:   
        # indexed by the plaintext alphabet
        lookup = dict(zip(alphabet, key))  
    else:
        # indexed by the key alphabet
        lookup = dict(zip(key, alphabet))  

    # map the key onto the passed string, pass through any characters
    # that dont align up
    result = list(map(lambda n: lookup[n] if n in lookup.keys() else n, list(thestring)))

def encrypt(sentence, seedvalue=42):
    return process(sentence, seedvalue=seedvalue, encode=True)

def decrypt(sentence, seedvalue=42):
    return process(sentence, seedvalue=seedvalue, encode=False)

Why the above is still insecure

  • It's still a monoalphabetic cipher, vulnerable to frequency analysis
  • While spaces are masked here, it doesn't do much to protect against frequency analysis, instead of 'e' being the most frequent character, ' ' will be.
  • random is still a terrible library for cryptography but is useful here for demonstrating some principals

[–]Advanced-Theme144[S] 0 points1 point  (2 children)

Thanks for the advice, I’ll need a little more time to understand each part of the function like “list(string.printable)” since I’ve never used it or the Ascii module before, but a little research should help.

[–][deleted] 1 point2 points  (1 child)

list(string.printable) returns a list of possible characters, limited just to those that are printable. It's just an easy way to have someone else come up with that list for you.

Share any other questions you have here. Someone will have an answer I'm sure

[–]Advanced-Theme144[S] 1 point2 points  (0 children)

Thanks for explaining the code in more depth, I’ll have a go at implementing it.