Skip to content

Pad the DH public key to 128 bytes when opening an encrypted session - #1

Closed
Hue-215 wants to merge 1 commit into
brotskydotcom:mainfrom
Hue-215:pad-dh-public-key
Closed

Hue-215 wants to merge 1 commit into
brotskydotcom:mainfrom
Hue-215:pad-dh-public-key

Conversation

@Hue-215

@Hue-215 Hue-215 commented Oct 4, 2026

Copy link
Copy Markdown

Session::new sends the client's DH public key as keypair.public.to_bytes_be(), which drops leading zero bytes. About 1 in 256 freshly generated keys therefore goes out as 127 bytes or fewer.

KWallet's Secret Service daemon (ksecretd) before 6.25.0 rejects public keys shorter than 128 bytes with Client public key size is invalid. So against those versions, about 0.4% of SecretService::connect(EncryptionType::Dh) calls fail at random. Distributions still ship them, e.g. Ubuntu 26.04 LTS has kwallet6 6.24.0. KDE removed the check in kwallet 307db62 (bug 514194), but older installs will be around for a while.

This change pads the public key to the 1024-bit group size (128 bytes), the same way derive_shared already pads the shared secret. Leading zeros don't change the value for services that read the key as an unsigned big-endian integer, as libsecret's DH code does.

Testing

  • Added a unit test for the padding; it passes with both crypto-rust and crypto-openssl.

  • Ran 3000 encrypted sessions against ksecretd 6.24.0 (through dbus-secret-service-keyring-store 1.0.1):

    sessions Client public key size is invalid
    before 5051 24
    after 3000 0

ksecretd 6.24.0 has two more bugs in the same handshake, and they still cause occasional Unpad Errors. It doesn't pad the shared secret, and it reads the client key as a signed integer. Both are server-side, and the same KDE commit fixes them, so this PR doesn't try to work around them.

`to_bytes_be()` drops leading zero bytes, so about 1 in 256 public keys
was sent short. KWallet's ksecretd before 6.25.0 rejects such keys with
"Client public key size is invalid". Pad the key to the group size, as
`derive_shared` already does for the shared secret.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant