Giter Site home page Giter Site logo

smlx / piv-agent Goto Github PK

View Code? Open in Web Editor NEW
77.0 6.0 6.0 5.77 MB

An SSH and GPG agent which you can use with your PIV hardware security device (e.g. a Yubikey).

Home Page: https://smlx.github.io/piv-agent/

License: Apache License 2.0

Go 99.47% Dockerfile 0.34% Makefile 0.18%
piv ssh ssh-agent yubikey gpg-agent gpg pgp hacktoberfest

piv-agent's Introduction

PIV Agent

Release coverage Go Report Card User Documentation

About

  • piv-agent is an SSH and GPG agent providing simple integration of PIV hardware (e.g. a Yubikey) with ssh, and gpg workflows such as git signing, pass encryption, or keybase chat.
  • piv-agent originated as a reimplementation of yubikey-agent because I needed some extra features, and also to gain a better understanding of the PIV applet on security key hardware.
  • piv-agent makes heavy use of the Go standard library and supplementary crypto packages, as well as piv-go and pcsclite. Thanks for the great software!

DISCLAIMER

I make no assertion about the security or otherwise of this software and I am not a cryptographer. If you are, please take a look at the code and send PRs or issues. ๐Ÿ’š


Features

  • implements (a subset of) both ssh-agent and gpg-agent functionality
  • support for multiple hardware security keys
  • support for multiple slots in those keys
  • support for multiple touch policies
  • all cryptographic keys are generated on the hardware security key, rather than on your laptop
    • secret keys never touch your hard drive
  • uses systemd (Linux) or launchd (macOS) socket activation
    • as a result, automatically drop the transaction on the security key and cached passphrases after some period of disuse
  • provides "fall-back" to traditional SSH and OpenPGP keyfiles

Design philosophy

This agent should require no interaction and in general do the right thing when security keys are plugged/unplugged, laptop is power cycled, etc.

It is highly opinionated:

  • Only supports 256-bit ECC keys on hardware tokens
  • Only supports ed25519 SSH keys on disk (~/.ssh/id_ed25519)
  • Requires socket activation

It makes some concession to practicality with OpenPGP:

  • Supports RSA signing and decryption for OpenPGP keyfiles. RSA OpenPGP keys are widespread and Debian in particular only documents RSA keys.

It tries to strike a balance between security and usability:

  • Takes a persistent transaction on the hardware token, effectively caching the PIN.
  • Caches passphrases for on-disk keys (i.e. ~/.ssh/id_ed25519) in memory, so these only need to be provided once after the agent starts.
  • After a period of inactivity (32 minutes by default) it exits, dropping both of these. Socket activation restarts it automatically as required.

Hardware support

Tested with:

Will be tested with (once PIV support is available):

Any device implementing the SCard API (PC/SC), and supported by piv-go / pcsclite may work. If you have tested another device with piv-agent successfully, please send a PR adding it to this list.

Platform support

Currently tested on Linux with systemd and macOS with launchd.

Protocol / Encryption Algorithm support

Supported Not Supported Support Blocked (Curve25519)
โœ… โŒ โณ

Curve25519 algorithms are blocked on hardware support. Currently I'm only aware of Solo V2 which intends to implement this non-standard curve. Support is not yet available (see the link above).

ssh-agent

Security Key Keyfile
ecdsa-sha2-nistp256 โœ… โŒ
ssh-ed25519 โณ โœ…

gpg-agent

Security Key Keyfile
ECDSA Sign (NIST Curve P-256) โœ… โœ…
EDDSA Sign (Curve25519) โณ โณ
ECDH Decrypt โœ… โœ…
RSA Sign โŒ โœ…
RSA Decrypt โŒ โœ…

Install and Use

Please see the documentation.

Develop

Prerequisites

Install build dependencies:

# debian/ubuntu
sudo apt install libpcsclite-dev

Build and test

make

Build and test manually

This D-Bus variable is required for pinentry to use a graphical prompt:

go build ./cmd/piv-agent && systemd-socket-activate -l /tmp/piv-agent.sock -E DBUS_SESSION_BUS_ADDRESS ./piv-agent serve --debug

Then in another terminal:

export SSH_AUTH_SOCK=/tmp/piv-agent.sock
ssh ...

Build and test the documentation

cd docs && make serve

piv-agent's People

Contributors

dependabot[bot] avatar github-actions[bot] avatar smlx 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

piv-agent's Issues

Age key support

As outlined in Mic92/ssh-to-age#14, it would be great if it would be possible to use piv-agent to generate age keys in some way.

Currently the only way to get SSH keys from Yubikey seems to be age-plugin-yubikey. Unfortunately it doesn't seem to be able to use the PIV keys generated by piv-agent. While that itself isn't too big of a deal, it also seems that age-plugin-yubikey cannot run while piv-agent is active, as the PIV device is busy. That means that piv-agent would have to be stopped every time a file needs to be encrypted or decrypted, which is really inconvenient.

Depending on the outcome of Mic92/ssh-to-age#14, it might be possible to get age keys from the SSH keys generated by piv-agent. However, I realised that piv-agent is already generating both SSH and GPG keys, so why not age? @str4d seems to acknowledge that some sort of an agent would be good to implement for age keys, and I have a hunch that piv-agent might already have a lot of the groundwork necessary for that.

piv-agent pinentry doesn't retry passphrase

With gpg-agent, if you get the passphrase wrong when entering it into pinentry you get the ability to retry the passphrase. piv-agent will just return an error immediately.

piv-agent should allow retries the same way gpg-agent does.

Lazy decryption for keyfiles

When piv-agent is invoked as a gpg-agent it currently reads all the GPG keyfiles and decrypts them during initialisation.

It would be nice if the GPG keyfiles could instead be lazily decrypted only when they actually needed to be used.

NixOS package and module

First for some context - in the past few days I went on a research spree trying to simplify my YubiKey encryption/signing/authentication setup (again). I tried FIDO2 resident SSH keys, GPG agent with SSH support, SSH agent with PIV keys through PKCS#11, yubikey-agent and pivy. In the end I think that this project still has the nicest UX for SSH keys (which can be used for both encryption and signing), and if #134 is addressed, it could be the best UX for YubiKey cryptography in general. Yet it seems to be criminally underrated, which I imagine doesn't help with motivation or contributions.

I've been using this project in a NixOS configuration for over a year now and I think making it generally available as part of the project could make it more attractive to others (though I do realise I'm talking about a niche within a niche within a niche...). Anyway, I suggest adding a flake to this repo which would output a package, an overlay, a NixOS module, and a home manager module. I volunteer to contribute this if you think it's a good idea.

Consider parsing gpg-agent keyfiles directly

gpg-agent stores keyfiles as encoded s-expressions on disk. If piv-agent read those directly then there would be no need to export GPG keys for use with piv-agent.

On the other hand, the GPG key export is only a one-time operation and it can be useful to not make piv-agent load all the keys stored by gpg-agent.

This issue can collect thoughts for/against this feature.

GPG "General error" when decrypting multiple things simultaneously

This issue can be reproduced using the following script (export KEYID variable before running):

#!/bin/bash

FOO="$(echo bar | gpg -r ${KEYID} -e -)"

(echo "${FOO}" | gpg -d) &
(echo "${FOO}" | gpg -d) &
(echo "${FOO}" | gpg -d) && fg

Which results in an output like this (showing only the relevant lines):

gpg: encrypted with 256-bit ECDH key, ID ...
gpg: public key decryption failed: General error
gpg: decryption failed: No secret key
...
gpg: encrypted with 256-bit ECDH key, ID ...
gpg: public key decryption failed: General error
gpg: decryption failed: No secret key
...
gpg: encrypted with 256-bit ECDH key, ID ...
bar
...

As you can see, only one of the three GPG processes successfully decrypts the input, while the other two fail with a "General error". Not sure if it matters, but I'm using a "touch policy: always" decrypting key as a subkey on a master key (setup as shown here), and specifying the master key id for the KEYID.

I discovered this issue when using a Terraform sops provider and defining several sops_file data blocks. Plans with that fail as GPG tries to decrypt several files at a time and runs into this issue, so it impacts real world use. I did find a workaround for that specific issue, as sops lets you define a custom path for the GPG executable. So I wrote a script that would lock the GPG process using flock and pointed SOPS_GPG_EXEC to it:

#!/bin/bash

# Process locking workaround for sops compatibility with piv-agent.
# Point SOPS_GPG_EXEC environmental variable to this script.

(
    # Fail after a minute of waiting.
    flock -x -w 60 200 || exit 60
    gpg "$@"
) 200>/tmp/piv-agent-gpg-lock

macOS support

piv-agent currently uses socket activation and is only tested against systemd.

I believe macOS has similar functionality, so if anyone can get this working please send a PR!

Releases currently have a build for macOS which is completely untested ๐Ÿ˜ฌ edit: these have been disabled since the build broke and I don't have hardware to get it working again. edit again: these are re-enabled, please test and report results here.

solo v2

Hello ๐Ÿ‘‹

Has your solo v2 arrived yet?
If not I have mine so I'm happy to help with testing and maybe some development

piv-agent doesn't exit if constantly used

piv-agent doesn't exit if it is constantly being called (e.g. by a cronjob that is decrypting something using gpg). This is not great because it means that keyfile passphrases are held in memory for long periods.

By default piv-agent should exit after some period (e.g. 12 hours?) even if constantly in use.

Allow concurrent usage

Concurrent invocations of gpg will currently block because the piv-agent server is not concurrent.

piv-agent should be able to handle concurrent invocations of gpg.

Improved GUI prompt configuration

First of all, in my opinion, this is currently by far the best solution for security keys in terms of the balance of simplicity, functionality and security. However, I would love it if the GUI prompts weren't hardcoded. In particular I mean the pinentry executable (which I think can be changed using WithBinaryName) and touch notification delay. It would be great if those things (and other GUI elements if I'm missing any) could be configured through piv-agent serve arguments.

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.