Giter Club home page Giter Club logo

parcimonie.sh's Introduction

parcimonie.sh

This is a reimplementation of Parcimonie, written completely in a si{mp,ng}le Bash script.

What does it do?

parcimonie.sh refreshes individual keys in your GnuPG keyring at randomized intervals. Each key is refreshed over a unique, single-use Tor circuit.

Unlike the original Parcimonie, parcimonie.sh guarantees that each key refresh happens over a unique Tor circuit even when multiple refreshes happen at the same time (torsocks --isolate).

Why?

You can check the original Parcimonie design document if you are wondering why this is needed. This is the original file from the perl parcimonie and is only here to be archived.

The tl;dr version: gpg --refresh-keys discloses your entire list of PGP keys to the keyserver you are using, as well as whoever is wiretapping your connection if you are using an unencrypted protocol such as HKP (which is the default for most setups). That is a bad thing.

Known security issues

  • On GnuPG 2.1+, key refreshes are not guaranteed to use unique Tor circuit (issue #15).
  • On GnuPG 2.1+, if the user refreshes a key outside of parcimonie.sh prior to parcimonie.sh's first key refresh, Tor will not be used for key refreshes (also issue #15).

Installation

If on Arch, grab the parcimonie-sh-git package from the AUR.

On Fedora, install parcimonie.sh from the official repositories: dnf install parcimonie.sh.

Otherwise, just copy parcimonie.sh somewhere and make it run at boot with the right environment variables (see the "Usage" section).

Dependencies

  • GnuPG: tested with GnuPG 2, probably works OK with 1.* as well
  • torsocks 2.0
  • Have Tor running

Usage

Just run parcimonie.sh. There are some optional environment variables that you can use to override the default values.

  • TOR_ADDRESS: IP on which Tor is listening. If not set, uses 127.0.0.1.
  • TOR_PORT: Port on which Tor is listening. If not set, uses 9050. Make sure this refers to a SOCKSPort entry of your torrc for which NoIsolateSOCKSAuth is not present. If you have no idea what that means, you have nothing to worry about.
  • PARCIMONIE_USER: The user to run as. If not set, will run as whatever user is running the script. If set, will su to the specified user. You can also set it to the special value *, which will cause the script to multiple run instances of itself: one instance for each user who has a directory called .gnupg in their home directory. Useful for boot scripts, and for config files for the systemd service.
  • MIN_WAIT_TIME: Minimum time to wait between key refreshes. Defaults to 900 seconds (15 minutes).
  • TARGET_REFRESH_TIME: Rough expected time for refreshing every key in the keyring. Defaults to 604800 seconds (1 week). Note that this doesn't guarantee that every key will be refreshed in that time. The time intervals between refreshes and the actual keys to refresh are picked randomly every time. See the delay computation function for the exact formula.
  • COMPUTER_ONLINE_FRACTION: Fraction of time that the computer is expected to be online, from 0.1 (online 10% of the time) to 1.0 (always online). Defaults to 1.0. This is used to scale TARGET_REFRESH_TIME accordingly in order to make it likely enough for keys to be regularly refreshed on a computer that is not online permanently. MIN_WAIT_TIME is still honored.
  • USE_RANDOM: Whether or not to use /dev/random instead of /dev/urandom as source of randomness. By default, this is set to false, therefore /dev/urandom is used.
  • GNUPG_BINARY: Path to gpg. If not set, will use gpg2 or gpg from the $PATH.
  • DIRMNGR_PATH: Path to dirmngr, for GnuPG < 2.1. If not set, will try to find it in $PATH. If not found, GnuPG < 2.1 will be assumed.
  • DIRMNGR_CLIENT_PATH: Path to dirmngr-client. If not set, will try to find it in $PATH. dirmngr-client is required if dirmngr is specified or found in $PATH.
  • TORSOCKS_BINARY: Path to torsocks. If not set, will use torsocks from the $PATH.
  • GNUPG_HOMEDIR: Value for the --homedir argument of gpg. Ignored when PARCIMONIE_USER=*. If not set, no --homedir argument is passed, which usually means ~/.gnupg will be used.
  • GNUPG_KEYSERVER: Value for the --keyserver argument of gpg. If not set, no --keyserver argument is passed, which means your default keyserver will be used.
  • GNUPG_KEYSERVER_OPTIONS: Value for the --keyserver-options argument of gpg. If not set, a single http-proxy= argument is passed. If you already use torify connections to keyservers with gpg's http-proxy keyserver-option in your gpg.conf while having other keyserver-options defined on top of that, you will need to re-specify those along with http-proxy= in GNUPG_KEYSERVER_OPTIONS in order to disable the proxying part. parcimonie.sh needs to run gpg with torsocks in order to ensure that all key grabs happen on different Tor circuits, and torsocks won't allow gpg to connect to its http-proxy on 127.0.0.1.
  • PARCIMONIE_CONF: If set, this file will be sourced before running. Useful to set environment variables without polluting the environment too much.

systemd service

If you installed the Arch package or the Fedora package, you have a parameterized systemd service called parcimonie.sh@. The parameter refers to an environment file in /etc/parcimonie.sh.d; for example, the parcimonie.sh@hello service reads the environment variables from /etc/parcimonie.sh.d/hello.conf, and runs parcimonie.sh with it.

A ready-to-use configuration file is provided at /etc/parcimonie.sh.d/all-users.conf; it is set to start parcimonie.sh for all users on the system who have a ~/.gnupg directory. If that sounds like what you want, you can enable it right away using the parcimonie.sh@all-users service. If not, another sample configuration file is provided at /etc/parcimonie.sh.d/sample-configuration.conf.sample (Arch package) or at /usr/share/doc/parcimonie.sh/sample-configuration.conf.sample (Fedora package).

You can also use the systemd user service called parcimonie.sh, which uses the configuration file ~/.config/parcimonie.sh.conf.

Why a reimplementation?

Oh gee, let me think.

$ pactree parcimonie-git                       $ pactree -d 1 parcimonie-sh-git
parcimonie-git                                 parcimonie-sh-git
├─perl-any-moose                               ├─bash
│ ├─perl-moose                                 ├─torsocks
│ │ ├─perl-class-load                          ├─tor
│ │ │ ├─perl-module-runtime                    └─gnupg
│ │ │ │ └─perl-params-classify
│ │ │ ├─perl-data-optlist
│ │ │ │ ├─perl-params-util
│ │ │ │ ├─perl provides perl-scalar-list-utils
│ │ │ │ └─perl-sub-install
│ │ │ ├─perl-package-stash
│ │ │ │ ├─perl-dist-checkconflicts
│ │ │ │ │ ├─perl-list-moreutils
│ │ │ │ │ └─perl provides perl-exporter
│ │ │ │ ├─perl-package-deprecationmanager
│ │ │ │ │ ├─perl-list-moreutils
│ │ │ │ │ ├─perl-params-util
│ │ │ │ │ └─perl-sub-install
│ │ │ │ ├─perl provides perl-scalar-list-utils
│ │ │ │ └─perl-package-stash-xs
│ │ │ ├─perl-try-tiny
│ │ │ ├─perl-test-fatal
│ │ │ │ └─perl-try-tiny
│ │ │ └─perl-module-implementation
│ │ │   └─perl-module-runtime
│ │ ├─perl-class-load-xs
│ │ │ └─perl-class-load
│ │ ├─perl-data-optlist
│ │ ├─perl-devel-globaldestruction
│ │ │ ├─perl-sub-exporter
│ │ │ │ ├─perl
│ │ │ │ ├─perl-data-optlist
│ │ │ │ ├─perl-params-util
│ │ │ │ └─perl-sub-install
│ │ │ └─perl-sub-exporter-progressive
│ │ ├─perl-dist-checkconflicts
│ │ ├─perl-eval-closure
│ │ │ ├─perl provides perl-test-simple
│ │ │ ├─perl-test-requires
│ │ │ ├─perl-test-fatal
│ │ │ ├─perl-try-tiny
│ │ │ └─perl-sub-exporter
│ │ ├─perl-list-moreutils
│ │ ├─perl-mro-compat
│ │ ├─perl-package-deprecationmanager
│ │ ├─perl-package-stash
│ │ ├─perl-package-stash-xs
│ │ ├─perl-params-util
│ │ ├─perl-sub-exporter
│ │ ├─perl-sub-name
│ │ ├─perl-task-weaken
│ │ └─perl-try-tiny
│ └─perl-mouse
├─perl-namespace-autoclean
│ ├─perl-b-hooks-endofscope
│ │ ├─perl-module-implementation
│ │ ├─perl-module-runtime
│ │ ├─perl-sub-exporter
│ │ ├─perl-sub-exporter-progressive
│ │ ├─perl-try-tiny
│ │ ├─perl-variable-magic
│ └─perl-namespace-clean
│   ├─perl-b-hooks-endofscope
│   └─perl-package-stash
├─perl-gnupg-interface
│ └─perl-any-moose
├─perl-clone
├─perl-config-general
├─perl-file-homedir
│ └─perl-file-which
├─perl-path-class
├─perl-net-dbus
│ ├─dbus
│ │ ├─expat
│ │ │ └─glibc
│ │ ├─coreutils
│ │ ├─filesystem
│ │ └─shadow
│ │   ├─bash
│ │   ├─pam
│ │   └─acl
│ └─perl-xml-twig
│   ├─perl-xml-parser
│   │ └─expat
│   └─perl-text-iconv
├─perl-tie-cache
├─perl-time-duration-parse
│ └─perl-exporter-lite
├─perl-moosex-types-path-class
│ ├─perl-moose
│ ├─perl-moosex-types
│ │ ├─perl-carp-clan
│ │ ├─perl-namespace-clean
│ │ ├─perl-sub-install
│ │ └─perl-sub-name
│ └─perl-path-class
├─perl-moosex-getopt
│ ├─perl-getopt-long-descriptive
│ │ ├─perl-params-validate
│ │ │ └─perl-module-implementation
│ │ └─perl-sub-exporter
│ ├─perl-moose
│ └─perl-moosex-role-parameterized
└─perl

Licensing

parcimonie.sh is licensed under the WTFPL.

parcimonie.sh's People

Contributors

bober182 avatar eksperimental avatar etienneperot avatar gdetrez avatar genodeftest avatar jelhan avatar joelpurra avatar kaikli avatar meisterp avatar morxa avatar mroq avatar tribut avatar vbrandl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parcimonie.sh's Issues

PGP key expired

Hi,

when I try to install on Arch using makepkg, it fails the signature check using git log.

It looks like your PGP key expired 2019-01-13. If you still own this key could you update the expiration date and re-publish?

Does not torify key fetches with GnuPG 2.1+

Recent modern GnuPG delegates to dirmngr all keyserver operations. Torifying gpg has no effect on how dirmngr reaches keyservers at all. I realize this is being discussed on #15, but if I'm guessing right, this problem entirely prevents parcimonie.sh (sic) from doing its job as designed on recent distros, so it doesn't seem good enough to me to not have this documented anywhere else than on a ticket titled "IPC syntax error with gnupg 2.1.4".

I suggest requesting a CVE for this problem, and documenting this in README.md so that new potential users are aware of this limitation.

Make sure every key gets updated at some time

When picking a key to update, parcimonie simply picks a random key from the keyring. This way it can happen that certain keys don't get updated for a longe time while other keys get updated multiple times in the same period.

Maybe it is possible to implement a logic that updates every key once before the next round of updates.
I was thinking of storing a set of all keys from the keyring, picking random keys from the set and update a flag in the set when they get updated. When all keys are updated, a new set is generated and so on.
This set needs to be stored persistent so it still exists after a reboot.

For keys that are added to the keyring while a update cycle is still running, the daemon could compare the full set that was used to create the current update cycle and diff it against the actual keyring. Every key that is new gets added to the update set.

The structure of the set could be something simple like

fingerprint:0
fingerprint:1

where 0 or 1 indicate wether the key has or hasn't been update in the current cycle.

Maybe there is a more elegant way to achieve this but I think it would be good to make sure every key gets updated.

[RESEARCH] Windows workaround

Dear Etienne,
Since parcimonie.sh is oriented primarily towards Unix users, what workaround comes to your mind to offer it to Windows users? Perhaps it is enough to specify Tor-based keyserver such as qdigse2yzvuglcix.onion?

Using tor as http proxy

Using current stable version of gnupg and curl it's possible to use tor socks proxy as http-proxy option in keyserver-options. So there is no need for torsocks anymore.

$ gpg --keyserver-options http-proxy=socks5://127.0.0.1:9050 --search [email protected]
gpg: searching for "[email protected]" from hkps server hkps.pool.sks-keyservers.net
gpg: key "[email protected]" not found on keyserver

On the other hand current implemation breaks if usage of tor is defined in gnupg configuration (~/.gnupg/gpg.conf). In this scenario torsocks adds a second tor layer and therefore connection fails:

$ torsocks gpg --keyserver-options http-proxy=socks5://127.0.0.1:9050 --search [email protected]
gpg: searching for "[email protected]" from hkps server hkps.pool.sks-keyservers.net
[Mar 10 01:59:15] WARNING torsocks[10135]: [connect] Connection to a local address are denied since it might be a TCP DNS query to a local DNS server. Rejecting it for safety reasons. (in tsocks_connect() at connect.c:177)
gpgkeys: HTTP search error 7: 
gpg: key "[email protected]" not found on keyserver
gpg: keyserver internal error
gpg: keyserver search failed: keyserver error

Therefore parcimonie.sh could not be used if tor should also be used for all other keyserver operations of gnupg. This is bad.

Tested with gnupg 1.4.16 and curl 7.37.1 running Ubuntu 14.10.

Consider using torsocks --isolate

Hi!

Recent torsocks has a --isolate option, that should allow you to drop the code that generates a unique SOCKS user/password etc. :)

torsocks rejects connection

When running parcimonie.sh I get this output:

$ parcimonie.sh 
Sleeping 3539 seconds before refreshing key 1234567890ABCDEF1234567890ABCDEF01234567...
gpg: requesting key 0x90ABCDEF01234567 from hkps server hkps.pool.sks-keyservers.net
[Jan 05 17:33:23] WARNING torsocks[1121]: [syscall] Unsupported syscall number 186. Denying the call (in tsocks_syscall() at syscall.c:165)
[Jan 05 17:33:23] WARNING torsocks[1121]: [connect] Connection to a local address are denied since it might be a TCP DNS query to a local DNS server. Rejecting it for safety reasons. (in tsocks_connect() at connect.c:177)
gpgkeys: HTTP fetch error 7: 
gpg: no valid OpenPGP data found.
gpg: Total number processed: 0
> Sleeping 5850 seconds before refreshing key 1234567890ABCDEF1234567890ABCDEF01234568...

(I replaced the key ids.) I am running the latest version of parcimonie.sh on torsocks 2.0.0 on Fedora 21 with no additional arguments or env variables. Any Idea what I am missing?

Fixes for Mac OSX

Running parcimonie.sh on Mac OSX 10.9 Mavericks (perhaps with custom versions of some tools) failed for me.

  • sed doesn't have the -r flag for extended regular expressions, but it has the equivalent -E flag.
  • expr didn't want to parse numbers with extra whitespace.

Here are the steps taken to fix them:

$ ./parcimonie.sh
sed: illegal option -- r
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
No GnuPG keys found.

Editing parcimonie.sh to use sed -E instead, removing /i ignore case flag etcetera.

$ ./parcimonie.sh
expr: not a decimal number: '                636261616                                                '
expr: not a decimal number: '      89'
> Sleeping  seconds before refreshing key 4C47B4FF173AE6ED0DB733946DF6890D2A977668...

Testing the commands called from parcimonie.sh.

# Commands in getPublicKeys() called from getNumKeys()
# Note the whitespace surrounding the number
$ gpg --list-public-keys --fixed-list-mode --fingerprint --with-key-data | grep -E '^fpr:' | wc -l
      89
$ # Commands in getRandom()
$ # Note the whitespace and the trailing newline/empty line
$ od -vAn -N4 -tu4 < /dev/urandom
               1315831259

$ od -vAn -N4 -tu4 < /dev/random
                 46678454

Now editing parcimonie.sh to remove whitespace around numbers, including newlines/empty lines, keeping only the digits.

$ ./parcimonie.sh
> Sleeping 2922 seconds before refreshing key 4C47B4FF173AE6ED0DB733946DF6890D2A977668...

The changes are present in the mac-osx-fixes-sed-expr branch in my fork. Because this is a quick, non-portable hack, I'm not going to submit a pull request. Hope someone else might find it useful though!

Sed flag test error output visible on Mac OS X

In 7fff20a, the sed regexp flag test generates an error message on Mac OS X.

$ ./parcimonie.sh
sed: illegal option -- r
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
> Sleeping 12840 seconds before refreshing key ...

It would be better to hide the error output, as it does not affect running the script.

GnuPG 2.1 & dirmngr handling

Starting with gnupg 2.1.4 on Arch Linux, receiving a key always fails with the same error:

May 17 18:55:36 clavius parcimonie.sh[435]: > Sleeping 11282 seconds before refreshing key <key_id>...
May 17 22:03:38 clavius parcimonie.sh[435]: gpg: keyserver receive failed: IPC syntax error

Updating the key manually works as expected:

$ gpg --recv-keys "<key_id>"
gpg: key <short_id>: "..." not changed
gpg: Total number processed: 1
gpg:              unchanged: 1

With gnupg 2.1.3, this error did not occur.

My gpg.conf:

require-cross-certification
keyserver hkp://pool.sks-keyservers.net
personal-digest-preferences SHA512
cert-digest-algo SHA512
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
use-agent

My /etc/parcimonie.sh.d/user.conf:

PARCIMONIE_USER=<user>
USE_RANDOM=true

My tor config is the default of an up-to-date Arch Linux. Since tor was not updated with gnupg, I don't think the error is directly related to tor.

How to reproduce

I can only guess that it must be related to gnupg 2.1.4, as my configuration is probably the standard configuration:

  1. install gnupg >= 2.1.4
  2. start parcimonie
  3. check the log for an IPC syntax error

Expected behavior

The key should be refreshed successfully.

Actual behavior

Receiving the key fails with the error shown above.

Finds no keys with gnupg 2.1

With gnupg 2.1, parcimonie.sh doesn't find any keys:

❯ parcimonie.sh             
No GnuPG keys found.

Apparently this is due to the changed output of --with-colons.

GnuPG 2 dependencie

Readme says that GnuPG version 2 is a dependencie. I'm running parcimonie.sh with GnuPG 1.4.16 without facing any issues.

$targetRefreshTime implies the computer is up 24/7

The specified $targetRefreshRate only works out if the computer is never turned of. Especially on laptops this is not really feasible. Even worse, with a low number of keys the maximum possible time for any refresh to occur might be higher then the uptime (24h with 14 keys).
Putting the sleep after the refresh would at least ensure one refresh per restart.

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.