-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enforce SHA-512 for RSA SSH signatures
Motivation: x/crypto/ssh defaults to using SHA-1 for signatures: https://github.com/golang/crypto/blob/master/ssh/keys.go#L963-L982 Because Teleport uses RSA for user, host and CA keys, we end up with SHA-1 by default. SHA-1 is now considered weak and OpenSSH plans to deprecate it: https://www.openssh.com/txt/release-8.3 Fix: Wrap all RSA `ssh.Signer`s and override `SignWithAlgorithm` to provide `SigAlgoRSASHA2512` if not otherwise specified. This will only affect new certs, existing certs will use `SigAlgoRSA` until rotated. For CA certs (e.g. exported with `tctl auth export`) users might need to manually rotate. Limited local testing with openssh 8.2 client and `-oHostKeyAlgorithms=-ssh-rsa` confirms that this works with a new cluster and fails with an old one.
- Loading branch information
Andrew Lytvynov
committed
May 27, 2020
1 parent
aa4f74f
commit 07a2150
Showing
10 changed files
with
134 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package sshutils | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"crypto/elliptic" | ||
"crypto/rand" | ||
"crypto/rsa" | ||
"io" | ||
|
||
"golang.org/x/crypto/ssh" | ||
"gopkg.in/check.v1" | ||
) | ||
|
||
type CompatSignerSuite struct{} | ||
|
||
var _ = check.Suite(&CompatSignerSuite{}) | ||
|
||
func (s *CompatSignerSuite) TestCompatSignerNoop(c *check.C) { | ||
ecdsaKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) | ||
c.Assert(err, check.IsNil) | ||
ecdsaSigner, err := ssh.NewSignerFromSigner(ecdsaKey) | ||
c.Assert(err, check.IsNil) | ||
|
||
// ECDSA key should be returned as-is, not wrapped. | ||
c.Assert(CompatSigner(ecdsaSigner), check.Equals, ecdsaSigner) | ||
} | ||
|
||
func (s *CompatSignerSuite) TestCompatSigner(c *check.C) { | ||
rsaSigner, err := newMockRSASigner() | ||
c.Assert(err, check.IsNil) | ||
|
||
wrapped := CompatSigner(rsaSigner) | ||
// RSA key should get wrapped. | ||
c.Assert(wrapped, check.Not(check.Equals), rsaSigner) | ||
wrappedAS := wrapped.(ssh.AlgorithmSigner) | ||
|
||
// Simple Sign call should use the enforced SHA-2 algorithm. | ||
wrapped.Sign(nil, nil) | ||
c.Assert(rsaSigner.lastAlg, check.Equals, ssh.SigAlgoRSASHA2512) | ||
rsaSigner.lastAlg = "" | ||
|
||
// SignWithAlgorithm without specifying an algorithm should use the | ||
// enforced SHA-2 algorithm. | ||
wrappedAS.SignWithAlgorithm(nil, nil, "") | ||
c.Assert(rsaSigner.lastAlg, check.Equals, ssh.SigAlgoRSASHA2512) | ||
rsaSigner.lastAlg = "" | ||
|
||
// SignWithAlgorithm *with* an algorithm should respect the provided | ||
// algorithm. | ||
wrappedAS.SignWithAlgorithm(nil, nil, "foo") | ||
c.Assert(rsaSigner.lastAlg, check.Equals, "foo") | ||
} | ||
|
||
type mockRSASigner struct { | ||
ssh.Signer | ||
lastAlg string | ||
} | ||
|
||
func newMockRSASigner() (*mockRSASigner, error) { | ||
rsaKey, err := rsa.GenerateKey(rand.Reader, 2056) | ||
if err != nil { | ||
return nil, err | ||
} | ||
rsaSigner, err := ssh.NewSignerFromSigner(rsaKey) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &mockRSASigner{Signer: rsaSigner}, nil | ||
} | ||
|
||
func (s *mockRSASigner) SignWithAlgorithm(rand io.Reader, data []byte, alg string) (*ssh.Signature, error) { | ||
s.lastAlg = alg | ||
return nil, nil | ||
} |
This file contains 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