109

I am looking for a way to securely store passwords which I intend to use in some Python scripting. I will be logging into different things and I don't want to store the passwords as plaintext in the script itself.

Instead I was wondering if there is anything which is able to securely store those passwords and then retrieve them using something like a master password which I could enter to the script at the beginning.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
user1598386
  • 1,103
  • 2
  • 9
  • 5
  • 5
    You can store the passwords in a text (e.g. JSON) file encrypted with GPG, then have your script run GPG to decrypt it every time it is run. – Dietrich Epp Aug 20 '12 at 18:29
  • **See also**: http://stackoverflow.com/questions/157938 – dreftymac May 01 '17 at 20:39
  • 1
    @DietrichEpp, that would require the script to have the GPG decryption secret. Since the script can easily be parsed, an attacker could recover the GPG secret and then recover your passwords. – chessofnerd Oct 03 '19 at 21:21
  • @chessofnerd: No, that is not true. It is not required to store the decryption secret in the script. Instead you can have GPG prompt the user for a password, or you can use an agent running in the background. – Dietrich Epp Oct 04 '19 at 14:12
  • the other link is also closed, this is also closed for answers. I've found a better way to manage pws using `pycryptodomex`. Where do I post it? – Nikhil VJ Aug 28 '21 at 15:39

3 Answers3

51

Know the master key yourself. Don't hard code it.

Use py-bcrypt (bcrypt), powerful hashing technique to generate a password yourself.

Basically you can do this (an idea...)

import bcrypt
from getpass import getpass
master_secret_key = getpass('tell me the master secret key you are going to use')
salt = bcrypt.gensalt()
combo_password = raw_password + salt + master_secret_key
hashed_password = bcrypt.hashpw(combo_password, salt)

save salt and hashed password somewhere so whenever you need to use the password, you are reading the encrypted password, and test against the raw password you are entering again.

This is basically how login should work these days.

ZF007
  • 3,708
  • 8
  • 29
  • 48
CppLearner
  • 16,273
  • 32
  • 108
  • 163
  • @Dougal ah nice. I didn't even remember that. Yeah. – CppLearner Aug 21 '12 at 01:52
  • 23
    `raw_password` is undefined in your example. what does it reference? – BCR Oct 05 '16 at 18:42
  • 9
    I really don't see how to use this? I imagine that `raw_password` is the password that initially should be stored and that the user wants to fetch this using `master_secret_key` and `salt`. But you state that one has to read the hashed password and test against `raw_password`, but `raw_password` are unknown!? Question is: how to extract `raw_password` given `master_secret_key` and `salt`? – mr.bjerre Sep 12 '17 at 10:54
  • 36
    This really did not answer the OP question. This answer is not for storing a password for retrieval... this answer is for checking a password someone is entering in your script. The OP wants (as do I) an answer on how to store AND RETRIVE a password. For instance, I want to securely store my Gmail password for use by my script... –  Dec 24 '17 at 22:16
  • 3
    This is still good practice and safe in 2020. – Chris Fowl Apr 12 '20 at 15:19
  • 5
    In the event that someone else comes across this in >= 2020, I made a gist with a more complete/correct example here: https://gist.github.com/JacobJerrell/6a5dd5296aff378557a13efa36b3870d – Jacob J Sep 15 '20 at 03:16
22

I typically have a secrets.py that is stored separately from my other python scripts and is not under version control. Then whenever required, you can do from secrets import <required_pwd_var>. This way you can rely on the operating systems in-built file security system without re-inventing your own.

Using Base64 encoding/decoding is also another way to obfuscate the password though not completely secure

More here - Hiding a password in a python script (insecure obfuscation only)

Community
  • 1
  • 1
Pratik Mandrekar
  • 9,362
  • 4
  • 45
  • 65
  • 51
    Base64 encoding passwords is never a good idea. It only gives an illusion of security. Just don't do it. https://paragonie.com/blog/2015/08/you-wouldnt-base64-a-password-cryptography-decoded – mb. Oct 07 '15 at 03:45
  • 7
    Depends on whether you are protecting against a low tech or high tech attack. No point over engineering at times. – Pratik Mandrekar Oct 07 '15 at 06:53
  • Wouldn't this require anyone using the script to create their own `secrets.py`? – Stevoisiak Nov 07 '17 at 14:53
  • 2
    I produce only small Python scripts (tools) and store them in our company git server. I use this solution too but I didn't want to push all the passwords into the git. So my `secrets.py` is stored only locally. The version pushed to git is only an empty template with no real password. – CraZ Jun 06 '18 at 07:03
  • @Stevoisiak, yes. That is correct. One thing I do is store sensitive data in a config file that can be used by [Config Parser](https://docs.python.org/2/library/configparser.html). The config file lives alongside the program so the program always know where to find it. That way my user can muck around in a config file instead of muck around in a python file (which might be a little easier for them). – chessofnerd Oct 03 '19 at 21:19
  • Thank you, I will use this to store the secrets in windows desktop and let the scripts access it from any drive so that the script which is accessible to many (in my case) does not have a password stored. – surpavan Dec 30 '19 at 08:52
13

the secure way is encrypt your sensitive data by AES and the encryption key is derivation by password-based key derivation function (PBE), the master password used to encrypt/decrypt the encrypt key for AES.

master password -> secure key-> encrypt data by the key

You can use pbkdf2

from PBKDF2 import PBKDF2
from Crypto.Cipher import AES
import os
salt = os.urandom(8)    # 64-bit salt
key = PBKDF2("This passphrase is a secret.", salt).read(32) # 256-bit key
iv = os.urandom(16)     # 128-bit IV
cipher = AES.new(key, AES.MODE_CBC, iv)

make sure to store the salt/iv/passphrase , and decrypt using same salt/iv/passphase

Weblogic used similar approach to protect passwords in config files

andreas-h
  • 10,679
  • 18
  • 60
  • 78
Ted Shaw
  • 2,298
  • 14
  • 8
  • 6
    could you give an example of decrypting to go with the encrypt example? – iNoob Oct 11 '16 at 08:52
  • There is a pretty good example of decrypting here: https://stackoverflow.com/questions/7014953/i-need-to-securely-store-a-username-and-password-in-python-what-are-my-options?noredirect=1&lq=1 – rer Aug 04 '18 at 18:28