4
\$\begingroup\$

This is my final version of my simpel Decrypter/Encryptor called Dencryptor. This is one of my first Python projects and I think it turned out pretty good. I am using a Caesar cipher right now and I think it is working as intended. I may try to add some other ciphers to it but I think it is working good right now. This was just a project to learn from and the encryption isn't strong so I do not recommend any one actually using this for anything.

List of commands:

  • help - Show this page.
  • encrypt {text} - Encrypt some text
  • key - Displays your current decryption key
  • key {key} - Set a decryption key
  • decrypt {text} - Decrypt some text
  • exit - close application

What do you guys think about it? Any changes required?

Special thanks to: @Coal_ and @henje for helping!

    import secrets
    import string

    print("""  _____                                   _            
     |  __ \                                 | |           
     | |  | | ___ _ __   ___ _ __ _   _ _ __ | |_ ___ _ __ 
     | |  | |/ _ \ '_ \ / __| '__| | | | '_ \| __/ _ \ '__|
     | |__| |  __/ | | | (__| |  | |_| | |_) | ||  __/ |   
     |_____/ \___|_| |_|\___|_|   \__, | .__/ \__\___|_|   
                                   __/ | |                 
                                  |___/|_|                 """)
    userinput = ''
    exit = False
    key = None
    characters = list(string.printable)[:-5]


    def get_int(prompt):
            try:
                return int(prompt)
            except ValueError:
                print("Input requires a number!")


    def encrypt(args, key):
        text = []
        encryptlist = []
        try:
            for line in args:
                text.extend(line)
            for x in range(len(text)):
                index = characters.index(text[x])
                newindex = (index + key) % len(characters)
                cipher = characters[newindex]
                encryptlist.append(cipher)
                x += 1
            encrypted = ''.join(encryptlist)
            return encrypted
        except ValueError:
            print('Invalid character(s)!')


    def decrypt(args, key):
        text = []
        decryptlist = []
        try:
            for line in args:
                text.extend(line)
            for x in range(len(text)):
                index = characters.index(text[x])
                newindex = (index - key) % len(characters)
                cipher = characters[newindex]
                decryptlist.append(cipher)
                x += 1
            decrypted = ''.join(decryptlist)
            return decrypted
        except ValueError:
            print('Invalid character(s)!')


    while not exit:
        arguments = ''
        userinput = input('> ')
        command = userinput.split(' ', 1)[0]

        if userinput != command:
            arguments = userinput.split(' ', 1)[1]

        if userinput == 'help':
            print('''
    Dencrypter commands
    ------------------------------------------
    help - Show this page.
    encrypt {text} - Encrypt some text
    key - Displays your current decryption key
    key {key} - Set a decryption key
    decrypt {text} - Decrypt some text
    exit - close application
            ''')

        if userinput == 'exit':
            exit = True

        elif command == 'encrypt':
            encryptionkey = secrets.randbits(10)
            encryption = encrypt(arguments, encryptionkey)
            if arguments != '':
                if encryption is not None:
                    print('Encrypted tekst: ' + encryption)
                    print('Encryption key: ' + str(encryptionkey))
            else:
                print('The encrypt command requires an argument. \nUse like this: encrypt {text}')

        elif command == 'key':
            if arguments != '':
                key = get_int(arguments)
                if key is not None:
                    print('Decryption key changed to: ' + str(key))
            else:
                print('Decryption key: ' + str(key))

        elif command == 'decrypt':
            if arguments != '':
                print('Decrypted tekst: ' + decrypt(arguments, key))
                print('Using decryption key: ' + str(key))
            else:
                print('The decrypt command requires an argument. \nUse like this: decrypt {tekst}')
\$\endgroup\$
4
\$\begingroup\$

It's a nice program, intuitively usable and good if you don't have any cryptographically versed attacker.

When I tried it, my session looked like this:

> encrypt Hello
Encrypted text: (ELLO
Encryption key: 311
> decrypt (ELLO
Traceback (most recent call last):
  File "C:/Users/rillig/git/python-playground/caesar.py", line 105, in <module>
    print('Decrypted tekst: ' + decrypt(arguments, key))
  File "C:/Users/rillig/git/python-playground/caesar.py", line 52, in decrypt
    newindex = (index - key) % len(characters)
TypeError: unsupported operand type(s) for -: 'int' and 'NoneType'

Oops. But that's easy to fix.

Like in every Python review here, have a look at PEP 8, the Python style guide. It has lots of tips on how to structure the code and format it nicely. Yes, it's a long document, so read it in little steps, as you have time.

In your greeting string, the first line looks weird. When you add a backslash immediately after the opening """, the first line break is ignored in the string:

print("""\
  _____                                   _
 |  __ \                                 | |
 | |  | | ___ _ __   ___ _ __ _   _ _ __ | |_ ___ _ __
 | |  | |/ _ \ '_ \ / __| '__| | | | '_ \| __/ _ \ '__|
 | |__| |  __/ | | | (__| |  | |_| | |_) | ||  __/ |
 |_____/ \___|_| |_|\___|_|   \__, | .__/ \__\___|_|
                               __/ | |
                              |___/|_|                 """)

Now your logo looks good in the source code also.

To quote from your code:

characters = list(string.printable)[:-5]

Be careful that the encrypted text does not end in a space. That would not be visible on the screen. Imagine this small dialog:

Q: How much do I owe you?
A: 150

Now if that is encrypted and the final 0 is missing, that would be bad.

Continuing with your code:

except ValueError:
    print('Invalid character(s)!')

This error message is a bit unspecific. If your program is friendly, it tells me which of the many characters I typed is invalid, ideally with some context so that I can find it.

        print('''
Dencrypter commands
------------------------------------------
help             Show this page
encrypt {text}   Encrypt some text
key              Display your current decryption key
key {key}        Set a decryption key
decrypt {text}   Decrypt some text
exit             Close application
        ''')

I reformatted this usage section to start all descriptions in the same column. That way, I can easily scan the first word of each description to see which of the verbs is most appropriate to what I want to do.

I also normalized the periods at the end, the upper/lower spelling of the first letter and replaced Displays with Display, to match the grammar of the other entries.

By the way, it's great that you use actual verbs as the commands. I see many other beginner programs that have numbered menu items: Press 1 to encrypt a text. Press 2 to enter a decryption key. And so on. Your variant is the way to go.

You should normalize tekst to text. :)

I really like the Use it like this instructions. They are essential for having fun with the program. "Don't tell me what I did wrong, rather tell me how to do it correctly."

To make your program easily testable, it should do all of its work in a function called main. See this question for further details.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.