When computing a `rsa-sha2` signature, the signature value is not extended to the same number of octets as the key modulus. This leads to authentication failures at least for the Erlang `public_key` library.
# Description of the Bug
You can reproduce the issue as follows.
1. Enable the SSH agent of GnuPG with the `enable-ssh-support` option.
2. Setup the agent socket in your shell.
```
$ export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
```
3. Add the key `test.asc` to your keyring. It is important to reproduce the issue with the provided keys. You will find the key in the OpenSSH-Format in `test` and the corresponding public key in `test.pub`.
```
$ gpg --import test.asc
```
4. Add the keys keygrip to the `sshcontrol` file.
```
8AE5C1CD8EE6BF269E9D72A31A9C6BC7F2267406 0
```
5. Check for the key to be present in the agent.
```
$ ssh-add -l
3072 SHA256:m7ZbRbJqW/0T7eWLX6pTGvw/yv1r+wEJTVB75RwDjx8 test (RSA)
```
6. Compute two signatures with the `paramiko` Python package.
```python
import paramiko
a = paramiko.agent.Agent()
k = a.get_keys()[0]
sig = k.sign_ssh_data(bytes([ 196 ]), algorithm='rsa-sha2-256')
print(len(sig[20:]))
with open("196.bin", "wb") as f:
f.write(sig[20:])
sig = k.sign_ssh_data(bytes([ 197 ]), algorithm='rsa-sha2-256')
print(len(sig[20:]))
with open("197.bin", "wb") as f:
f.write(sig[20:])
```
The term `[20:]` extracts the raw signature value from the agent protocol. The output was written to the files `196.bin` and `197.bin`. You will find that the signature `197.bin` just consists of 383 octets whereas `196.bin` consists of 384 octets which matches the key modulus length of 3072 bits.
```
$ ls -l 196.bin 197.bin
-rw-r--r-- 1 demo demo 384 27. Okt 12:07 196.bin
-rw-r--r-- 1 demo demo 383 27. Okt 12:33 197.bin
```
It's because the 8 most significant bits of the signature value in the latter case are all zero und thus truncated in the output. If this case occurs during an authentication attempt, the Erlang library will refuse it with an error message.
RFC 8332 section 3 specifies the format of the SSH signature `rsa-sha2-256` and `rsa-sha2-512`:
> The resulting signature is encoded as follows:
>
> string "rsa-sha2-256" / "rsa-sha2-512"
> string rsa_signature_blob
>
> The value for 'rsa_signature_blob' is encoded as a string that
> contains an octet string S (which is the output of RSASSA-PKCS1-v1_5)
> and that has the same length (in octets) as the RSA modulus. When S
> contains leading zeros, there exist signers that will send a shorter
> encoding of S that omits them. A verifier MAY accept shorter
> encodings of S with one or more leading zeros omitted.
It specifies the signature encoding must have the same number of octets as the key modulus. Supporting truncated values is truly optional and cannot be relied on.
In contrast for `ssh-rsa` signatures, RFC 4253 specifies in section 6.6 for the signature encoding that it must not have any padding.
> The resulting signature is encoded as follows:
>
> string "ssh-rsa"
> string rsa_signature_blob
>
> The value for 'rsa_signature_blob' is encoded as a string containing
> s (which is an integer, without lengths or padding, unsigned, and in
> network byte order).
So in this case, truncating leading 0-bytes should still be mandatory.
* {F31157079}
* {F31157158}
* {F31157224}
* {F31160634}
* {F31160633}
* {F31160632}
* {F31160631}
# Related information
If you load the same key into the OpenSSH agent ...
```
$ unset SSH_AUTH_SOCK
$ eval $(ssh-agent)
$ ssh-add test
Identity added: test (test)
```
... and perform step 6 again, you will get a the same signature, but with a leading 0-byte in the latter case.
# Proposed resolution
Signature values for `rsa-sha2-256` and `rsa-sha2-512` should be extended to the length of the key modulus.