Search code examples
pythonencryptionuppercaselowercasevigenere

encrypting upper-case letters python vigenere


I'm having trouble encrypting upper-case letters e.g. if the message is COMPUTING IS FUN the keyword is GCSE i should get JRFUBWBSN LL KBQ but my actual result is xftipkpgb zz ype. This result neither has the correct letters nor is capital. Any help appreciated

                    message = input('\nenter message: ')
                    keyword = input('enter keyword: ')
                    def chr_to_inta(char):
                        return 0 if char == 'Z' else ord(char)-64
                    def int_to_chra(integer):
                        return 'Z' if integer == 0 else chr(integer+64)
                    def add_charsa(msg, key):
                        return int_to_chr(( chr_to_int(msg) + chr_to_int(key)) % 26 )


                    def chr_to_int(char):
                        return 0 if char == 'z' else ord(char)-96
                    def int_to_chr(integer):
                        return 'z' if integer == 0 else chr(integer+96)
                    def add_chars(msg, key):
                        return int_to_chr(( chr_to_int(msg) + chr_to_int(key)) % 26 )

                    def vigenere(message, keyword):

                        keystream = cycle(keyword)
                        new = ''
                        for msg in message:
                            if msg == ' ': # adds a space
                                new += ' '
                            elif 96 < ord(msg) < 123: # if lowercase
                                new += add_chars(msg, next(keystream))

                            else: # if uppercase
                                new += add_charsa(msg, next(keystream))

                        return new

                    new = vigenere(message, keyword)
                    print('your encrypted message is: ',new)

Solution

  • since you dont seem to get what i am saying:

    def add_charsa(msg, key):
        return int_to_chr(( chr_to_int(msg) + chr_to_int(key)) % 26 )
    

    is what you currently have. with this, you get your bad output:

    >>> vigenere('COMPUTING IS FUN','GCSE')
    'xftipkpgb zz ype'
    

    This is because you have not changed the return statement for this function to call your new uppercase functions. if you change the return statement to:

    def add_charsa(msg, key):
        return int_to_chra(( chr_to_inta(msg) + chr_to_inta(key)) % 26 )
    #notice the change in function calls from int_to_chr -> int_to_chra, and chr_to_int -> chr_to_inta
    

    you will then get the expected:

    >>> vigenere('COMPUTING IS FUN','GCSE')
    'JRFUBWBSN LL KBQ'
    

    It is worth it to know that if your key has a mix of upper and lower case letters, this will not work. very well. i would instead change your keystream to be : keystream = cycle(keyword.lower()) then your function would be:

    def add_charsa(msg, key):
            return int_to_chra(( chr_to_inta(msg) + chr_to_int(key)) % 26 )
        #notice the call to chr_to_int(key) because key will always be lower case