Vignere Encrypt/decrypt program in Python - python

I'll get straight to the point:
I need to find a way to encrypt and decrypt a string of text using a Vigenère Cipher using Python3. I am trying to do this without downloading extra assets, but importing existing ones will be fine. A specific feature I want my program to have is that users will need to be able to enter the key they want to use inside the program itself. So far, I have managed to change letters into their values in the alphabet as well as back, but how do I do map this to the whole string while changing the key letter? Code so far:
with open("appbin/vignere.json", "rt") as vd:
vigneredict = json.load(vd)
with open("appbin/encrypt.txt", "rt") as intx:
inputtext = intx.read()
vignereword = input("Input the keyword for encrypting your text: ")
with open("appbin/vigkey.txt", "w") as kw:
kw.write(vignereword)
textlist = list(inputtext)
This code loads in the text from a file called encrypt.txt and stores it, as well as making it into a list. How do I do the actual encrypting part?

first make and store your key as a list, then Use a for loop like this
index = 0
for letter in textlist:
#blah blah
index += 1
if index > len(keylist):
index = 0
in place of blah blah put your method of converting the key and text letters to numbers (the index variable is for when you need to get the letter out of the keylist but I left that bit of the code for you to write), and add them together, subtracting 25 if the number is bigger than 25 then convert back to a letter and store in a new variable

Related

Generating Numbers/Text in certain way/form

Working on a script to generate a Key of letters/numbers in a certain way, I need to generate the key in a format like shown here xxxx-xxxx-xxxx, i would generate the key in replace of the xxxx-xxxx-xxxx like 19n3-m1m9-1nl1 but then generate this key in front of another string like Key=xxxx-xxxx-xxxx so Key=19n3-m1m9-1nl1 and loop it multiple times then save this string in a text file
If you provide more detail I'll be able to answer your question better, but here is how I would achieve what I think it is you're attempting:
1: Import relevant modules
import random, string
2: Generate random string of 16 letters / digits. Note this will not evenly distribute numbers/letters throughout the key like the example you gave - please let me know if this is a requirement.
key = ''.join(random.choices(string.ascii_lowercase + string.digits, k=16))
3: "Join" groups of 4 characters with a dash.
key = '-'.join([key[:4], key[4:8], key[8:12], key[12:16]])
4: Lastly, add "Key=" to the start of the string:
key = "Key=" + key
5: Example output:
'Key=ed2o-kn7o-jyif-18wo'
You can save this to a text file using:
text_file = open("keys.txt", "w")
text_file.write(key)
text_file.close()

why does my if elif loop fail to consistently find string in data

My code is reading urls from a csv file, doing a GET on their content, parsing the response, and writing output to a second csv. If a keyword is found, I need it to output certain data; if not found, it should output a subset of that data. In other words, not all columns of the csv file would be populated in all cases.
My 4 row test file is constructed so that the keyword is missing in the first iteration, present in the second, missing in third, present in last.The code below will find the keyword and populate the csv correctly the first time it iterates through, but it doesn't find it in the last instance. I can't figure out what is wrong with my if/elif loop:
counter = 0
for row in list_reader:
key_id = row['keyId']
ex_id = row['key']
get_response = key.get_item(row['keyId'])
#get_item is a method from the imported Client
length = (get_response['length'])
word = (get_response['transcript']['words'][0]['w'])
if word != "[keyword1]" and word != "[keyword2]":
print "other",counter
results_writer.writerow([key_id,ex_id,length])
elif word == "[keyword1]":
print word, counter
x = (get_response['value1'])
y = (get_response['value2'])
counter = counter + 1
results_writer.writerow([key_id,ex_id,length,x,y])
With this the output from the terminal is:
other 0
[PCI] 0
other 1
other 1
If it were working properly, the last "other" would be another "[PCI]". It populates the csv file accordingly the first time, but after that it populates as if the keyword never appears again.
How can I fix the loop so it iterates successfully to find the keyword after the first time?
(Posted on behalf of the question author).
I found the problem. It happened that [PCI] was the first word in the 2nd instance. My word variable only would find the first word. So in the other instance, since it wasn't the first word, it didn't trigger.

Python dictionary attack only solves the last hash

I'm trying to build a dictionary attack script (for education purposes) using Python and it only ever solves the last SHA-256 hash in my file.
The logic is as follows:
Read a file containing words
Store the hashed value of the word along with the word as a key-value pair in a dictionary
Scan the lines of a text file containing SHA-256 hashes (1 hashed value per line)
Iterate over the items in the dictionary and print the key if a value matches the hash
It works perfectly for the very last item in my file, but says a match was not found for all my others.
My hash file looks like:
9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08
5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8
Containing the hashed values for "test" and "password".
My word file contains over 70,000 words and I've made sure both words are in the file, and when I debug, they both have values in the dictionary if I call the expression.
Here's where I iterate over the hashes in my file:
with open(hashFile) as f:
for c in f:
findMatch(str(c).lower(),wordMap)
And the function I wrote to compare a hashed value to every value in the dictionary:
def findMatch(hv,m):
#k is the key, m is the dictionary
for k in m:
if(m[k].lower() == hv):
print("Match was found: " + k )
return
print("Match was not found, searched through " + str(len(wordMap)) + " words")
Any help is appreciated, thanks!
In findMatch(str(c).lower(),wordMap), there is no need to call str() (because c is already a string), but there is a need to strip off the trailing newline character: findMatch(c.strip().lower(),wordMap). Otherwise, it is included in the hash value calculation. Apparently the last line of your file does not have the trailing newline, that's why it is correctly recognized.

Can I use range for a list filled with words?

I wanted to make a password guesser in Python, so I thought I could use the method in the code below. I'm new to Python so I don't really know what I'm doing.
In the code, I had a file containing 109538 words from a dictionary read, and now its a list.
For the code to work, the range needs to be set to the list "DictionaryWords", which consists of all the words in the dictionary as a list.
#I made this to open file and read it
dictfile = open('c:/ScienceFairDictionaryFolder/wordsEn.txt', 'r')
DictionaryWords = dictfile.readlines()
Password = "Cat"
for x in range(0, 109538):
if x is Password:
print(x, "Found it!")
else:
print("Nope! Not here!")
Is it possible, or does range only work for lists consisting of integers?

Looping a write command to output many different indices from a list separately in Python

Im trying to get an output like:
KPLR003222854-2009131105131
in a text file. The way I am attempting to derive that output is as such:
with open('Processed_Data.txt', 'r') as file_P, open('KIC_list.txt', 'w') as namelist:
nameData = []
for line in file_P:
splt_file_P = line.split()
nameData.append(splt_file_P[0])
for key in nameData:
namelist.write('\n' 'KPLR00' + "".join(str(w) for w in nameData) + '-2009131105131')
However I am having an issue in that the numbers in the nameData array are all appearing at once in the specified output, instead of using on ID cleanly as shown above the output is something like this:
KPLR00322285472138721382172198371823798123781923781237819237894676472634973256279234987-2009131105131
So my question is how do I loop the write command in a way that will allow me to get each separate ID (each has a specific index value, but there are over 150) to be properly outputted.
EDIT:
Also, some of the ID's in the list are not the same length, so I wanted to add 0's to the front of the 'key' to make them all equal 9 digits. I cheated this by adding the 0's into the KPLR in quotes but not all of the ID's need just two 0's. The question is, could I add 0's between KPLR and the key in any way to match the 9-digit format?
Your code looks like it's working as one would expect: "".join(str(w) for w in nameData) makes a string composed of the concatenation of every item in nameData.
Chances are you want;
for key in nameData:
namelist.write('\n' 'KPLR00' + key + '-2009131105131')
Or even better:
for key in nameData:
namelist.write('\nKPLR%09i-2009131105131'%int(key)) #no string concatenation
String concatenation tends to be slower, and if you're not only operating on strings, will involve explicit calls to str. Here's a pair of ideone snippets showing the difference: http://ideone.com/RR5RnL and http://ideone.com/VH2gzx
Also, the above form with the format string '%09i' will pad with 0s to make the number up to 9 digits. Because the format is '%i', I've added an explicit conversion to int. See here for full details: http://docs.python.org/2/library/stdtypes.html#string-formatting-operations
Finally, here's a single line version (excepting the with statement, which you should of course keep):
namelist.write("\n".join("KPLR%09i-2009131105131"%int(line.split()[0]) for line in file_P))
You can change this:
"".join(str(w) for w in nameData)
to this:
",".join(str(w) for w in nameData)
Basically, the "," will comma delimit the elements in your nameData list. If you use "", then there will be nothing to separate the elements, so they appear all at once. You can change the delimiter to suit your needs.
Just for kicks:
with open('Processed_Data.txt', 'r') as file_P, open('KIC_list.txt', 'w') as namelist:
nameData = [line.split()[0] for line in file_P]
namelist.write("\n".join("KPLR00" + str(key) + '-2009131105131' for key in nameData))
I think that will work, but I haven't tested it. You can make it even smaller/uglier by not using nameData at all, and just use that list comprehension right in its place.

Categories

Resources