ssh: respect signer's algorithm preference in pickSignatureAlgorithm
Previously, pickSignatureAlgorithm constructed the list of candidate
algorithms by iterating over the static list returned by
algorithmsForKeyFormat. This caused the Signer's preference order
to be ignored in favor of the library's default internal order.
This change inverts the filtering logic to iterate over the signer's
supported algorithms first. This ensures that if a MultiAlgorithmSigner
explicitly prefers a specific algorithm (e.g., rsa-sha2-512 over
rsa-sha2-256), that preference is preserved and respected during the
handshake negotiation.
Fixes golang/go#77585
diff --git a/ssh/client_auth.go b/ssh/client_auth.go
index 3127e49..bf3d03e 100644
--- a/ssh/client_auth.go
+++ b/ssh/client_auth.go
@@ -275,9 +275,14 @@
// Filter algorithms based on those supported by MultiAlgorithmSigner.
var keyAlgos []string
- for _, algo := range algorithmsForKeyFormat(keyFormat) {
- if slices.Contains(as.Algorithms(), underlyingAlgo(algo)) {
- keyAlgos = append(keyAlgos, algo)
+ supportedKeyAlgos := algorithmsForKeyFormat(keyFormat)
+
+ for _, signerAlgo := range as.Algorithms() {
+ for _, algo := range supportedKeyAlgos {
+ if underlyingAlgo(algo) == signerAlgo {
+ keyAlgos = append(keyAlgos, algo)
+ break
+ }
}
}
diff --git a/ssh/client_auth_test.go b/ssh/client_auth_test.go
index a183c21..199d207 100644
--- a/ssh/client_auth_test.go
+++ b/ssh/client_auth_test.go
@@ -1159,6 +1159,52 @@
}
}
+func TestPickSignatureAlgorithmRespectsSignerPreference(t *testing.T) {
+ algoSigner, ok := testSigners["rsa"].(AlgorithmSigner)
+ if !ok {
+ t.Fatalf("rsa test signer does not implement the AlgorithmSigner interface")
+ }
+
+ serverExtensions := map[string][]byte{
+ "server-sig-algs": []byte(KeyAlgoRSASHA256 + "," + KeyAlgoRSASHA512),
+ }
+
+ tests := []struct {
+ name string
+ signerPrefs []string
+ expectedAlgo string
+ }{
+ {
+ name: "Signer prefers SHA512 then SHA256",
+ signerPrefs: []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256},
+ expectedAlgo: KeyAlgoRSASHA512,
+ },
+ {
+ name: "Signer prefers SHA256 then SHA512",
+ signerPrefs: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512},
+ expectedAlgo: KeyAlgoRSASHA256,
+ },
+ }
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ orderedSigner, err := NewSignerWithAlgorithms(algoSigner, tc.signerPrefs)
+ if err != nil {
+ t.Fatalf("failed to create ordered signer: %v", err)
+ }
+
+ _, selectedAlgo, err := pickSignatureAlgorithm(orderedSigner, serverExtensions)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+
+ if selectedAlgo != tc.expectedAlgo {
+ t.Errorf("Algorithm mismatch; got %q want %q", selectedAlgo, tc.expectedAlgo)
+ }
+ })
+ }
+}
+
// configurablePublicKeyCallback is a public key callback that allows to
// configure the signature algorithm and format. This way we can emulate the
// behavior of buggy clients.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Code-Review | +1 |
Fixes golang/go#77585This issue is currently marked as a [proposal](https://go.dev/s/proposal). If this change is indeed in scope of the proposal process, this CL shouldn't be submitted before the proposal is accepted.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Fixes golang/go#77585This issue is currently marked as a [proposal](https://go.dev/s/proposal). If this change is indeed in scope of the proposal process, this CL shouldn't be submitted before the proposal is accepted.
I originally proposed prioritizing rsa-sha2-512 by default. During the discussion, it was noted that users should be able to customize the order via the Algorithms() []string method. However, I discovered that the custom ordering is currently not taking effect, which is a bug. This CL is intended to fix that issue. Given this is a bug fix for existing functionality, is it possible to reclassify the issue from a proposal to a bug?
Fixes golang/go#77585Lonny WongThis issue is currently marked as a [proposal](https://go.dev/s/proposal). If this change is indeed in scope of the proposal process, this CL shouldn't be submitted before the proposal is accepted.
I originally proposed prioritizing rsa-sha2-512 by default. During the discussion, it was noted that users should be able to customize the order via the Algorithms() []string method. However, I discovered that the custom ordering is currently not taking effect, which is a bug. This CL is intended to fix that issue. Given this is a bug fix for existing functionality, is it possible to reclassify the issue from a proposal to a bug?
Yes, fixing a bug doesn't need a proposal. It sounds like you should either update #746020 to describe the bug instead of the original proposal, or if the original proposal should still be pursued then file a separate issue for the bug and this CL can be updated to target it instead.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |