Passwords are notably problematic for programmers. You’re not imagined to retailer them with out encrypting them, and you are not imagined to reveal what’s been typed when your person enters one. This grew to become notably vital to me once I determined I needed to spice up safety on my laptop computer. I encrypt my house listing—however as soon as I log in, any password saved as plain textual content in a configuration file is probably uncovered to prying eyes.
Specifically, I take advantage of an software referred to as Mutt as my electronic mail shopper. It lets me learn and compose emails in my Linux terminal, however usually it expects a password in its configuration file. I restricted permissions on my Mutt config file in order that solely I can see it, however I am the one person of my laptop computer, so I am probably not involved about authenticated customers inadvertently taking a look at my configs. Instead, I needed to guard myself from absent-mindedly posting my config on-line, both for bragging rights or model management, with my password uncovered. In addition, though I’ve no expectations of unwelcome visitors on my system, I did need to be certain that an intruder could not get hold of my password simply by working
cat on my config.
The Python module
python-gnupg is a Python wrapper for the
gpg software. The module’s identify is
python-gnupg, which it’s essential to not confuse with a module referred to as
GnuPG (GPG) is the default encryption system for Linux, and I have been utilizing it since 2009 or so. I really feel snug with it and have a excessive degree of belief in its safety.
I made a decision that one of the best ways to get my password into Mutt was to retailer my password inside an encrypted GPG file, create a immediate for my GPG password to unlock the encrypted file, and hand the password over to Mutt (truly to the
offlineimap command, which I take advantage of to synchronize my laptop computer with the e-mail server).
Getting user input with Python is fairly simple. You make a name to
enter, and regardless of the person sorts is saved as a variable:
print("Enter password: ")
myinput = enter()
print("You entered: ", myinput)
My downside was once I typed a password into the terminal in response to my password immediate, every part I typed was seen to anybody wanting over my shoulder or scrolling via my terminal historical past:
Enter password: my-Complex-Passphrase
Invisible password entry with getpass
As is commonly the case, there is a Python module that is already solved my downside. The module is
getpass4, and from the person’s perspective, it behaves precisely like
enter besides with out displaying what the person is typing.
You can set up each modules with pip:
$ python -m pip set up --user
Here’s my Python script to create a password immediate:
# by Seth Kenlon
# set up deps:
# python3 -m pip set up --user python-gnupg getpass4
from pathlib import Path
homedir = str(Path.house())
gpg = gnupg.GPG(gnupghome=os.path.be a part of(homedir,".gnupg"), use_agent=True)
passwd = getpass.getpass(immediate="Enter your GnuPG password: ", stream=None)
with open(os.path.be a part of(homedir,'.mutt','cross.gpg'), 'rb') as f:
apipass = (gpg.decrypt_file(f, passphrase=passwd))
if __name__ == "__main__":
apipass = get_api_pass()
Save the file as
password_prompt.py if you wish to attempt it out. If you are utilizing
offlineimap and need to use this resolution to your personal password entry, then reserve it to some location you may level
offlineimap to in your
.offlineimaprc file (I take advantage of
Testing the password immediate
To see the script in motion, you first should create an encrypted file (I will assume that you have already got GPG arrange):
$ echo "hello world" > cross
$ gpg --encrypt cross
$ mv cross.gpg ~/.mutt/cross.gpg
$ rm cross
Now run the Python script:
$ python ~/.mutt/password_prompt.py
Enter your GPG password:
good day world
Nothing shows as you sort, however so long as you enter your GPG passphrase accurately, you will notice the check message.
Integrating the password immediate with offlineimap
I wanted to combine my new immediate with the
offlineimap command. I selected Python for this script as a result of I knew that
offlineimap could make calls to Python functions. If you are an
offlineimap person, you will admire that the one “integration” required is altering two strains in your
First, add a line referencing the Python file:
pythonfile = ~/.mutt/password_prompt.py
And then change the
remotepasseval line in
.offlineimaprc with a name to the
get_api_pass() perform in
remotepasseval = get_api_pass()
No extra passwords in your config file!
It generally feels virtually paranoid to consider safety trivia in your private pc. Does your SSH config actually should be restricted to 600? Does it actually matter that your electronic mail password is in an inconsequential config file buried inside a hidden folder referred to as, of all issues,
.mutt? Probably not.
And but understanding that I haven’t got delicate knowledge quietly hidden away in my config recordsdata makes it quite a bit simpler for me to commit recordsdata to public Git repositories, to repeat and paste snippets into assist boards, and to share my data within the type of precise, known-good configuration recordsdata. For that alone, improved safety has made my life simpler. And with so many nice Python modules obtainable to assist, it is easy to implement.