fix(ssh): repair pasted private key material and negotiate RSA signature hash#186
Merged
Conversation
…ure hash Private-key SSH tunnel connections failed with generic errors in common setups: - russh's PEM reader matches BEGIN/END markers by exact line equality and silently drops base64 lines with stray whitespace, so keys pasted with indentation, trailing spaces, collapsed newlines, literal \n escapes, CRLF endings, or a BOM failed to decode with 'Could not read key'. Normalize key material and canonically re-fold PEM blocks before decoding (legacy encrypted PEM headers and PPK content are preserved). - The RSA signature hash was hardcoded to rsa-sha2-256, which breaks against servers that only accept ssh-rsa. Negotiate via the RFC 8308 server-sig-algs extension and keep SHA-256 as the fallback; non-RSA keys skip the negotiation. - Encrypted-key decode failures now say that a passphrase is required or hint at a wrong passphrase instead of a generic 'Invalid SSH private key'.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
SSH tunnel connections using private-key auth fail with generic errors ("Invalid SSH private key: Could not read key" / "SSH authentication failed") in several common setups.
Root causes
russh::keys::decode_secret_keymatches-----BEGIN/END ...-----markers by exact line equality and silently drops any base64 line containing a non-base64 character. A key pasted into settings with indentation, a trailing space on any line, collapsed newlines (single-line paste), literal\nescapes (copied out of JSON), CRLF endings, or a BOM fails to decode even though it looks fine in the UI. Verified against russh 0.62.2:SshKey: length invalidCould not read keyrsa-sha2-256. Servers that only accept legacyssh-rsa(old OpenSSH/embedded devices) reject the auth outright.Fix
normalize_ssh_private_key_material: strips BOM/zero-width chars, normalizes CRLF and literal\n/\r\nescapes, trims per-line whitespace, and canonically re-folds the PEM block at 64 columns. Legacy encrypted PEM (Proc-Type:/DEK-Info:headers) and PuTTY PPK content are intentionally left line-structured. Applied inresolve_ssh_auth_materialfor both pasted keys and keys read fromprivateKeyPath, so existing mangled stored keys are repaired at connect time.server-sig-algsextension (RFC 8308) viabest_supported_rsa_hash(), falling back to the previous SHA-256 behavior when the server does not advertise the extension. Non-RSA keys skip the negotiation (avoids the extension-info wait).describe_ssh_private_key_decode_errormaps decode failures to actionable messages ("key is encrypted; configure the key passphrase", "Invalid SSH private key or wrong passphrase: ...").No UI changes (backend-only), so no gateway WebUI mirror is needed. The gateway has no parallel SSH implementation; the Tauri terminal runtime is the single connect path (tunnel + SFTP).
Tests
resolve_ssh_auth_materialwith pasted and file-based keys; encrypted key with passphrase; error messages for missing/wrong passphrase.cargo test --lib→ 518 passed.cargo clippy --lib --testsintroduces no new warnings.