How do I add files in a dictionary? - python

I am creating a small system where the person can login with a username and a password. The code would then check the text file that contains the username and the password on the same line.
I have no idea how to make this work thought. How come it is so complicated to create a simple login system based off of a text file with the details in it? I believe that it is my philosophy that is wrong and not the actual code.
I have used various codes like the following:
with open('users/users.txt') as f:
{int(k): v for line in f for (k, v) in (line.strip().split(None, 1),)}
Which come to no use. What am I doing wrong?

I'm assuming you have a text file that's laid out like so:
username1 password1
username2 password2
...
From what I gathered from your question, you wish to parse this file and store the results in a dictionary (i.e. username key maps to password value). This sort of stuff is more appropriately stored in a database (SQLite is built-in to Python, for instance), so you should definitely look into learning about databases rather than using a plain text file for data storage, especially user accounts.
Also, you should think about how you should store sensitive information like passwords using techniques such as hashing, but that's something you can think about when you want to make the next step (I'm under the assumption this is a small learning project, so concepts like databases and hashing might be beyond your current scope, but they are absolutely worth learning).
As for your question, you could think about doing something like the following:
accounts = dict()
with open('users.txt') as f:
for account in f:
(usr, pwd) = account.strip().split()
accounts[usr] = pwd
print(accounts)
I think code clarity is more important than keeping it all in one line! The code that I have shown isn't exhaustive, more like a guideline. As I said before, I don't recommend you go this route, so definitely look into databases and proper password storing techniques!
What you could do in the mean time to ensure some form of security is to store the password as a hash (i.e. pwd would be a hash). Then when the user passes the password to the system you can calculate the hash and check if the hashes are equal. This would be better than dealing with plain text passwords. Python has a built-in module for hashing called hashlib. I'm not an expert on hashing, but this would be a decent starting point.

Related

Is it possible to make a program that can read from a file, but you can't open the file from outside the program?

Basically, I have built a login system.
The first time that a user uses the login system, a text file is created and the username and password are saved there when the user uses a "remember password?" function.
The second time the software uses the system, the system already has the user and password typed in if the user previously used the "remember password?" function.
The thing is, the text file where the password and user are stored can be accessed by simply just going to folder and double clicking on it, which is awful for security reasons.
Is it possible to make it so that the text file can't be accessed outside the program?
It's not possible, as long as you are storing data on your disk, the data will always be readable.
Actuall when you uses .txt, it means that you want it to be readable to others. If you are looking for security, you have to encode your content(Account & Password) to something else that only your program can read.
something similar to chaning 'A' to 'B', '1' to '0', '0' to '7'.....
or another approach used by modern Login Sytem: Hashing your Password
Basically, there isn't a way to securely store a password in clear in a file in the file system.
You can arrange things so that a file can only be read by a specific account on the system. However, someone with admin privilege will (probably) be able to do things that will give themselves access. And there will most likely be other ways to break file system security in some circumstances.
The ideal solution is to NOT store the password. Even storing it encrypted with a private key is a bad idea.
Creating and storing a "salted hash" of a password can be secure ... provided that there is no way that a "bad guy" can capture the password characters before they have been hashed, but I don't think that is going to help you here ... since you apparently need to be able to recover the actual password.
Maybe the best approach would be to investigate "password safe" or "key chain" products that are provided by the client's OS or web browser. Unfortunately, this is going to be platform specific.
You could also just "hide" the file containing the password, or (reversibly) obscure the password. But this is insecure. It can easily be defeated by reverse engineering the steps that your code is taking to hide the password.

Is it safe to hash a password two separate times with two separate salts and save both hashes on the same server

I hope I didn't create a duplicate question.
I tried to look for already existing questions, but I didn't find anything.
I have successfully set up a database with username, salt and hashed password for logging in.
For checking the password, I compare the generated hash with the one of the database, see code below.
password_hashed_from_user = res[0][0]
salt = res[0][1]
key_generated = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), base64.b64decode(salt.encode('utf-8')), 100000, dklen=128)
key_encoded = base64.b64encode(key_generated).decode('utf-8')
if key_encoded != password_hashed_from_user:
logging.debug("Password was wrong:\n{}\n{}".format(key_encoded, password_hashed_from_user))
return "Username and/or password incorrect", False
The problem now is that I want the user to be able to act completely anonymously, which means I want the user to be able to use a generated token for identification, which cannot be traced back to his account.
Therefore I would need to store the token in a separate table, not correlated to the one with the credentials.
In order for the user to not be able to cheat and just ask the server for a new token every time he logs in (and therefore act as a new user), I wanted to compute the token based on the credentials.
So I figured, I could just have a separate salt and create a new hash based on the password (with the same method as in the code example).
Since the password itself is not stored on the server, this hash could not be generated without the password of the user itself.
This way, the generated token is always the same, as long as the salt doesn't change.
So I can make sure that a specific user is always identified as the same one, while the user can make sure that I cannot trace back his actions.
Background
The background is that I need to create a voting environment, where people have to register and identify themselves in order to prevent double voting, but the vote results, as well as the participation etc should not be traced back to the specific user.
As this is a project in my studies, I cannot just use existing frameworks/libraries.
Now my question:
Is it safe to store two separate hashes of the same password with different salts on the same server or would the duplication make it feasible to recreate the actual password? Both salts would be stored together, together with one of the hashes. The other hash would be in a separate, unrelated table.
I always struggled a bit with encryption on that level.
Is it safe to store two separate hashes of the same password with different salts on the same server or would the duplication make it feasible to recreate the actual password?
Yes, it is safe.
The basic idea behind that statement is that the salt "injects" sufficient uniqueness into the process that the password hash can work with to ensure that two different salts yield unrelated-looking hashes. A real-world example of this would be the worry of two different users having the same password (but different salts) - which also doesn't leak anything about the password and was one of the main motivations to introduce salts.
The more cryptographic argument is either you assume your hash acts like a random oracle - which yields unrelated random ouputs for unique inputs - in which case the uniqueness of the salt hides all output. Or you use a weaker assumption that your password hash is a randomness extractor combined with a pseudo-random function (not unreasonable for a cryptographic hash-based password-hash) with the key in the password input. In that case assuming the password is unknown and sufficiently random all unique salts will be mapped to strings that are indistinguishable from random output and therefore cannot yield any information about the output.
Alternatively you can also use Bellare, Ristenpart and Tessaro's definition for password hashing security which essentially says "breaking a password hash is as hard as guessing the password if said hash is good".

Creating an encrypted file containing various credentials with Python

I am working on a program, written in Python 3, for work to automate a number of tasks we do. Currently the tasks are each their own program, but I intend to eventually move them all together under a unified interface (thinking of using prompt-toolkit). My current solution for credentials is just a creds.toml file and each of the needed credentials are stored within it:
[db_name]
user = "me"
pass = "changeme!"
What I'd like to do is maintain the dictionary interface my credentials have, but store those passwords in an encrypted file. Eventually I'd like to have it so that credentials are added through my program so no one needs to interact with the program at all. I think this would be the best for users as we have a mix of sysadmin on my team and not all are too comfortable with CLIs and interacting with text files (silly Windows people ;) ).
What would be my best option for this? I am mostly concerned with accidentally viewing one another's credentials more than I am concerned with anything else. This will be used in a NOC so shifts share the same consoles and would have access to one another's file. It's pretty common to have to go into someone else's home dir to grab a script they wrote or to pick up something they didn't complete on their shift.
Ideally my workflow would be:
s_creds = decrypt(file)
creds = pickle.load(s_data)
session = Database(creds['db_name']
And the Database class would contain:
def __init__(self, cred):
...
self.user = cred['user']
self.pass = cred['pass']
...
I had initially thought that the file would be a toml file that was just encrypted. But it would make more sense to skip that and just serialize a dictionary.
Not too concerned with licenses, but I prefer not GPLv3 because of the hoops.
While editing one of the very first utils I created for this project I stumbled upon my initial credential storage method, keyring. This package allows for storing passwords on the local machine's keyring, in memory, or in an encrypted file (with use of another package, keyring.cryptfile). It will require reworking some stuff, though, as the credentials are not in a dictionary, but in an object.
Using keyring works something like:
>> import keyring
>> svc = 'service_name'
>> usr = 'username'
>> pass = 'qwerty'
>> keyring.set_password(svc, usr, pass)
>> credentials = keyring.get_credential(svc, usr)
>> credentials._username
'username'
>> credentials._password
'qwerty'
I will then be able to make this much more secure than even an encrypted textfile, by letting the OS handle the actual handling of the credentials. This seems like a good solution, while I can say "the passwords don't matter, no one will see them other than people who already have access to the same resources" that's wishful thinking and I should be more security minded with the proverbial "keys to the kingdom".

django filter with icontains doesn't work [duplicate]

I have the following model that has a first_name field.
from django.db import models
from encrypted_fields import EncryptedCharField
class Customer(models.Model):
first_name = EncryptedCharField(max_len=30)
I use django-encrypted-fields to encrypt the data stored in my db. As of this ( I think ) I am not able to filter results.
I want to do this:
customers = Customer.objects.all().filter(first_name__icontains="George") #George exists as customer
but I get an empty list. Is there a way I can go round that?
This isn't possible, by design. The data stored in the database is an opaque blob, so even if the plaintext you set the field to contains "George", that text isn't in the database.
The idea regarding encrypting the data again and comparing the stored database value against that is an interesting one, but it still won't work. The data is encrypted with a random initialization vector, so you can't simply reproduce the results.
Possible solution
You may be able to work around the problem with hashing though. For example, if your user provides an email and password for authentication, but you want the email to be stored encrypted in your database, you could store a hashed version of the email in addition to the encrypted one. Then you can reproduce the hash and query against that, and only decrypt the email once you've found your user.
It is not immediately possible because the data stored in the underlying database is a cipher text in binary format. To support this, you'd need searchable fields like Kevin mentioned above, however those are very slow in large production use-cases, as they require decryption prior to executing the search.
Also note that django-encrypted-fields is deprecated, as it makes use of Google Keyczar which has been abandoned in favor of Google Tink. I ended up in the same situation and created https://github.com/script3r/django-tink-fields to address my needs.
For some cases the solution/workaround might be to compare in Python instead of using the Django ORM, so instead of:
return BlockedIP.objects.filter(ip_address=ip_address).exists()
Do something like this:
return ip_address in BlockedIP.objects.values_list('ip_address', flat=True)
Note that this might very well not be efficient if you have a lot of records.
Yes, you can do it with django-searchable-encrypted fields with a handful of caveats:
You need to add fields that are searchable, on top of which ones are encrypted yourself
Updates don't work properly, you need to update both the encrypted field and the searchable field
Adding a searchable field after means you need to iterate over your objects and set the value to itself (don't quote me on this, but that's the way it appears).
https://pypi.org/project/django-searchable-encrypted-fields/

Authenticating on Web.py - will this code be unsafe for production?

I am making a simple web-app which requires login for the admin page. I came across this incantation on the web.py site (http://webpy.org/cookbook/userauth) :
import hashlib
import web
def POST(self):
i = web.input()
authdb = sqlite3.connect('users.db')
pwdhash = hashlib.md5(i.password).hexdigest()
check = authdb.execute('select * from users where username=? and password=?', (i.username, pwdhash))
if check:
session.loggedin = True
session.username = i.username
raise web.seeother('/results')
else: return render.base("Those login details don't work.")
However the page also gives a somewhat ominous warning: "Do not use this code on real site - this is only for illustration.". I was wondering if there are any major holes in this, I'm somewhat unfamiliar with web-programming so just wanted to make sure that using this code wont unwittingly make the app open to trivial attack vectors?
Many thanks
select * from users where username=? and password=?', (i.username, pwdhash)
^ SQL injection, broseph. If someone does 'or 1=1' into the search field, they'll get the first result in users because of the SELECT * from. Often the first entry is the admin credentials.
The only glaringly obvious problem I see is that the password is stored with as simple MD5 hash with no salt. From your point of view, this isn't so much of an issue, but from the user's point of view it's a major security flaw since someone with access to the database can fairly easily crack sufficiently bad passwords by just googling their MD5 hashes.
The only possible problem I can think of here, could be if it would somehow be possible to exploit MD5 collisions, i.e. that two different strings can generate the same MD5 hash - in that case someone could potentially log in with a password that is not correct, but generates the same MD5 hash.
Changing to a better hashing algorithm such as SHA-1 (or something else available in hashlib) would close this potential security problem.
As far as I know, it would be very difficult to exploit the MD5 collision problem to gain access. Even so, it is broken, and quoting security guru Bruce Schneier from the wikipedia article:
[he] wrote of the attack that "[w]e already knew that MD5 is a broken hash function" and that "no one should be using MD5 anymore."

Categories