Storing and using encryption key without user input in python - python

I am writing a script that is going to be ran as a scheduled task every morning. The program pulls encrypted usernames and passwords from a SQL Database and will need to decrypt them. My question is, is there any way for me to store the encryption/decryption key for the script to use without expecting a user input such as a password? Ideally the script should run completely autonomously.

The most flexible idea as stated by #EugeneProut would be to use env variable. I would like to extend that it also provides the best security. Then You can simply access the variable by using the code as below:
import os
print(os.environ['ENCRYPTION_KEY'])
This solution is the most production-like, since gives the best possibility to provide the key securely for example as secret.

Related

How to avoid plain text passwords in a python script?

I am going to start a new python project with web scraping, data analysis and etc... This implies making some logins in emails and data websites. I would like to know how can I avoid putting plain text password in my python scripts? Because I understand this is not very secure to have your password readable somewhere.
I have found a method using cryptography library that encrypts your password and generates a secret key that can decrypt it but I think it is not a good idea because as soon as a put the secret key in the script, someone can decrypt my password.
https://www.linkedin.com/pulse/encrypt-passwords-python-scripts-lee-rock/
Also, some people say to create a file named secret.py and stores there all passwords I need. When I have to use it, I can import this file and get the password. Consequently, this is not good too because there is a file full of readables passwords.
None of all these results were not satisfying.
In my case, I would like to share my code without leaking my passwords.

How to encrypt and decrypt passwords for selenium testing?

The context is testing of a web app with selenium while using a number of virtual user accounts we created for this very purpose. And so the testing process needs to access our sites and log-on with the virtual user's id and password.
None of these accounts are critical and they are flagged as testing accounts so no damage can be done. Still, it would probably be a good idea to encrypt the passwords and decrypt them prior to use.
If it matter, our test app is written in Python, Django and uses PostgreSQL for the database. It runs on a small Linode instance.
What might best practices be for something like this?
EDIT 1
The other thought I had was to store the credentials on a second machine and access them through and API while only allowing that access to happen from a known server's non-public IP. In other words, get two instances at Linode and create a private machine-to-machine connection within the data center.
In this scenario, access to the first machine would allow someone to potentially make requests to the second machine if they are able to de-obfuscate the API code. If someone really wants the data they can certainly get it.
We could add two factor authentication as a way to gate the tests. In other words, even if you had our unencrypted test_users table you couldn't do anything with them because of the 2FA mechanism in place just for these users.
Being that this is for testing purposes only I am starting to think the best solution might very well be to populate the test_users table with valid passwords only while running a test. We could keep the data safe elsewhere and have a script that uploads the data to the test server when we want to run a test suite. Someone with access to this table could not do thing with it because all the passwords would be invalid. In fact, we could probably use this fact to detect such a breach.
I just hate the idea of storing unencrypted passwords even if it is for test users that can't really do any damage to the actual app (their transactions being virtual).
EDIT 2
An improvement to that would be to go ahead and encrypt the data and keep it in the test server. However, every time the tests are run the system would reach out to us for the crypto key. And, perhaps, after the test is run the data is re-encrypted with a new key. A little convoluted but it would allow for encrypted passwords (and even user id's, just to make it harder) on the test server. The all-important key would be nowhere near the server and it would self-destruct after each use.
What is generally done in a case like this is to put the password through a cryptographic hash function, and store the hashed password.
To verify a login, hash the provided password and compare the calculated hash to the stored version.
The idea behind this is that it is considered impossible to reverse a good cryptographic hash function. So it doesn't matter if an attacker could read the hashed passwords.
Example in Python3:
In [1]: import hashlib
In [2]: hashlib.sha256('This is a test'.encode('utf8')).hexdigest()
Out[2]: 'c7be1ed902fb8dd4d48997c6452f5d7e509fbcdbe2808b16bcf4edce4c07d14e'
In [3]: hashlib.sha256('This is a tist'.encode('utf8')).hexdigest()
Out[3]: 'f80b4162fc28f1f67d1a566da60c6c5c165838a209e89f590986333d62162cba'
In [4]: hashlib.sha256('This is a tst.'.encode('utf8')).hexdigest()
Out[4]: '1133d07c24ef5f46196ff70026b68c4fa703d25a9f12405ff5384044db4e2adf'
(for Python2, just leave out the encode.)
As you can see, even one-letter changes lead to a big change in the hash value.

Python hashed password to use in different script?

OK, i was unable to find this same question anywhere.. So i apologize in advance if this has been asked before.
My need is to have a script ssh into other devices at different times, to do this I need to store a password. I don't want to use plain text or base64, but I would be OK with hashing the password and I have no issue doing that. The issue is I don't know how to get the hash to be sent to the devices as a password. It just sends the hash and the login gets denied.
This is the hash script that writes to a file:
import getpass, hashlib, os
pwf = open('hashes.txt', 'w')
password = getpass.getpass()
hashpass = hashlib.sha256(password).hexdigest()
pfw.write(hashpass)
This is the 2nd script that I can pull the hash out of the file, but its still a hash.
hashes = open('hashes.txt', 'r')
for pw in hashes:
passwrd = pw.strip()
password = passwrd
Thats all fine and dandy, but the I cant login with the hash.. Im sure im doing something fundamentally wrong here. please let me know.
Also i left out the other ssh code as I didnt think it was relevent.
The entire point of a cryptographic hash is that it isn't feasible to reverse it into the original password. If you need to send the actual password, a hash will not work for you; you'd need to use an actual encryption algorithm - but then you run into a similar problem of how you store the encryption key you're using to store the password.
Either way you need a way of securely storing data on your local system that other unauthorized users can't access. Typically this is done by using key-based ssh authentication and storing the key with permissions that make it inaccessible to other users. This essentially skips the unnecessary step of encrypting/decrypting a password and instead just uses the encryption key as the authentication mechanism for ssh.
Note that there exist Python libraries that are designed for the kind of task you're doing (sshing to remote systems and running commands automatically) - fabric is one of them.

How to programmatically(python) authenticate username/password using OS users

I'm writing a python program which allow user to login to it. I don't want to implement my own authentication but would rather take advantage of the OS(linux) mechanism. That is, when the user is trying to sign in my app by inputing username/password pair(which should be a valid OS user), I need to authenticate the pair by the OS. How to do that ? It may need the subprocess module, yet I've tried with no luck.
Try using PAM via Python PAM or similar
That should be possible by having your script read the /etc/passwd and /etc/shadow files, which contain details about usernames and passwords on a Linux system. Do note that the script will have to have read access to the files, which depending on the situation may or may not be possible.
Here are two good articles explaining the format of those files, which should tell you everything you need to know in order to have your script read and understand them:
Understanding /etc/passwd File Format
Understanding /etc/shadow File Format
By the way, when it talks about encrypted password, it means that it has been encrypted using the DES algorithm. You'll probably need to use pyDes or another python implementation of the DES algorithm in order for your script to create an encrypted password that it can compare to the one in /etc/shadow.

Security measures for controlling access to web-services/API

I have a webapp with some functionality that I'd like to be made accessible via an API or webservice. My problem is that I want to control where my API can be accessed from, that is, I only want the apps that I create or approve to have access to my API. The API would be a web-based REST service. My users do not login, so there is no authentication of the user. The most likely use case, and the one to work with now, is that the app will be an iOS app. The API will be coded with django/python.
Given that it is not possible to view the source-code of an iOS app (I think, correct me if I'm wrong), my initial thinking is that I could just have some secret key that is passed in as a parameter to the API. However, anyone listening in on the connection would be able to see this key and just use it from anywhere else in the world.
My next though is that I could add a prior step. Before the app gets to use API it must pass a challenge. On first request, my API will create a random phrase and encrypt it with some secret key (RSA?). The original, unencrypted phrase will be sent to the app, which must also encrypt the phrase with the same secret key and send back the encrypted text with their request. If the encryptions match up, the app gets access but if not they don't.
My question is: Does this sound like a good methodology and, if so, are there any existing libraries out there that can do these types of things? I'll be working in python server-side and objective-c client side for now.
The easiest solution would be IP whitelisting if you expect the API consumer to be requesting from the same IP all the time.
If you want to support the ability to 'authenticate' from anywhere, then you're on the right track; it would be a lot easier to share an encryption method and then requesting users send a request with an encrypted api consumer handle / password / request date. Your server decodes the encrypted value, checks the handle / password against a whitelist you control, and then verifies that the request date is within some timeframe that is valid; aka, if the request date wasnt within 1 minute ago, deny the request (that way, someone intercepts the encrypted value, it's only valid for 1 minute). The encrypted value keeps changing because the request time is changing, so the key for authentication keeps changing.
That's my take anyways.
In addition to Tejs' answer, one known way is to bind the Product ID of the OS (or another unique ID of the client machine) with a specific password that is known to the user, but not stored in the application, and use those to encrypt/decrypt messages. So for example, when you get the unique no. of the machine from the user, you supply him with password, such that they complete each other to create a seed X for RC4 for example and use it for encryption / decryption. this seed X is known to the server as well, and it also use it for encryption / decryption. I won't tell you this is the best way of course, but assuming you trust the end-user (but not necessarily any one who has access to this computer), it seems sufficient to me.
Also, a good python library for cryptography is pycrypto
On first request, my API will create a random phrase and encrypt it with some secret key (RSA?)
Read up on http://en.wikipedia.org/wiki/Digital_signature to see the whole story behind this kind of handshake.
Then read up on
http://en.wikipedia.org/wiki/Lamport_signature
And it's cousin
http://en.wikipedia.org/wiki/Hash_tree
The idea is that a signature can be used once. Compromise of the signature in your iOS code doesn't matter since it's a one-use-only key.
If you use a hash tree, you can get a number of valid signatures by building a hash tree over the iOS binary file itself. The server and the iOS app both have access to the same
file being used to generate the signatures.

Categories

Resources