Coder Social home page Coder Social logo

stef / pwdsphinx Goto Github PK

View Code? Open in Web Editor NEW
16.0 8.0 8.0 1.21 MB

python bindings for libsphinx, a reference client/server and a native backend for web-extensions for Sphinx-based password storage

Home Page: https://www.ctrlc.hu/~stef/blog/posts/sphinx.html

License: GNU General Public License v3.0

Python 90.59% Shell 7.61% Makefile 1.80%
python python-bindings sphinx password-storage password-manager client-server web-extension x11-utilities

pwdsphinx's Introduction

sphinx: a password Store that Perfectly Hides from Itself (No Xaggeration)

pwdsphinx is python wrapper around libsphinx - a cryptographic password storage as described in https://eprint.iacr.org/2015/1099

Dependencies

You need libsphinx and libequihash for the python reference frontend.

You need also to install pysodium using either your OS package manager or pip.

If you want to use also the websphinx browser extension you need to install also an X11 variant of pinentry from the gnupg project:

  • either apt-get install pinentry-qt
  • or apt-get install pinentry-gtk2
  • or apt-get install pinentry-gnome3
  • or apt-get install pinentry-fltk

(or anything equivalent to apt-get install on your OS)

Installation

pip3 install pwdsphinx should get you started.

API

sphinxlib is a ctypes-based python wrapper around libsphinx, so you can build whatever you fancy immediately in python. The interface exposed wraps the 3 sphinx functions from the library like this:

def challenge(pwd)

returns bfac and chal

def respond(chal, secret)

return the response

def finish(pwd, bfac, resp)

returns the raw 32 byte password.

Server/Client

Since the sphinx protocol only makes sense if the "device" is somewhere else than where you type your password, pwdsphinx comes with a server implemented in py3 which you can host off-site from your usual desktop/smartphone. Also a client is supplied which is able to communicate with the server and manage passwords.

Both the client and the server can be configured by any of the following files:

  • /etc/sphinx/config
  • ~/.sphinxrc
  • ~/.config/sphinx/config
  • ./sphinx.cfg

Files are parsed in this order, this means global settings can be overridden by per-user and per-directory settings.

oracle - the server

pwdsphinx comes with a python reference implementation of a extended sphinx server called oracle.

The server can be "configured" by changing the variables in the [server] section of the config file.

The address is the IP address on which the server is listening, default is localhost - you might want to change that.

The port where the server is listening is by default 2355.

datadir specifies the data directory where all the device "secrets" are stored, this defaults to "data/" in the current directory. You might want to back up this directory from time to time to an encrypted medium.

verbose enables logging to standard output.

timeout sets the timeout for any connection the server keeps open.

max_kids sets the number maximum requests handled in parallel. The timeout config variable makes sure that all handlers are recycled in predictable time.

rl_decay specifies the number of seconds after which a ratelimit level decays to an easier difficulty.

rl_threshold increase the difficulty of ratelimit puzzles if not decaying.

rl_gracetime gracetime in seconds added to the expcted time to solve a rate-limiting puzzle.

Change these settings to fit your needs. Starting the server can be done simply by:

oracle

sphinx - the client

This is the client that connects to the oracle to manage passwords using the extended sphinx protocol.

Client Configuration

Like the server, the client can be configured changing the settings in the [client] section of the config file. The host and port should match what you set in the oracle.

The datadir (default: ~/.sphinx) variable holds the location for your client parameters. Particularly it contains a masterkey which is used to derive secrets. The master key - if not available - is generated by issuing an init command. You should back up and encrypt this master key.

rwd_keys toggles if the master password is required for authentication of management operations. If it is False it protects against offline master password bruteforce attacks - which is also a security guarantee of the original SPHINX protocol. The drawback is that for known (host,username) tuples the seeds/blobs can be changed/deleted by an attacker if the clients masterkey is available to them. But neither the master nor the account password can leak this way. This is merely a denial-of-service vector. If rwd_keys is True, then this eliminates the denial-of-service vector, but instead eliminates the offline-bruteforce guarantee of the SPHINX protocol. Note that the oracle is oblivious to this setting, this is purely a client-side toggle, in theory it is possible to have different settings for different "records" on the oracle.

validate_password Stores a check digit of 5 bits in on the oracle, this helps to notice most typos of the master password, while decreasing security slightly.

userlist option (default: True) can disable the usage of userlists. This prohibits the server to correlate all the records that belong to the same sphinx user relating to the same host. The cost of this, is that the user has to remember themselves which usernames they have at which host.

Operations

The client provides the following operations: Create, Get, Change, Commit, Undo, List and Delete. All operations need a username and a site this password belongs to, even if they're only empty strings.

Create password

Creating a new password for a site is easy, pass your "master" password on standard input to the client, and provide parameters like in this example:

echo -n 'my master password' | sphinx create username example.com ulsd 0 ' !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

The parameters to the client are create for the operation, then username for the username on the site example.com then a combination of the letters ulsd and the 0 for the size of the final password. The letters ulsd stand in order for the following character classes: u upper-case letters, l lower-case letters, s symbols and d for digits. The s is a short-cut to allow all of the symbols, if you have a stupid server that limits some symbols, you can specify the allowed symbols explicitly. Currently these are the symbols supported (note the leading space char):

 !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

Be careful, if you specify these on the command-line you'll have to escape the quotes you use for enclosing this list and possibly the backslash char that is also part of this list. In the create username example above the symbols are correctly escaped, in case you need to copy/paste them.

If you do not provide password rules, they will be defaulting to 'ulsd' and length as long as possible.

If the command runs successfully - the resulting new high-entropy password according to the given rules is printed to the console.

In case for some reason you cannot use random passwords with your account, or you want to store a "password" that you cannot change, like a PIN code for example, or a passphrase shared with your colleagues, you can specify a maximum 44 character long password, that will be generated by the SPHINX client for you. In that case the command line looks like this (note the same syntax also works for the change operation)

echo -n 'my master password' | sphinx create username example.com "correct_battery-horse#staple"

In this case you cannot specify neither the accepted character classes, nor the size, nor symbols.

Note1, since the master password is not used to encrypt anything, you can actually use different "master" passwords for different user/site combinations.

Note2, using echo is only for demonstration, you should use something like this instead (getpwd is available from the contrib directory):

getpwd.sh | sphinx create username example.com ulsd 0

Get password

Getting a password from the sphinx oracle works by running the following command:

echo -n 'my master password' | sphinx get username example.com

Here again you supply your master password on standard input, provide the get operation as the first parameter, your username as the 2nd and the site as the 3rd parameter. The resulting password is returned on standard output.

Change password

You might want to (or are forced to regularly) change your password, this is easy while you can keep your master password the unchanged (or you can change it too, if you want). The command is this:

echo -en 'my master password\nnew masterpassword' | sphinx change username example.com 'ulsd' 0 ' !"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

Here again you supply your master password on standard input, but separated by a new-line you also provide the new master password. The new master password can be the same as the old, but can also be a new password if you want to change also the master password. You provide the change operation as the first parameter to the client, your username as the 2nd and the site as the 3rd parameter. You also can provide similar password generation rule parameters that were also used to create the original password, in case your account has new password rules and you want/have to accommodate them. Your new password is returned on standard output.

Committing a changed password

After changing the password, you will still get the old password when running get. To switch to use the new password you have to commit the changes with

echo -n 'my master password' | sphinx commit username example.com

Undoing a password commit

If you somehow messed up and have to go back to use the old password, you can undo committing your password using:

echo -n 'my master password' | sphinx undo username example.com

Deleting passwords

In case you want to delete a password, you can do using the following command:

echo -n "my master password" | sphinx delete username example.com

You provide the delete operation as the first parameter to the client, your username as the 2nd and the site as the 3rd parameter. This command does not provide anything on standard output in case everything goes well.

QR code config

In case you want to use phone with the same sphinx server, you need to export your config to the phone via a QR code.

sphinx qr

Will display a QR code containing only public information - like the server host and port, and if you use rwd_keys. This is mostly useful if you want to share your setup with a friend or family.

If you want to connect your own phone to the setup used with pwdsphinx, you also need to export your client secret in the QR code:

sphinx qr key

This contains your client secret, and you should keep this QR code confidential. Make sure there is no cameras making copies of this while this QR code is displayed on your screen.

If for whatever reason you want to display the QR code as an SVG, just append the svg keyword to the end of the sphinx qr command.

X11 frontend

You can find a bunch of shell-scripts that are based on pinentry-(gtk|qt), xinput, xdotool and dmenu, the top-level entry to these is the dmenu-sphinx.sh script, which stores its history of entered hostnames in ~/.sphinx-hosts - if the hosts are in any way sensitive, you might want to link this file to /dev/null. The contrib/README.md should give you an idea of how else to combine these scripts.

Credits

This project was funded through the NGI0 PET Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 825310.

pwdsphinx's People

Contributors

dnet avatar lucaslasota avatar rolfschr avatar stef avatar tweidinger avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pwdsphinx's Issues

How to configure [client|server][ssl_key|ssl_cert]?

Hi,

could you add some documentation about the [client|server][ssl_key|ssl_cert] config options? The code mentions that one should use different certs/keys for dev & prod. Could you give examples of how to setup oracle.py/sphinx.py in a dev and a prod scenario? I simply don't know what is expected to be configured there.

Questions about sphinxlib

I trying to build pwdsphinx, but there always ValueError during challenge and finish
So, I would like to ask:

  1. Why do you need to wrap sphinx_challenge in __check if sphinx_challenge is void function?
  2. In my case, there are always ValueError during challenge and finish, while with respond everything is ok. Maybe you have some suggestions?

Thanks a lot

error while running oracle

I've tried to build pwdsphinx, but when I run oracle, I got this error message (see below).
I've created a Dockerfile: https://github.com/gyulaweber/build_sphinx to see what I did (the sequence of the commands reflects the sequence of dependencies).

Any suggestion is most appreciated :)

root@dd719ac08b16:/opt# oracle
Traceback (most recent call last):
  File "/usr/local/bin/oracle", line 11, in <module>
    load_entry_point('pwdsphinx==0.3.1', 'console_scripts', 'oracle')()
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 561, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2631, in load_entry_point
    return ep.load()
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2291, in load
    return self.resolve()
  File "/usr/lib/python2.7/dist-packages/pkg_resources/__init__.py", line 2297, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "build/bdist.linux-x86_64/egg/pwdsphinx/oracle.py", line 3, in <module>
  File "/usr/local/lib/python2.7/dist-packages/asyncio/__init__.py", line 9, in <module>
    from . import selectors
  File "/usr/local/lib/python2.7/dist-packages/asyncio/selectors.py", line 39
    "{!r}".format(fileobj)) from None
                               ^
SyntaxError: invalid syntax

Providing a wrong master password yields an error instead of a wrong secret (as was the case previously)

Hi,

I setup pwdsphinx and it works fine. In the past (not sure which commit, definitely before equihash was introduced), when providing the 'wrong' password to retrieve a secret, I would simply get a wrong secret; now I get an error message (see below). I am not sure whether this is intended or not. I just wanted to highlight this. Feel free to close this issue if this is expected behavior.

Thanks

bash-4.4$ sphinx init
bash-4.4$ ls ./datadir/masterkey
./datadir/masterkey
bash-4.4$ printf 'm' | sphinx create user site uld 10 # "m" is the master password
your ☆☆☆☆ (0/4) master password can be online recovered in 7 minutes, and offline in less than a second, trying ~12 guesses
UeZzrVEtox
bash-4.4$ printf 'm' | sphinx get user site
UeZzrVEtox
bash-4.4$ printf 'wrongmasterpassword' | sphinx get user site
Traceback (most recent call last):
  File "/nix/store/z1d50cbhzrjz4pinmsyvalh7444d10qr-python3.8-pwdsphinx-7fde7bb/bin/.sphinx-wrapped", line 9, in <module>
    sys.exit(main())
  File "/nix/store/z1d50cbhzrjz4pinmsyvalh7444d10qr-python3.8-pwdsphinx-7fde7bb/lib/python3.8/site-packages/pwdsphinx/sphinx.py", line 673, in main
    ret = cmd(s, pwd, *args)
  File "/nix/store/z1d50cbhzrjz4pinmsyvalh7444d10qr-python3.8-pwdsphinx-7fde7bb/lib/python3.8/site-packages/pwdsphinx/sphinx.py", line 385, in get
    raise ValueError("bad checkdigit")
ValueError: bad checkdigit

sphinx entry point fails due to missing arguments

System:
Arch Linux x86_64 Linux 5.9.14-arch1-1

Steps to reproduce:

  • install pwdsphinx from pip3
  • run sphinx with any arguments

Expected result:
Correct input runs the specified operation, incorrect input shows help prompt
Actual result:
Error: main() missing 1 required positional argument: 'params'

/usr/local/bin/sphinx contains the following code:

if name == 'main':
sys.argv[0] = re.sub(r'(-script.pyw?|.exe)?$', '', sys.argv[0])
sys.exit(load_entry_point('pwdsphinx==0.5', 'console_scripts', 'sphinx')())

Passing sys.argv to the entry point is enough to make things work -- could this be some unexpected behavior of easy_install?

This seems to be an installation issue not related to the code, but I thought it's worth pointing out.

oracle server config improvement suggestions

Hi,

I have some remarks on the sphinx.cfg [server] section.

The current example server config specifies a 'keydir'. Is this needed? I could not find any reference to that config option in the code base.

The datadir can currently contain the tilde character (~) because it gets expanded. Would that be possible to do this for the ssl key/cert files, too? This would allow easier testing.

Best,
Rolf

T-ORPF extension - plans ?

Thank you for your work on this. I wanted to find out if you had any plans to expand this to cover the T-ORPF/PPSS concept discussed in your presentation ? So that Kd could be stored in a redundant manner.

Cannot import ``SphinxHandler`` from ``sphinx``

I am trying to run webpshinx.py and get the following error:

Traceback (most recent call last):
  File "./websphinx.py", line 28, in <module>
    from sphinx import datadir, SphinxHandler
ImportError: cannot import name 'SphinxHandler' from 'sphinx' (/home/rolfschr/src/pwdsphinx/pwdsphinx/sphinx.py)

I cannot find any SphinxHandler defintion indeed:

$ grep -R 'SphinxHandler'
Binary file __pycache__/websphinx.cpython-37.pyc matches
websphinx.py:    from pwdsphinx.sphinx import datadir, SphinxHandler
websphinx.py:    from sphinx import datadir, SphinxHandler
websphinx.py:    handler = SphinxHandler(datadir)
websphinx.py:    handler = SphinxHandler(datadir)
websphinx.py:    handler = SphinxHandler(datadir)
websphinx.py:    handler = SphinxHandler(datadir)
websphinx.py:    handler = SphinxHandler(datadir)
websphinx.py:    handler = SphinxHandler(datadir)

What do I have to do in order to get things running?

allow disabling of userlist feature

creating a blob on the server containing all usernames associated with a host belonging to the same user allows the server to correlate these and learn something about the user. make this configurable. probably the easiest is just to set the record id to all-zeros for the userblob record, the server can detect this and can skip the updating of this blob together with the client.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.