Reputation: 140457
For an automation project, I have to persist user id/password to allow my scripts to connect to a remote service.
My idea is to use the keyring module to achieve some better level of security; but as not all platforms support keyring; I am looking into storing credentials into a flat file, too. I created a "Credentials" class; and figured that using pickle
I could just dump/load objects of that class, like:
def _store_to_file(credentials):
from pickle import dump
pkl = open('whatever.dat', 'wb')
dump(credentials, pkl)
pkl.close()
Unfortunately, this file gives away the password in plain text:
S'_password'
p6
S'bla'
I understand that file, stored by a local script isn't offering real security. But I was hoping to at least get to a point where one would need more than a simple "less whatever.dat" to acquire that password text.
I had hoped that pickle has some kind of "scramble" mode; but couldn't find anything. Am I overlooking something?
Alternatively: is there another way to persist my objects that easily, but not that "easy human readable"?
Upvotes: 2
Views: 1750
Reputation: 148965
You should not.
The problem in applications that try to keep a safely encrypted copy of a key is just that they need another key to decrypt it. It could be encrypted too by would need still another key. It could... (sorry joking :-) ). It only makes sense when you have to store multiple secrets, because you unlock the secure vault with one single password - what keyring and password managers do...
For one single password, the correct and portable way is to rely on the OS to provide a secure folder. Both Linux (and Unix-like) and provide either access control rules (only accessible to user), or encrypted folders if you need better security. Just document it and respect the single responsibility principle.
Upvotes: 1
Reputation: 140457
A simple solution; based on the comment by Keef Baker --- using AES encryption to scramble on password/username; like this:
class Credentials(object):
def __init__(self, user, password):
self._user = aes.encrypt(user)
self._password = aes.encrypt(password)
@property
def user(self):
return aes.decrypt(self._user)
@property
def password(self):
return aes.decrypt(self._password)
from Crypto.Cipher import AES
aes = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
Upvotes: 3