0

Ceasar cipher encryption method. Using ord() and chr () to decrypt a string. If a value with the offset is < 32 or > 126 on the ASCII table it will loop back around to the appropriate value.

However, it is not working 100%, skips over symbols from the ASCII table for some reason, and isn't getting every value correct?

input - yohvldvk#wioH#$

offset - 5

expected output - tjcqg_qf}rdjC}~

user_decrypt_message = input("Please enter string to decrypt: ")
decrypted_message = ""
user_decrypt_offset = 0

while not user_decrypt_offset in range (1, 95):
    user_decrypt_offset = int(input("Please enter offset value (1 to 94): "))

for letter in user_decrypt_message:
    if ord(letter) + user_decrypt_offset < 32:
        decrypted_message += chr(ord(letter) - user_decrypt_offset + 95)
    elif ord(letter) + user_decrypt_offset > 126:
        decrypted_message += chr(ord(letter) + user_decrypt_offset - 95)
    else:
        decrypted_message += chr(ord(letter) - user_decrypt_offset)

print()
print("Decrypted string: ")
print(decrypted_message)
Infusion
  • 17
  • 5
  • You are checking if `ord(letter) + user_decrypt_offset` is in the valid range - but in two of the three possible branches, you are basing the result on `ord(letter) - user_decrypt_offset` instead. The validity check you performed tells you nothing about whether *that* result is valid. – jasonharper May 15 '22 at 15:29
  • You are adding a number and then if it is *below* the lowest value you are subtracting the same number and adding a constant. You are showing a decryption method while you are talking about encryption in your question. All logic is wrong. For decryption you probably always need to extract the offset, assuming that it is the same for encryption / decryption. – Maarten Bodewes May 15 '22 at 15:29
  • What you want to do is to introduce a `charToIndex` which converts the character to a range 0..94, then do the shifting (which can now use the modulus operator) and then convert back to character. The more steps, the easier it is to debug. – Maarten Bodewes May 15 '22 at 15:34
  • It seems to be working but not completely it skips over the symbols such as } and ~. The + or - 95 is so it loops back and pulls the correct ASCII value in the range of 32-126. I'm new to coding are you able to draft a code so I can see? – Infusion May 15 '22 at 15:46

2 Answers2

0
def inputOffset():
    user_decrypt_offset = 0
    while user_decrypt_offset < 1 or user_decrypt_offset >= 95:
        user_decrypt_offset = int(input("Please enter offset value (1 to 94): "))
    return user_decrypt_offset
    
def decrypt(iuser_decrypt_message, user_decrypt_offset):
    decrypted_message = ""
    for letter in iuser_decrypt_message:
        if ord(letter) + user_decrypt_offset < 32:
            print("1. if", ord(letter))
            decrypted_message += chr(ord(letter) - user_decrypt_offset + 95)
        elif ord(letter) + user_decrypt_offset > 126:
            print("2. if", ord(letter))
            decrypted_message += chr(ord(letter) + user_decrypt_offset - 95)
        else:
            print("3. if", ord(letter))
            decrypted_message += chr(ord(letter) - user_decrypt_offset)
        print(decrypted_message, ord(decrypted_message[-1]))
    return decrypted_message
    
iuser_decrypt_message = input("Please enter string to decrypt: ")
user_decrypt_offset = inputOffset()
decrypted_message = decrypt(iuser_decrypt_message, user_decrypt_offset)

print()
print("Decrypted string: ")
print(decrypted_message)

I just rewrote your code and added a few print statements. If you run this code you will see that when the loop inside decrypt() function come to '#'(whose ASCII value is 35) it will jump to 3. if statement and it will append a character with ASCII value 30(35 - 5) which is ␞(record separator delimiter). I guess there is a problem with it because it won't display.

DimitrijeCiric
  • 446
  • 1
  • 10
  • Right I see, so in my case, it should wrap back around to ASCII value 125 as it's going < 32. Is there a way to do that? Maybe with modulus or something? @DimitrijeCiric – Infusion May 15 '22 at 15:59
  • Yes, it should be done with modulo. You can make string with characters that are allowed in input, and to perform shift with modulo on that string. @Infusion – DimitrijeCiric May 15 '22 at 16:22
0

The problem is that your code is not consistent in subtracting the offset. Sometimes it adds it, sometimes it subtracts it. It should always do the same thing.

To avoid this mistake, first calculate the new offset, put it in a variable, and only work with that name from then onwards.

So:

for letter in user_decrypt_message:
    # Subtract the offset (never add it)
    new_offset = ord(letter) - user_decrypt_offset
    if new_offset < 32:
        decrypted_message += chr(new_offset + 95)
    elif new_offset > 126:
        decrypted_message += chr(new_offset - 95)
    else:
        decrypted_message += chr(new_offset)

It may be useful to work with the modulo operator:

for letter in user_decrypt_message:
    new_offset = (ord(letter) - user_decrypt_offset - 32) % 95 + 32
    decrypted_message += chr(new_offset)

And you can also build the string via a list comprehension:

decrypted_message = "".join(
    chr((ord(letter) - user_decrypt_offset - 32) % 95 + 32)
    for letter in user_decrypt_message
)
trincot
  • 317,000
  • 35
  • 244
  • 286