Python Forum
Searching for items within a list
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Searching for items within a list
#1
For a project for a coding class I'm taking, we've been told to complete the code for an encrypted password saver. For part of this, I need to search for a password within a list of passwords based on the website associated with the password, then print the password. The passwords are saved in the list as follows:

passwords = [["yahoo","XqffoZeo"],["google","CoIushujSetu"]]
Essentially, it's a list filled with lists, organized [website, password].

Originally, I set out to do this via linear search. This is the code I'm using for that:

def linsearch(myItem, myList):
   found = False
   position = 0
   while position < len(myList) and not found:
       if myList[position] == myItem:
           found = True
       position = position +1
   return found
The problem being that whenever I call linsearch, it always returns "false." I assume this is because I'm searching an encrypted list. How could I decrypt the list, search it, print the password, and then encrypt it again? I'm having a hard time figuring it out.

The full code is below. Anything in between "YOUR CODE HERE" or "MY CODE" comments is my own code, the rest was provided by the instructor.

import csv
import sys

#The password list - We start with it populated for testing purposes
passwords = [["yahoo","XqffoZeo"],["google","CoIushujSetu"]]


#The password file name to store the passwords to
passwordFileName = "samplePasswordFile"

#The encryption key for the caesar cypher
encryptionKey=16

#Caesar Cypher Encryption
def passwordEncrypt (unencryptedMessage, key):

   #We will start with an empty string as our encryptedMessage
   encryptedMessage = ''

   #For each symbol in the unencryptedMessage we will add an encrypted symbol into the encryptedMessage
   for symbol in unencryptedMessage:
       if symbol.isalpha():
           num = ord(symbol)
           num += key

           if symbol.isupper():
               if num > ord('Z'):
                   num -= 26
               elif num < ord('A'):
                   num += 26
           elif symbol.islower():
               if num > ord('z'):
                   num -= 26
               elif num < ord('a'):
                   num += 26

           encryptedMessage += chr(num)
       else:
           encryptedMessage += symbol

   return encryptedMessage

#load password from file
def loadPasswordFile(fileName):

   with open(fileName, newline='') as csvfile:
       passwordreader = csv.reader(csvfile)
       passwordList = list(passwordreader)

   return passwordList

#save password to file
def savePasswordFile(passwordList, fileName):

   with open(fileName, 'w+', newline='') as csvfile:
       passwordwriter = csv.writer(csvfile)
       passwordwriter.writerows(passwordList)

# The below section of code is a function that performs a linear search when called
##### my code #####
def linsearch(myItem, myList):
   found = False
   position = 0
   while position < len(myList) and not found:
       if myList[position] == myItem:
           found = True
       position = position +1
   return found
##### my code #####

#menu
while True:
   print("What would you like to do:")
   print(" 1. Open password file")
   print(" 2. Lookup a password")
   print(" 3. Add a password")
   print(" 4. Save password file")
   print(" 5. Print the encrypted password list (for testing)")
   print(" 6. Quit program")
   print("Please enter a number (1-4)")
   choice = input()

   if(choice == '1'): #Load the password list from a file
       passwords = loadPasswordFile(passwordFileName)
   if(choice == '2'): #Lookup at password
       print("Which website do you want to lookup the password for?")
       for keyvalue in passwords:
           print(keyvalue[0])
       passwordToLookup = input()

       ####### YOUR CODE HERE ######
       print(linsearch(int(passwordToLookup), passwords))
       ####### YOUR CODE HERE ######


   if(choice == '3'):
       print("What website is this password for?")
       website = input()
       print("What is the password?")
       unencryptedPassword = input()

       ####### YOUR CODE HERE ######
       encryptedPassword = passwordEncrypt(unencryptedPassword, encryptionKey)
       newPassword = [website, encryptedPassword]
       passwords.append(newPassword)
       ####### YOUR CODE HERE ######

   if(choice == '4'): #Save the passwords to a file
           savePasswordFile(passwords,passwordFileName)


   if(choice == '5'): #print out the password list
       for keyvalue in passwords:
           print(', '.join(keyvalue))

   if(choice == '6'):  #quit our program
       sys.exit()

   print()
   print()
Reply
#2
It's almost always better to iterate directly over the items in a list, rather than over the indexes of the list:

for pass in pass_list:
    if pass[0] == search_user:
        found = pass[1]
        break
Note that pass is a list of two items, so I'm grabbing the first item in that sub-list with the zero index. You can also use tuple assignment to make it even easier:

for user, pass in pass_list:
    if user == search_user:
        found = pass
        break
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
Different solution:

passwords = [["yahoo","XqffoZeo"],["google","CoIushujSetu"]]
pwdict = dict(passwords)
# {'google': 'CoIushujSetu', 'yahoo': 'XqffoZeo'}
Then you've some userinput as example data:

username_1 = 'yahoo'
password_1 = 'XqffoZeo'

username_2 = 'yahoo'
password_2 = 'wrong_password'

username_3 = 'no_user'
password_3 = 'some_password'
Before you have to do input validation.
No empty usernames and no empty passwords!
Additionally you should never save clear text passwords
Use sha-256 hash with salt for it or better pbkdf2
https://docs.python.org/3/library/hashli...derivation

You should take a look into: https://docs.python.org/3.6/library/stdt...types-dict
The dict has a get method which can return a default value, if the key doesn't exist.
I'm using in this case an empty string as a default value. But again, validating inputs is very important.
When you don't do this and someone sends an empty password with, you've a big problem with this approach.

pwdict.get(username_1, '') == password_1 # returns True
pwdict.get(username_2, '') == password_2 # returns False
pwdict.get(username_3, '') == password_3 # returns False
Dicts are very fast in lookup because they are like hash tables.

I <3 dicts. If i clould change the law, I'll marry them.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#4
(Jun-20-2017, 10:21 PM)ichabod801 Wrote: It's almost always better to iterate directly over the items in a list, rather than over the indexes of the list:

for pass in pass_list:
    if pass[0] == search_user:
        found = pass[1]
        break
Note that pass is a list of two items, so I'm grabbing the first item in that sub-list with the zero index. You can also use tuple assignment to make it even easier:

for user, pass in pass_list:
    if user == search_user:
        found = pass
        break

I'm still very new. If you don't mind explaining a little more closely, how exactly does this work? I don't understand how I would be able to print the password based on this code.
Reply
#5
Well, now that I look at it, I shouldn't have used pass as a variable name. That's a statement in Python, very bad move. First, iterating over a list:

knights = ['Arthur', 'Bedevere', 'Robin', 'Lancelot', 'Galahad']
for knight in knights:
    print(knight)
Each time through the loop, it will take one knight's name out of the loop, assign it to the knight variable, and then print that variable. Second, tuple assignment:

Output:
>>> knight, steed = ['Lancelot', 'Concorde'] >>> knight 'Lancelot' >>> steed 'Concorde'
If you have an iterable, like ['Lancelot', 'Concord'], you can assign each item in it to a different variable by putting a list of variables on the left side of the assignment. Since the for loop is doing an assignment to the loop variable each time through the loop, you can use it there as well.

So the first time through the second loop I give, user will be equal to the first item in the first sub-list. In your example, it would be equal to 'yahoo'. The variable pass (let's pretend I wasn't an idiot, and the variable was passwd instead) would be equal to the second item in the first sub-list. In your example it would be equal to 'XqffoZeo'. If 'yahoo' is what you are looking for, it will store 'XqffoZeo' in the found variable, and break out of the loop. If 'yahoo' isn't what you are looking for, it will grab the second sub-list in the pass_list, assign those to values to the user and passwd variables, and check again.

At the end you have the found variable, which you can print or return or whatever.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#6
Okay, I think I understand now. What does search_user reference, though? What would the equivalent be in my code?
Reply
#7
Oh, first of all, pass is a statement and can not be used as a variable name.
You should first learn the language. There are many good tutorials.
Additional you should play inside the python repl to understand the code better.
Do small steps.
The code example is really bad. Here with different variable names.

username_password_list = [["yahoo","XqffoZeo"],["google","CoIushujSetu"]]
user_you_seek = 'yahoo'
for username, password in username_password_list:
    # simple unpacking of the two elements to username and password
    if username == user_you_seek:
        password_of_user = password
        break
  • When you use index access
    username_password_list[0]
    what do you see?
  • What does break do in a loop?
  • What happens, when the user is not inside the nested list? Do you think it's a good approach?
  • Bonus question: What happens when the same user is twice in the list?
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#8
(Jun-21-2017, 01:00 AM)Yobby Wrote: What does search_user reference, though? What would the equivalent be in my code?

In your linsearch function, it would be myItem.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#9
(Jun-21-2017, 01:31 AM)ichabod801 Wrote:
(Jun-21-2017, 01:00 AM)Yobby Wrote: What does search_user reference, though? What would the equivalent be in my code?

In your linsearch function, it would be myItem.

Okay, thanks. I have it working perfectly now.
Reply
#10
This assignment is awful. Do you have an email address for the professor? I'd love to educate them on proper password usage.

Cliff notes:
- don't store passwords
- don't store encrypted passwords
- don't encrypt passwords
- don't print passwords
- use one-way hashing

The only legitimate use of storing passwords that can be decrypted is for a password manager, and even in that case, caesar is the wrong cipher to use. You'd need to use something that's actually cryptographically sound, like aes. Given an "encrypted" output from a caesar cipher, you can trivially find out what the original input is, meaning it's not really encrypted at all. It's only really useful if you want to physically write something down and for an acquaintance to be able to "decrypt" it with only needing a piece of paper and pen(cil).

"It's just a homework assignment" is also not a valid excuse for this nonsensical shit, either. Using words like "encryption" and "cipher" will make students believe that this is how things are Really Done, so after they're done with the class, they'll go and Really Do it out in the wild. If you want a toy assignment that doesn't cause future security issues, maybe just make a cron-like alarm that soft-encrypts the alert messages?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to parse and group hierarchical list items from an unindented string in Python? ann23fr 0 185 Mar-27-2024, 01:16 PM
Last Post: ann23fr
  Why do I have to repeat items in list slices in order to make this work? Pythonica 7 1,327 May-22-2023, 10:39 PM
Last Post: ICanIBB
  Finding combinations of list of items (30 or so) LynnS 1 876 Jan-25-2023, 02:57 PM
Last Post: deanhystad
  For Word, Count in List (Counts.Items()) new_coder_231013 6 2,593 Jul-21-2022, 02:51 PM
Last Post: new_coder_231013
  How to get list of exactly 10 items? Mark17 1 2,518 May-26-2022, 01:37 PM
Last Post: Mark17
  how to assign items from a list to a dictionary CompleteNewb 3 1,580 Mar-19-2022, 01:25 AM
Last Post: deanhystad
  Searching in the list quest 4 1,533 Mar-02-2022, 10:30 AM
Last Post: quest
  Reading list items without brackets and quotes jesse68 6 4,632 Jan-14-2022, 07:07 PM
Last Post: jesse68
Question How to gather specific second-level items from a list chatguy 2 1,546 Dec-17-2021, 05:05 PM
Last Post: chatguy
  deleting select items from a list Skaperen 13 4,535 Oct-11-2021, 01:02 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020