Skip to content

SSH Agent signs all RSA Keys with sha512, regardless of what was asked #16681

@LelouBil

Description

@LelouBil

Steps To Reproduce

  1. Import an RSA SSH Key into Bitwarden
  2. Enable the SSH-Agent
  3. Try to use the key with openssh, when it is requesting a sign using rsa-sha2-256 (I don't know how to force this for now, but if you do ssh -vvv it should say "debug3: sign_and_send_pubkey: signing using rsa-sha2-256")

Expected Result

A successful connection

Actual Result

The connection fails with
"agent key RSA SHA256: returned incorrect signature type
sign_and_send_pubkey: no mutual signature supported"

Screenshots or Videos

No response

Additional Context

So I actually tracked down the issue exactly, here is the relevant information :

I retraced the whole key signing code flow and it becomes clear what happens :

First, the key is constructed here :

fn parse_key_safe(pem: &str) -> Result<ssh_key::private::PrivateKey, anyhow::Error> {

and put in the BitwardenSshKey struct, the actual private key is a ssh_key::private::PrivateKey struct (important because in the agent library its refered as a dyn ssh_key::SigningKey)

Then, in the agent library, the function call to sign data with the key is here :

https://github.com/bitwarden/bitwarden-russh/blob/a641316227227f8777fdf56ac9fa2d6b5f7fe662/src/ssh_agent.rs#L240

It's a trait method, so we can follow to the implementation for ssh_key::private::PrivateKey (since we know the type by looking at the bitwarden/clients code

Here is the implementation :

https://github.com/RustCrypto/SSH/blob/bea6fe42a47089c0b35879ef69e632ad256f145f/ssh-key/src/signature.rs#L273-L294

Nothing, special, it just forwards based on the enabled features and the key type. (it extracts the KeyPairData and calls try_sign on the keypair value inside of KeyPairData)

For RSA Keys, the keypair value of KeyPairData is of type RsaKeypair, and look at it's signing implementation :

https://github.com/RustCrypto/SSH/blob/bea6fe42a47089c0b35879ef69e632ad256f145f/ssh-key/src/signature.rs#L664-L678

It always makes a signature with sha512 !

So actually the code changed here
RustCrypto/SSH@26d482b
and now allows to make sha-1 or sha-256 signatures, so you would need to upgrade the ssh-key version, and also special case RSA keys.

However, the ssh-agent specification has a "flags" field right after the data to be signed, that specifies extra properties for RSA keys :

You can see the "flags" field here and the special RSA flags in 4.5.1 right below
https://www.ietf.org/archive/id/draft-miller-ssh-agent-07.html#name-private-key-operations

And the corresponding values here (bit flags) :
https://www.ietf.org/archive/id/draft-miller-ssh-agent-07.html#name-signature-flags-2

And so there is also an issue with the code in bitwarden-russh because it doesn't read this field at all.

So, Finally, a summary of what to do :

  1. Upgrade ssh-key in bitwarden-russh (I don't know if you're okay depending on release candidates or want to wait for the full 0.7.0, but in any case you need at least 0.7.0-rc.0)
  2. In bitwarden-russh, change the type of the private_key() method in the SshKey trait to return a full PrivateKey struct (from ssh-key)
  3. In bitwarden-russh also depend on the "signature" crate to be able to use the "Signer" trait
  4. Parse the flags field
  5. if the key is RSA, and there are flags, call the correct signing method.

I have a small PR for bitwarden-russh, but some other code broke after upgrading ssh-key and I don't know how to fix it for now.

Operating System

Linux

Operating System Version

Fedora 42

Installation method

Flatpak

Build Version

tested on latest commit as well (7b94d6a at time of writing)

Issue Tracking Info

  • I understand that work is tracked outside of GitHub. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions