Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[enhancement] Feature request + PoC: Unlock using public key in ssh-agent #349

Open
iskunk opened this issue Apr 5, 2022 · 0 comments
Open

Comments

@iskunk
Copy link

iskunk commented Apr 5, 2022

I'd like to propose/request an alternative to typing in passphrases that uses a mechanism many security-conscious users are likely familiar with: the SSH authentication agent.

SSH allows users who hold a private key to authenticate to remote SSH servers that have the corresponding public key. The authentication process involves the SSH server sending a random message to the client, which the client signs (with the user's private key), and then sends back to the server. The server can then verify that the signature corresponds to the public key, and if so, it lets the user in.

Ssh-agent facilitates this process, and uses a simple wire protocol to support it. One of the commands in this protocol is SSH_AGENTC_SIGN_REQUEST, which covers the server requesting a signature from the client of some arbitrary blob of data. Any program that speaks the ssh-agent protocol, usually via the Unix socket at $SSH_AUTH_SOCK, can make such a request.

Now, fscrypt is not using public-key cryptography in any way, just symmetric encryption which (for the protectors) usually takes the form of arbitrary passphrases. But I think that the ssh-agent signing functionality can be (ab)used as a convenient source for a secure "passphrase" that need not be typed in.

If you request a signature multiple times on an unchanging hunk of input data, you will get back the same signature every time. Even if the input data is publicly known, the signature (for a given public key) can only be generated by the user who holds the corresponding private key. So the signature, which can be requested automatically via ssh-agent, could in itself be used as a passphrase for an fscrypt protector. I believe it would be no worse, security-wise, than a (decent) typed-in custom passphrase.

I am attaching a rough proof-of-concept implementation of this idea, written in Python (not a Gopher, sorry) and using the Paramiko library. This script supports two operations:

$ ./fscrypt-ssh.py setup

will connect to a running ssh-agent, allow you to select a key (if there are multiple), and generate a passphrase that is derived from a signature (made using that key) of some arbitrary text. This passphrase should be used in a custom-passphrase protector for a test directory. This directory, in locked form, is then passed to the second operation:

$ ./fscrypt-ssh.py unlock DIRECTORY

This will connect to a running ssh-agent, and attempt to unlock DIRECTORY using the available keys.

Now, of course there are multiple devils in the details:

  1. I'm not sure what should be used for the input data to be signed. It needs to be something that doesn't change for a given encrypted directory, or else the signature operation will return different results. And it probably can't be considered a secret. But using a hard-coded string that is always the same everywhere would probably not be good (if the signature-derived passphrase is compromised in one place, then it can be re-used wherever else the same private key is employed). Something incorporating the protector and/or policy ID, perhaps?

  2. The proof-of-concept tries to unlock a directory using all the available keys, but this is dumb---it can already get the corresponding (public key) fingerprints from ssh-agent, so it should look for a key with a specific fingerprint. This information can't be stored in the existing protector types, however (unless you stuff it into a protector description, which appears to be read-only once created).

    (Implementation note: Ssh-agent actually gives you the public keys in full, not just the fingerprints---the PoC generates SHA256 fingerprints itself, hashing and all. You can match against the entirety of the public key if desired, though that's probably overkill.)

  3. The signature response from ssh-agent contains a variable-length header that should probably be chopped off before deriving a passphrase from it, as the header is obviously not high-entropy data. This article describes it.

  4. By default, a user's ssh-agent is only accessible on the system where it is running. In order for the agent to be accessible on remote systems, agent forwarding needs to be enabled. This is not without risk. I don't think this is a significant issue for the usage proposed here---if an attacker can get access to a user's remote ssh-agent, then they could probably capture the keystrokes of a typed passphrase, too---but it is worth the disclaimer.

  5. I am not a cryptographer, so running all this by one is probably advisable :-)

We have a good solution already for passphrase-less login access to remote systems, and I think the above approach can provide us similarly streamlined unlocking of local and remote encrypted directories.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants