Skip to content

Instantly share code, notes, and snippets.

@dssstr
Last active August 18, 2024 00:10
Show Gist options
  • Save dssstr/aedbb5e9f2185f366c6d6b50fad3e4a4 to your computer and use it in GitHub Desktop.
Save dssstr/aedbb5e9f2185f366c6d6b50fad3e4a4 to your computer and use it in GitHub Desktop.
Simple Vigenere Cipher written in Python 3.5.
def encrypt(plaintext, key):
key_length = len(key)
key_as_int = [ord(i) for i in key]
plaintext_int = [ord(i) for i in plaintext]
ciphertext = ''
for i in range(len(plaintext_int)):
value = (plaintext_int[i] + key_as_int[i % key_length]) % 26
ciphertext += chr(value + 65)
return ciphertext
def decrypt(ciphertext, key):
key_length = len(key)
key_as_int = [ord(i) for i in key]
ciphertext_int = [ord(i) for i in ciphertext]
plaintext = ''
for i in range(len(ciphertext_int)):
value = (ciphertext_int[i] - key_as_int[i % key_length]) % 26
plaintext += chr(value + 65)
return plaintext
@flipperbw
Copy link

I think there are limitations here with lower case and capital letters. You'd need to check for .lower(), and also simply pass the character through if it doesn't match A-Z.

I wrote one that handles all default ASCII characters (95):

def vig(txt='', key='', typ='d'):
    if not txt:
        print 'Needs text'
        return
    if not key:
        print 'Needs key'
        return
    if typ not in ('d', 'e'):
        print 'Type must be "d" or "e"'
        return

    k_len = len(key)
    k_ints = [ord(i) for i in key]
    txt_ints = [ord(i) for i in txt]
    ret_txt = ''
    for i in range(len(txt_ints)):
        adder = k_ints[i % k_len]
        if typ == 'd':
            adder *= -1

        v = (txt_ints[i] - 32 + adder) % 95

        ret_txt += chr(v + 32)

    print ret_txt
    return ret_txt

For example:

q = vig('Let\'s check this out!', 'super secret key', 'e')
`{&-'@wnivq55to.4&'z4
vig(q, 'super secret key', 'd')
Let's check this out!

@flipperbw
Copy link

flipperbw commented Jan 3, 2018

Okay, even better:

universe = [c for c in (chr(i) for i in range(32,127))]

uni_len = len(universe)

def vign(txt='', key='', typ='d'):
    if not txt:
        print 'Needs text.'
        return
    if not key:
        print 'Needs key.'
        return
    if typ not in ('d', 'e'):
        print 'Type must be "d" or "e".'
        return
    if any(t not in universe for t in key):
        print 'Invalid characters in the key. Must only use ASCII symbols.'
        return

    ret_txt = ''
    k_len = len(key)

    for i, l in enumerate(txt):
        if l not in universe:
            ret_txt += l
        else:
            txt_idx = universe.index(l)

            k = key[i % k_len]
            key_idx = universe.index(k)
            if typ == 'd':
                key_idx *= -1

            code = universe[(txt_idx + key_idx) % uni_len]

            ret_txt += code

    print ret_txt
    return ret_txt

@0xjmux
Copy link

0xjmux commented Mar 6, 2018

@flipperbw ,
I'm trying to make a similar program. Would you mind reposting your code with comments; I'm having a bit of a hard time following it.
Thanks.

@deed02392
Copy link

I implemented this some years ago, along with a tabula recta generator so you can do it by hand (for fun!)

https://github.com/deed02392/vigenere

@C0C41N3LoRd
Copy link

@flipperbw

Hello!
in your first code (the one that starts like:
def vig(txt='', key='', typ='d'):
if not txt:
print 'Needs text')
there is a thing called "ret_text"
what does it do? I am trying to get inputs and then encode/decode it but I am not sure how I should do that, if only I knew what ret_text does. Can you specify it?
Thanks!

@flipperbw
Copy link

It's just the return text, that one by one figures out the proper character to return given the key. It's been a while since I wrote this snippet but if it can find a match of an ascii character, itll convert that, else it will leave it alone.

@HamburgerPlsdotexe
Copy link

I think there are limitations here with lower case and capital letters. You'd need to check for .lower(), and also simply pass the character through if it doesn't match A-Z.

I wrote one that handles all default ASCII characters (95):

def vig(txt='', key='', typ='d'):
    if not txt:
        print 'Needs text'
        return
    if not key:
        print 'Needs key'
        return
    if typ not in ('d', 'e'):
        print 'Type must be "d" or "e"'
        return

    k_len = len(key)
    k_ints = [ord(i) for i in key]
    txt_ints = [ord(i) for i in txt]
    ret_txt = ''
    for i in range(len(txt_ints)):
        adder = k_ints[i % k_len]
        if typ == 'd':
            adder *= -1

        v = (txt_ints[i] - 32 + adder) % 95

        ret_txt += chr(v + 32)

    print ret_txt
    return ret_txt

For example:

q = vig('Let\'s check this out!', 'super secret key', 'e')
`{&-'@wnivq55to.4&'z4
vig(q, 'super secret key', 'd')
Let's check this out!

I like the way your code works but I dislike its readability

@shreyakapadia10
Copy link

What about lowercase?

@abiboe
Copy link

abiboe commented Apr 10, 2021

import tkinter as tk
from tkinter import ttk
from tkinter import *

root = Tk()

root.geometry('826x567')
root.configure(background='#000000')
root.title('Message Encryption and Decryption')

lblInfo=Label(root, text=':::::SECRET MESSAGING:::::::: \n :::Vigenère cipher:::', bg='black', font=('helvetica', 22, 'normal'),fg='purple').place(x=264, y=36)

rand = StringVar()
Msg = StringVar()
key = StringVar()
mode = StringVar()
Result = StringVar()

def qExit():
root.destroy()

def Reset():
rand.set("")
Msg.set("")
key.set("")
mode.set("")
Result.set("")

lblReference = Label(root,bg="black", font = ('Century', 11, 'bold'),text = "NAME:::",fg="white", bd = 11, anchor = "w").place(x=98, y=197)
txtReference =Entry(root, font = ('Century', 11, 'bold'),textvariable = rand, bd = 10, insertwidth = 4,bg = "white", justify = 'right').place(x=343, y=198)
lblMsg =Label(root,bg="black", font = ('Century', 11, 'bold'),text = "MESSAGE:::",fg="white", bd = 11, anchor = "w").place(x=98, y=241)
txtMsg =Entry(root, font = ('Century', 11, 'bold'),textvariable = Msg, bd = 10, insertwidth = 4,bg = "white", justify = 'right').place(x=343, y=241)
lblkey =Label(root,bg="black", font = ('Century', 11, 'bold'),text = "KEY:::",fg="white", bd = 11, anchor = "w").place(x=98, y=274)
txtkey =Entry(root, font = ('Century', 11, 'bold'),textvariable = key,fg="black", bd = 10, insertwidth = 4,bg = "white", justify = 'right').place(x=343, y=275)
lblmode =Label(root,bg="black", font = ('Century', 11, 'bold'),text = "Mode==",fg="white", bd = 11, anchor = "w").place(x=98, y=316)
txtmode =Entry(root, font = ('Century', 11, 'bold'),textvariable = mode, bd = 10, insertwidth = 4,bg = "white", justify = 'right').place(x=343, y=316)
lblService = Label(root,bg="black", font = ('Century', 11, 'bold'),text = "The Result--",fg="white", bd = 11, anchor = "w").place(x=98, y=354)
txtService = Entry(root, font = ('Century', 11, 'bold'),textvariable = Result, bd = 10, insertwidth = 4,bg = "white", justify = 'right').place(x=343, y=354)

import base64

def encode(key, clear):
enc = []

for i in range(len(clear)): 
    key_c = key[i % len(key)] 
    enc_c = chr((ord(clear[i]) +
                 ord(key_c)) % 256) 
                   
    enc.append(enc_c) 
      
return base64.urlsafe_b64encode("".join(enc).encode()).decode() 

def decode(key, enc):
dec = []

enc = base64.urlsafe_b64decode(enc).decode() 
for i in range(len(enc)): 
    key_c = key[i % len(key)] 
    dec_c = chr((256 + ord(enc[i]) -
                       ord(key_c)) % 256) 
                         
    dec.append(dec_c) 
return "".join(dec) 

def Ref():
print("Message= ", (Msg.get()))

clear = Msg.get() 
k = key.get() 
m = mode.get() 

if (m == 'e'): 
    Result.set(encode(k, clear)) 
else: 
    Result.set(decode(k, clear))

btnTotal =Button(root, text='Show Message', bg='#7FFF00', font=('verdana', 12, 'normal'), command=Ref).place(x=112, y=444)
btnReset =Button(root, text='Reset', bg='#FF3030', font=('verdana', 12, 'normal'), command=Reset).place(x=250, y=444)
btnExit =Button(root, text='Exit', bg='#A020F0', font=('verdana', 12, 'normal'), command=qExit).place(x=315, y=444)

root.mainloop()

@v1a0
Copy link

v1a0 commented Jan 20, 2022

Vigenere Cipher for any Unicode text

[ ! ] text and key have to be unicode encoding

def vigenere(text: str, key: str, encrypt=True):

    result = ''

    for i in range(len(text)):
        letter_n = ord(text[i])
        key_n = ord(key[i % len(key)])

        if encrypt:
            value = (letter_n + key_n) % 1114112
        else:
            value = (letter_n - key_n) % 1114112

        result += chr(value)

    return result
    

def vigenere_encrypt(text: str, key: str):
    return vigenere(text=text, key=key, encrypt=True)


def vigenere_decrypt(text: str, key: str):
    return vigenere(text=text, key=key, encrypt=False)

Example

>>> vigenere_encrypt(u"Hello world!", u"Leet1337:)")
'\x94ÊÑà\xa0Sª¦¬\x95°\x86'

>>> vigenere_decrypt(u"\x94ÊÑà\xa0Sª¦¬\x95°\x86", u"Leet1337:)")
'Hello world!'

@v1a0
Copy link

v1a0 commented Jan 20, 2022

Vigenere Cipher for specific alphabet

def vigenere(
        text: str, 
        key: str, 
        alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
        encrypt=True
):

    result = ''

    for i in range(len(text)):
        letter_n = alphabet.index(text[i])
        key_n = alphabet.index(key[i % len(key)])

        if encrypt:
            value = (letter_n + key_n) % len(alphabet)
        else:
            value = (letter_n - key_n) % len(alphabet)

        result += alphabet[value]

    return result


def vigenere_encrypt(text, key):
    return vigenere(text=text, key=key, encrypt=True)


def vigenere_decrypt(text, key):
    return vigenere(text=text, key=key, encrypt=False)

Example

vigenere_encrypt('Python', 'secretWORD')
'HcVYSg'

vigenere_decrypt('HcVYSg', 'secretWORD')
'Python'

P.S. Please note that the alphabet from the example is missing a space, so trying to encrypt several words will throw an exception!

vigenere_encrypt('Hello world', 'SecRet')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "<input>", line 34, in vigenere_encrypt
  File "<input>", line 16, in vigenere
ValueError: substring not found

For fix it, just add space into the alphabet

...
alphabet='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ', # <--- HERE
...

@SHTEFOZOID
Copy link

bravo Raihan!! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment