15

Is it possible to use running SSH agent to decrypt some data (supplied as a string or read from file)?

3 Answers3

15

No, it is not at least with OpenSSH -- there are no options to operate in this mode. It is for authenticating with remote servers (validating identity) and then encrypting the network traffic between ssh client application and the remote sshd server.

You could try compiling a library from OpenSSH that uses its encryption modes and create an executable based on that to use encryption, but the authors of OpenSSH did not try to do that. Here's a github repo that took openssh and tried converting it into a library that other applications can use.

OpenSSH uses well-known protocols that are implemented in OpenSSL; e.g., my ssh connection right now uses aes128-ctr to encrypt with hmac-md5 to verify integrity (the combination). Granted if you actually trace through to see where aes128-ctr comes from, you'll find it ultimately is taken from the OpenSSL library. (That is in libopenssh/cipher.c tells aes128_ctr to use EVP_aes_128_ctr which is going through the header file #include "cipher.h" (libOpenSSH which includes #include <openssl/evp.h> (note OpenSSL) which defines EVP_aes_128_ctr that ultimately traces back to being implemented (after some wrappers to deal with different modes/sizes) in openssl/crypto/aes/aes_core.c.


EDIT:

Sorry wasn't clear to me you were talking about ssh-agent.

As to using the private keys loaded into ssh-agent to encrypt or decrypt messages, no that is not possible. The entire purpose of the ssh-agent is to limit use of the private key to only the one acceptable function (authentication in ssh).

Look at the source code of ssh-agent and the description of the functionality in PROTOCOL.agent. For security, ssh-agent provides a very limited interface to using the stored ssh private keys.

For ssh2, the only use of the private key is to sign requests using your private key. With ssh1 there's also process authentication challenges, but you really shouldn't use ssh1 anymore. The other functions don't use the private key, but deal with key management.

Key challenges in SSH1 worked as fellows. First, the remote end sends a challenge -- a random bit-string encrypted with the user's public key (known from authorized_keys file). The user sends the challenge to ssh-agent, which uses the private key to decrypt the challenge message. Then, ssh-agent takes the random bit-string and calculates a cryptographic hash of it, and sends back the cryptographic hash. This verifies that the user was in possession of the private key, and only leaks the hash of the decrypted message -- but not the actual decrypted message.

Key challenges in SSH2 now work by sending signing requests. Again, the remote server sends a random bit-string to the user. Then ssh-agent takes that random-bit-string and uses their private key to cryptographically sign that message -- no decryption is performed. The signature is sent back and the server verifies the signature by using the public key to validate it.

In the context of RSA, the public key is (N = p*q, e) and the private key (N, d), where d is constructed so d*e ≡ 1 (mod (p-1)(q-1)) (d can be calculated efficiently knowing e, p and q via Euclid's extended algorithm). Then the method of signing is to hash (with SHA1) the random message h = sha1(r) and then raise the hash to a power with the private key S = h^d (mod N). Then the server validates the signature S with the user's public key by calculating S^e (mod N) which due to Euler's totient theorem will be the hash of the sent message, which it will compare it against S^e ≡ (h^d)^e ≡ h^(d*e) ≡ h^(1 + (q-1)(p-1)) ≡ h (mod N).

dr jimbob
  • 38,768
  • 8
  • 92
  • 161
  • Thanks for the research into OpenSSH, but I am asking about SSH agent protocol in general. They already load my private key, so is it possible to use this key for decryption? – anatoly techtonik Apr 14 '14 at 23:09
  • @techtonik - Updated my answer. To summarize, no, it is not possible to use the private key in ssh-agent for any purpose other than ssh authentication. This is a good thing; otherwise an attacker could extract the private key (without resorting to trying to read the memory of ssh-agent as root). – dr jimbob Apr 15 '14 at 06:09
  • Wow. Good extensive answer. So using `ssh-agent` for decryption is completely impossible with SSH2, but could be possible with SSH1 if it was patched to return bit-string instead of its hash. Why SSH1 agent can not send back decrypted challenge? Is it because of some weakness in private key decryption? – anatoly techtonik Apr 15 '14 at 08:02
  • 1
    @techtonik, if you encrypt sensitive data with your private ssh key, you wouldn't want a strong attacker (who can tamper network traffic) to be able to replace the actual sent SSH1 challenge with some sensitive document you encrypted, where ssh happily replies with decrypted document for the tamperer to steal. Would be safer to only leak the hash of the decrypted stream. Also, exposing the full ciphertext using textbook RSA opens it up to several attacks; really should do something like PKCS1v2 before using RSA key. Hashing mitigates some of the more obvious attacks. – dr jimbob Apr 15 '14 at 08:44
  • 2
    @techtonik - I should add there are other agents; e.g., gpg-agent that act similarly to ssh-agent by keeping your passphrase protected encryption keys available for reuse (for a configurable amount of time), so you don't have to keep typing them long passphrases. – dr jimbob Apr 15 '14 at 16:32
  • Yes, I wonder how `gpg-agent` work and why attacks on `ssh-agent` are not applicable to it. – anatoly techtonik Apr 18 '14 at 06:18
  • `ssh-agent` (in SSH1) was trained to automatically decrypt challenge messages presented by a potentially hostile server and send the hashes back over the internet. If it sent the original messages that would be a potential vulnerability. `gpg-agent` doesn't deal with networking directly; it decrypts/encrypts messages locally only with a key that's presumably only used to connect to SSH. – dr jimbob Apr 18 '14 at 06:32
  • I see, so it's possible that trojan may use running `gpg-agent` locally to decrypt messages. – anatoly techtonik Apr 18 '14 at 06:34
  • I came across this [ssh-crypt](https://github.com/Sets88/ssh-crypt/blob/09a0058ec9c611c054b0e6747f9cb9fda435b256/ssh_crypt/ssh_crypt.py#L162) package which derives an AES encryption key by asking the ssh-agent to sign a nonce. From what I understand, to encrypt a secret, you (1) generate a nonce, (2) connect to ssh-agent to have it sign the nonce, (3) hash the signature to derive an AES key, (4) write a file containing the nonce and the encrypted secret. To decrypt, you (1) open file and read back the nonce , (2) re-derive the same key, (3) read the encrypted secret from the file (4) decrypt. – init_js Aug 19 '22 at 07:41
  • oh. funny enough, the next answer in this thread right now is from the author of the package. woops. should have read all the answers https://security.stackexchange.com/a/142487/137828 – init_js Aug 19 '22 at 07:45
12

It is not possible to use the SSH Agent to asymmetrically decrypt data that was encrypted with the public key because the SSH Agent only exposes the ability to sign using the private key, not decrypt.

You can however use the fact that the private key in the SSH Agent is the only one who can generate a signature for something, and use that signature as a symmetric key.

I made sshcrypt to do this.

leighmcc
  • 261
  • 2
  • 4
  • 1
    I've come across this approach in other contexts. This allows some very nice workflows in terms of provisioning secrets to remote servers with ssh-agent forwarding. I'm wondering about the security of this approach though, do you have any references where the pros and cons of such an approach are discussed? (If you like I can ask a question about this...) – DrD Jun 02 '20 at 08:03
  • In the suggested approach, I think you're not really authenticating your agent when you encrypt something. You have to trust that your environment variables in your running point at an ssh-agent daemon socket address that you control. If an attacker could change your environment variables to an agent _they_ control, you'd be essentially asking the attacker's agent to generate the encryption key for you. At that point you're relying on trusting the OS and host security. You can partly mitigate this by authenticating the signature generated if you know the corresponding public key. – init_js Aug 19 '22 at 07:51
  • This is an implementation detail, but the symmetric encryption mode chosen should be an authenticated mode (like AES-CCM), otherwise you won't know after you decrypt the file whether you're looking at the original secret, or a garbage random string of the same size. – init_js Aug 19 '22 at 07:56
2

I got inspired by leighmcc's answer and implemented it in bash. The only dependencies are bash, ssh-add and openssl.

encryptFile path [seed] [pubkey-match]

The seed is used to generate the secret, and it's optional, defaulting to the empty string. You'll always generate the same secret for the same seed if you have the correct private key loaded.

w00t
  • 121
  • 3