how to convert bytes to binary using python - python

so i want convert bytes to binary in python, but when i run it, there's none in the result and i got error:
'NoneType' object is not iterable
here's the code i tried
//func biner
def biner(password):
print(password)
password[0]
for my_byte in password:
print(f'{my_byte:0>8b}', end=' ')
//func to use the result from func biner
def skalar(key, biner):
if len(key) <= key_bytes:
for x in range(len(key),key_bytes):
key = key + "0"
jumbin2 = len(key)
print(jumbin2)
jumbin = biner
print(biner)
hasilenkrip = ''
for a in jumbin:
hasilenkrip += a * jumbin2
print(hasilenkrip)
//how i called the func
enc = b'l\x87\x87\xe6'
ky = maru
tes = biner(enc)
tes1 = skalar(ky, tes)
print(tes1)

Your function currently returns None because there's no return statement. Perhaps instead of using print, you should modify your functions to return an array of outputs.
I suspect what you have in mind is something like this.
# //func biner
def biner(password):
print(password)
password[0]
return ' '.join(f'{my_byte:0>8b}' for my_byte in password)
# //func to use the result from func biner
def skalar(key, biner):
if len(key) <= key_bytes:
for x in range(len(key),key_bytes):
key = key + "0"
jumbin2 = len(key)
print(jumbin2)
jumbin = biner
print(biner)
hasilenkrip = ''
for a in jumbin:
hasilenkrip += a * jumbin2
return hasilenkrip
# print(hasilenkrip)
# //how i called the func
enc = b'l\x87\x87\xe6'
ky = maru
tes = biner(enc)
tes1 = skalar(ky, tes)
print(tes1)

some_bytes = int(input('Enter bytes: '))
print(f'{some_bytes>>4:04b}{some_bytes&0xf:04b} ({some_bytes})')

Related

Set function in Tkinter failed to display correct value

I'm creating a calculator and here's part of the code:
def _digit_formatting(x):
numbers = '1234567890.'
start_idxs = []
end_idxs = []
is_start = True
try:
for idx, value in enumerate(x):
if value in numbers and is_start:
start_idxs.append(idx)
is_start = False
elif value in numbers and idx == len(x) - 1:
end_idxs.append(len(x) - 1)
elif value in numbers and not is_start:
pass
elif value not in numbers and len(start_idxs) > len(end_idxs):
end_idxs.append(idx-1)
is_start = True
except:
...
if len(start_idxs) > len(end_idxs):
end_idxs.append(start_idxs[-1])
start_idxs.reverse()
end_idxs.reverse()
x = list(x)
for idx in range(len(start_idxs)):
if start_idxs[idx] == end_idxs[idx]:
num = x[start_idxs[idx]:end_idxs[idx]+1]
else:
num = x[start_idxs[idx]:end_idxs[idx]+1]
num = ''.join(num)
x = ''.join(x)
x = x[::-1]
num = num[::-1]
x = x.replace(num, '', 1)
x = list(x)
x.reverse()
num = num[::-1]
temp = f'{int(num):,}'
x.insert(start_idxs[idx], temp)
x = ''.join(x)
return x
def calculate(sv):
# This function is called when there's changes in entry box
if self.input_string_var.get() == '':
self.result_string_var.set('')
# Start
real_result = self.input_string_var.get().replace(',', '')
percent_count = self.input_string_var.get().count('%')
# Formatting input string
x = _digit_formatting(real_result)
print(x)
self.input_string_var.set(x)
if percent_count != 0:
numbers = '0123456789.'
for cnt in range(percent_count):
percent_idx = real_result.find('%', 0)
limit_operator = 2
percent_number = ''
for i in range(percent_idx - 1, -1, -1):
if real_result[i] not in numbers:
limit_operator -= 1
if limit_operator == 0:
break
if limit_operator == 1:
if real_result[i] in '*/':
percent_number = ''
break
else:
percent_number += real_result[i]
if percent_number == '':
percent_number = '1'
else:
percent_number = percent_number[1:][::-1]
real_result = list(real_result)
real_result[percent_idx] = f'/100*{percent_number}'
real_result = ''.join(real_result)
else:
real_result = self.input_string_var.get().replace(',', '')
try:
if eval(real_result) == int(eval(real_result)):
self.result_string_var.set(f'{int(eval(real_result)):,}')
else:
self.result_string_var.set(f'{int(eval(real_result)):,}')
except:
None
if self.input_string_var.get() == '':
self.result_string_var.set('')
# Entry box string variable
self.input_string_var = tk.StringVar()
self.input_string_var.trace('w', lambda name, index, mode: calculate(self.input_string_var))
There is two functions, first is _digit_formatting which is to format the equation to put comma like thousands, million and billion. The calculate function is called every time there's changes on the input string variable. But when I try to set the string variable to equation after formatting there seems to be a mistake, but if I print the value, it is correct. Example if I enter 1200 the value I printed is 1,200 which is correct but the value on the text box is not correct. Sorry if the code is messy, I'm still learning to make a clean code.
I cannot reproduce your code.
If you can take a look of my example.
n = 1234567890
print(f"I have {n:,} Reputations")
Result:
I have 1,234,567,890 Reputations

Equivalent strings don't give equivalent bitstrings in Python

I'm currently making an encryption program for an assignment however I cannot decrypt. The cause of this is that the key is a string made from a randomly generated bitstring however when turning the key back into a bitstring I get a different bitstring. I realized this after checking and finding out that the bitstring after turning the key back to binary is shorter than the bitstring used to make the key.
##imports##################################################
from socket import *
import random
##functions################################################
def CCipher(message, k):
output = ""
for x in message:
i = ord(x)
i = (i+k)%128
output += chr(i)
return output
def toBinary(message):
output = ""
for x in message:
i = bin(ord(x))[2:]
output += i
return output
def XOR(bitstring1, bitstring2):
output = ""
if(len(bitstring1) != len(bitstring2)):
print("Use bitstrings of the same length")
return None
for x in range(len(bitstring1)):
if(bitstring1[x] == "1" and bitstring2[x] == "0"):
output += "1"
elif(bitstring1[x] == "0" and bitstring2[x] == "1"):
output += "1"
else:
output += "0"
return output
def randomBinary(k):
output = ""
for x in range(k):
i = random.randint(0,1)
output = output + str(i)
return output
def toString(message):
output = ""
i = ""
n = 0
for x in message:
n += 1
i += x
if(n == 7):
output += chr(int(i,2))
n = 0
i = ""
return output
##server stuff#########################################
serverName = "OmariPC"
serverPort = 12347
clientSocket = socket(AF_INET,SOCK_STREAM)
clientSocket.connect((serverName,serverPort))
##files################################################
nowar = open("NoWar.dat",'r')
trump = open("Trump.dat","w")
##encryption###########################################
message = nowar.read()
mesBin = toBinary(message)
bkey = randomBinary(len(mesBin))
encrypted = XOR(mesBin, bkey)
encrypted = toString(encrypted)
key = toString(bkey)
trump.write(encrypted)
trump.close()
enKey = CCipher(key, 4)
##sending###############################################
clientSocket.send(enKey.encode())
print(len(enKey))
clientSocket.send(encrypted.encode())
print(len(encrypted))
##testing###############################################
if key == toString(bkey):
print(True)
else:
print(False)
if len(toBinary(key)) == len(bkey):
print(True)
else:
print(False)
output:
168
168
True
False
def toBinary(message):
output = ""
for x in message:
i = bin(ord(x))[2:]
output += i
return output
bin(ord(x)) generates strings of variable length. For example:
>>> bin(ord(' '))
0b100000
>>> bin(ord('a'))
0b1100001
You concatenate all of the results of bin() together, so there's no way to separate them later. Meanwhile, your toString() function reads exactly 7 "bits" at a time.
You could make bin() append chunks of a fixed-size instead:
# Pad the left with 0s to always generate a string of length 7.
# (Assumes that all input characters are ASCII.)
assert(ord(x) < 128)
bin(ord(x))[2:].rjust(7, '0')

How to use global variables created from string inside the same function?

I'm trying to extract data from a SPICE netlist file, specifically the defined parameters. This are the contents (of interest) of the file 'netlist.sp':
.param freq = 860x powS = 0
+ pi = 3.141592
+ nper = 15 cap1 = 68p
+ cycles = 20
+ tper = '1/freq'
+ tstep = 'tper/nper'
+ tstop = 'cycles*tper'
FYI, the + sign means to continue the previous line, and the param = 'equation' evaluates the expression.
So, I'm trying to create a global variable inside Python 3.6 for each one of the parameters. This is the code I got so far:
def isnumber(s):
try:
float(s)
return True
except ValueError:
return False
#This function is needed to convert the '68p' format to '68e-12'
def floatify(st):
if not isnumber(st[-1]):
vals = [ 't', 'g', 'x', 'meg', 'k', 'm', 'u', 'n', 'p', 'f', 'a']
prod = [1e12, 1e9, 1e6, 1e6, 1e3, 1e-3, 1e-6, 1e-9, 1e-12, 1e-15, 1e-18]
pos = vals.index(st[-1])
st = st[:-1]
num = float(st) * prod[pos]
else:
num = float(st)
return num
#This is the main function
def params (file):
fl = 0
strng = '00'
tnum = 0.0
with open(file) as dat:
for line in dat:
if line.startswith('*'):
pass
elif line.startswith('.param '):
fl = 1
spl = line.split()
a = [i for i,x in enumerate(spl) if x=='=']
for i in range(len(a)):
strng = spl[a[i]-1]
try:
tnum = floatify(spl[a[i]+1])
except ValueError:
tnum = eval(spl[a[i]+1])
globals()[strng] = tnum
elif (line.find('+')+1) and fl:
spl = line.split()
a = [i for i,x in enumerate(spl) if x=='=']
for i in range(len(a)):
strng = spl[a[i]-1]
try:
tnum = floatify(spl[a[i]+1])
except ValueError:
temp = spl[a[i]+1]
tnum = eval(temp)
globals()[strng] = tnum
elif (not (line.find('+')+1)) and fl:
break
params('netlist.sp')
#Testing the variables
print('params done')
print('freq = ', freq)
print('powS = ', powS)
print('pi = ', pi)
print('nper = ', nper)
print('cap1 = ', cap1)
print('cycles = ', cycles)
print('tper = ', tper)
print('tstep = ', tstep)
print('tstop = ', tstop)
# Testing the eval function:
print(eval('1/freq'))
print(eval('2*pi'))
The globals()[strng] = tnum statement creates the global variable from the extracted string and assigns the corresponding value.
The output is:
freq = 860000000.0
powS = 0.0
pi = 3.141592
nper = 15.0
cap1 = 6.8e-11
cycles = 20.0
tper = 1/freq
tstep = tper/nper
tstop = cycles*tper
1.1627906976744186e-09
6.283184
So, what I understand from the testing of the eval function is that the global variables created inside the params function are understood only outside of the function itself. I know that to modify a global variable inside a function you have to declare the global var statement inside the function. My question is how to do that in this case when the variables are created dynamically?
Note: The repl.it could be cleaned up quite a bit, but it does work for the example data.
As this repl.it shows, you can do this painlessly with a dictionary.
def fill_param(token):
for key in params.keys():
token = token.replace(key, str(params[key]))
return token
is the key which allows this: it uses str.replace to fill in the values for anything we already know before we eval it:
params[key] = eval(fill_param(value))
The start of process_params() is interesting as well:
global params
tokens = shlex.split(line)[1:]
we import the dictionary, then use shlex.split() to tokenize the string, leaving off the first token (.param or + depending on the line). shlex.split() is nice because it respects quotations.
Full code (in case repl.it dies). Note it leaves a lot to be desired, as I'm spent on this problem. I leave the clean-up as an exercise to the reader.
import shlex
with open("netlist.sp", "w") as f:
f.write("""cabbage
garbage
.param freq = 860x powS = 0
+ pi = 3.141592
+ nper = 15 cap1 = 68p
+ cycles = 20
+ tper = '1/freq'
+ tstep = 'tper/nper'
+ tstop = 'cycles*tper'
sweet american freedom""")
params = {}
def param_it(in_f):
def isnumber(s):
try:
float(s)
return True
except ValueError:
return False
def floatify(st):
if not isnumber(st):
vals = [ 't', 'g', 'x', 'meg', 'k', 'm', 'u', 'n', 'p', 'f', 'a']
prod = [1e12, 1e9, 1e6, 1e6, 1e3, 1e-3, 1e-6, 1e-9, 1e-12, 1e-15, 1e-18]
pos = vals.index(st[-1])
st = st[:-1]
num = float(st) * prod[pos]
else:
num = float(st)
return num
def number(st):
if isnumber(st) or len(st) == 1 and st in '0123456789':
return True
return st[-1] not in '0123456789' and isnumber(st[:-1])
def process_params(line):
global params
tokens = shlex.split(line)[1:]
assert len(tokens) % 3 == 0
for i in range(len(tokens)/3):
key = tokens[i*3]
value = tokens[i*3 + 2]
print "Processing key: %s value: %s... " % (key, value),
if number(value):
try:
value = float(value)
except ValueError:
value = floatify(value)
params[key] = value
else:
try:
params[key] = eval(fill_param(value))
except Exception as e: # eval can throw essentially any exception
print "Failed to parse value for k/v %s:%s" % (key, value)
raise
print "Converted value is : %s\n" % params[key]
def fill_param(token):
for key in params.keys():
token = token.replace(key, str(params[key]))
return token
with open(in_f, "r") as f:
param = False
for line in f:
if line.startswith(".param "):
process_params(line)
param = True
elif param and line.startswith("+"):
process_params(line)
elif param:
break
param_it("netlist.sp")
print params

Randomized Vigenere Cipher with Python

To clarify before beginning: I'm aware there are similar topics, but nothing that has really offered any direct help. Also: this is a class project; so I'm not looking for anyone to code my project for me. Tips and advice is what I'm looking for. (I would go to my professor for this kind of thing, but he can't be bothered to check his e-mail.)
This program is meant to take a user supplied seed, generate a key based on the integer, then to generate a 95 x 95 matrix in which all printable ascii characters are available for encryption/decryption purposes. (Key is all alpha, and capitalized)
The kicker: all the cells must be randomized. See image below:
Randomized Vigenere Matrix
I will post my code below (Python is certainly not my forte, though I will definitely take constructive criticisms.):
import random
class Vigenere(object):
def __init__(self, seed):
random.seed(seed)
#string containing all valid characters
self.symbols= """!"#$%&'()*+,-./0123456789:;?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~"""
self.eTable = [[0 for i in range(len(self.symbols))] for i in range(len(self.symbols))]
self.dTable = [[0 for i in range(len(self.symbols))] for i in range(len(self.symbols))]
self.keyWord = ""
self.message = ""
self.ciphertext = ""
self.keywordFromSeed(seed)
def setMessage(self,message):
self.message = message
#Generate psuedorandom keyword from seed
def keywordFromSeed(self,seed):
Letters = []
while seed > 0:
Letters.insert(0,chr((seed % 100) % 26 + 65))
seed = seed // 100
self.keyWord = "".join(Letters)
self.buildVigenere()
#Contructs a 95 x 95 matrix filled randomly
def buildVigenere(self):
n = len(self.symbols)
#Build the vigenere matrix
for i in range(n):
temp = self.symbols
for j in range(n):
r = random.randrange(len(temp))
self.eTable[i][j] = temp[r]
#This line below does not fill entire matrix. Why?
self.dTable[j][(ord(temp[r])-32)] = chr(i+32)
temp = temp.replace(temp[r],'')
def encrypt(self):
for i in range(len(self.message)):
mi = i
ki = i % len(self.keyWord)
self.ciphertext = self.ciphertext + self.eRetrieve(ki,mi)
def decrypt(self):
for i in range(len(self.message)):
emi = i
ki = i % len(self.keyWord)
char = self.dRetrieve(ki,emi)
self.ciphertext = self.ciphertext + char
print(self.ciphertext)
def eRetrieve(self,ki,mi):
row = ord(self.message[mi]) - 32
col = ord(self.keyWord[ki]) - 32
print(row, col)
return self.eTable[row][col]
def dRetrieve(self,ki,emi):
n = len(self.symbols)
whichRow = ord(self.keyWord[ki]) - 32
whichCol = ord(self.message[emi]) - 32
return(self.dTable[whichRow][whichCol])
And just in case it helps, here's my main.py:
import argparse
import randomized_vigenere as rv
def main():
#Parse parameters
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--mode", dest="mode", default = "encrypt", help="Encrypt or Decrypt")
parser.add_argument("-i", "--inputfile", dest="inputFile", default = "inputFile.txt", help="Input Name")
parser.add_argument("-o", "--outputfile", dest="outputFile", default = "outputFile.txt", help="Output Name")
parser.add_argument("-s", "--seed", dest="seed", default =7487383487438734, help="Integer seed")
args = parser.parse_args()
#Set seed and generate keyword
seed = args.seed
#Construct Matrix
f = open(args.inputFile,'r')
message = f.read()
Matrix = rv.Vigenere(seed)
Matrix.setMessage(message)
if(args.mode == 'encrypt'):
Matrix.encrypt()
Matrix.setMessage(Matrix.ciphertext)
Matrix.decrypt()
else:
Matrix.decrypt()
o = open(args.outputFile,'w')
o.write(str(Matrix.ciphertext))
if __name__ == '__main__':
main()
I've just been using the default seed: 7487383487438734
My Plaintext: ABCdefXYZ
I am going to answer this question:
#This line below does not fill entire matrix. Why?
I think it is your current question. If I am not mistaken, this should be the first line of your question, not a simple comment in function:
def buildVigenere(self):
n = len(self.symbols)
#Build the vigenere matrix
for i in range(n):
temp = self.symbols
for j in range(n):
r = random.randrange(len(temp))
self.eTable[i][j] = temp[r]
#This line below does not fill entire matrix. Why?
self.dTable[j][(ord(temp[r])-32)] = chr(i+32)
temp = temp.replace(temp[r],'')
First thing I did was to build a small self-contained example like this:
import random
def buildVigenere():
symbols= """!"#$%&'()*+,-./0123456789:;?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~"""
n = len(symbols)
eTable = [[0 for i in range(len(symbols))] for i in range(len(symbols))]
dTable = [[0 for i in range(len(symbols))] for i in range(len(symbols))]
#Build the vigenere matrix
for i in range(n):
temp = symbols
for j in range(n):
r = random.randrange(len(temp))
eTable[i][j] = temp[r]
print (r, len(temp), j, len(symbols), temp[r])
#This line below does not fill entire matrix. Why?
print (ord(temp[r])-32)
dTable[j][(ord(temp[r])-32)] = chr(i+32)
temp = temp.replace(temp[r],'')
print dTable
buildVigenere()
You really should learn to do that if you want answers here, and more generally be a successful programmer. Finding where the problem is and being able to reproduce it in a simple case is often the key.
Here I get an error:
Exception "unhandled IndexError"
list assignment index out of range
I add some print statements(see above) and I found that the error come from the fact that < > = are missing in the symbols string.
Why don't you use chr to build your string symbols?
And for buildVigenere, you can make a much simpler version by using
random.shuffle(x)
I was able to get it working. I'll post my implementation below:
main.py
import argparse
import randomized_vigenere as rv
def main():
#Parse parameters
parser = argparse.ArgumentParser()
parser.add_argument("-m", "--mode", dest="mode", default = "encrypt", help="Encrypt or Decrypt")
parser.add_argument("-i", "--inputfile", dest="inputFile", default = "inputFile.txt", help="Input Name")
parser.add_argument("-o", "--outputfile", dest="outputFile", default = "outputFile.txt", help="Output Name")
parser.add_argument("-s", "--seed", dest="seed", default =7487383487438734, help="Integer seed")
args = parser.parse_args()
#Set seed and generate keyword
seed = args.seed
#Construct Matrix
f = open(args.inputFile,'r')
message = f.read()
Matrix = rv.Vigenere(seed)
Matrix.setMessage(message)
if(args.mode == 'encrypt'):
Matrix.encrypt()
else:
Matrix.decrypt()
o = open(args.outputFile,'w')
o.write(str(Matrix.ciphertext))
print("Seed used:",Matrix.seed)
print("Key Generated:",Matrix.keyWord)
print("Original Message:",Matrix.message)
print("Decoded Message:",Matrix.ciphertext)
if __name__ == '__main__':
main()
randomized_vigenere.py
(Be sure to add '<', '=', and '>' to the symbol list. For some reason they keep getting removed from this post.)
import random
class Vigenere(object):
#Initialize Vigenere object.
#Sets the random seed based on integer passed to the object
#Establishes all valid symbols
#Generates empty matrix which will contain values for encryption/decryption
#Generates a keyword based on the integer passed to the object
def __init__(self, seed):
random.seed(seed)
self.seed = seed
self.symbols= """ !"#$%&'()*+,-./0123456789:;?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"""
self.Table = [[0 for i in range(len(self.symbols))] for i in range(len(self.symbols))]
self.keyWord = ""
self.message = ""
self.ciphertext = ""
self.keywordFromSeed(seed)
#Sets the plaintext that will be encrypted/decrypted
def setMessage(self,message):
self.message = message
#Generate psuedorandom keyword from seed
def keywordFromSeed(self,seed):
Letters = []
while seed > 0:
Letters.insert(0,chr((seed % 100) % 26 + 65))
seed = seed // 100
self.keyWord = "".join(Letters)
self.buildVigenere()
#Contructs a 95 x 95 matrix filled randomly with no repeats within same line
def buildVigenere(self):
random.seed(self.seed)
temp = list(self.symbols)
random.shuffle(temp)
temp = ''.join(temp)
for sym in temp:
random.seed(self.seed)
myList = []
for i in range(len(temp)):
r = random.randrange(len(temp))
if r not in myList:
myList.append(r)
else:
while(r in myList):
r = random.randrange(len(temp))
myList.append(r)
while(self.Table[i][r] != 0):
r = (r + 1) % len(temp)
self.Table[i][r] = sym
#Encryption function that iterates through both the message and the keyword
#and grabs values from Table based on the ordinal value of the current
#character being pointed to be the iterator
def encrypt(self):
for i in range(len(self.message)):
mi = i
ki = i % len(self.keyWord)
self.ciphertext = self.ciphertext + self.eRetrieve(ki,mi)
def eRetrieve(self,ki,mi):
row = ord(self.message[mi]) - 32
col = ord(self.keyWord[ki]) - 32
return self.Table[row][col]
#Decryption function that iterates through both the message and the keyword
#and grabs values from Table based on the ordinal value of the current
#keyWord character being pointed to be the iterator, then traversing the
#row that corresponds to that value. While traversing that row, once there
#is a match of the message value being searched for, take the iterator value
#and convert it to an ascii character. This is the decrypted character
def decrypt(self):
self.ciphertext = ""
for i in range(len(self.message)):
emi = i
ki = i % len(self.keyWord)
self.ciphertext = self.ciphertext + self.dRetrieve(ki,emi)
def dRetrieve(self,ki,emi):
n = len(self.symbols)
whichRow = ord(self.keyWord[ki]) - 32
for i in range(n):
if self.Table[i][whichRow] == self.message[emi]:
decryptChar = chr(i + 32)
return(decryptChar)
Thank you to #Eric-Levieil for assistance

vigenere cipher - not adding correct values

I want to get specific values from a for loop to add to another string to create a vigenere cipher.
here's the code.
userinput = input('enter message')
keyword = input('enter keyword')
new = ''
for a in keyword:
pass
for i in (ord(x) for x in userinput):
if 96 < i < 123: #lowercase
new += chr(97 + (i+ord(a)-97)#keeps all values in alphabet
print(new)
so the answer i want if i do 'abcd' as my message and 'ab' as my keyword the desired outcome is 'bddf' as 'a' + 'a' is 'b' and 'b' + 'b' = 'd' and etc. how would i change the code to match my desired outcome or will i have to change it completely and how would i go about doing so.
try this (you are missing the mod 26-part):
from itertools import cycle
plaintext = input('enter message: ')
keyword = input('enter keyword: ')
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(a, b):
return int_to_chr(( chr_to_int(a) + chr_to_int(b) ) % 26 )
def vigenere(plaintext, keyword):
keystream = cycle(keyword)
ciphertext = ''
for pln, key in zip(plaintext, keystream):
ciphertext += add_chars(pln, key)
return ciphertext
ciphertext = vigenere(plaintext, keyword)
print(ciphertext)
if you like list comprehensions, you can also write
def vigenere(plaintext, keyword):
keystream = cycle(keyword)
return ''.join(add_chars(pln, key)
for pln, key in zip(plaintext, keystream))
UPDATE
updated according to the wish that a+a=b. note that z is in that case the neutral element for the addition (z+char=z).

Categories