diff --git a/ssh/clientkeys.go b/ssh/clientkeys.go index c4aef1f9..d7969437 100644 --- a/ssh/clientkeys.go +++ b/ssh/clientkeys.go @@ -17,7 +17,7 @@ import ( "github.com/juju/utils/v4" ) -const clientKeyName = "juju_id_rsa" +const clientKeyName = "juju_id_ed25519" // PublicKeySuffix is the file extension for public key files. const PublicKeySuffix = ".pub" diff --git a/ssh/clientkeys_test.go b/ssh/clientkeys_test.go index bca37086..aac29cd2 100644 --- a/ssh/clientkeys_test.go +++ b/ssh/clientkeys_test.go @@ -9,9 +9,10 @@ import ( gitjujutesting "github.com/juju/testing" jc "github.com/juju/testing/checkers" + gc "gopkg.in/check.v1" + "github.com/juju/utils/v4" "github.com/juju/utils/v4/ssh" - gc "gopkg.in/check.v1" ) type ClientKeysSuite struct { @@ -23,7 +24,7 @@ var _ = gc.Suite(&ClientKeysSuite{}) func (s *ClientKeysSuite) SetUpTest(c *gc.C) { s.FakeHomeSuite.SetUpTest(c) s.AddCleanup(func(*gc.C) { ssh.ClearClientKeys() }) - generateKeyRestorer := overrideGenerateKey(c) + generateKeyRestorer := overrideGenerateKey() s.AddCleanup(func(*gc.C) { generateKeyRestorer.Restore() }) } @@ -51,7 +52,7 @@ func (s *ClientKeysSuite) TestPublicKeyFiles(c *gc.C) { // and populate it with a key pair. err := ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, jc.ErrorIsNil) - checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub") + checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_ed25519.pub") // All files ending with .pub in the client key dir get picked up. priv, pub, err := ssh.GenerateKey("whatever") c.Assert(err, jc.ErrorIsNil) @@ -61,12 +62,12 @@ func (s *ClientKeysSuite) TestPublicKeyFiles(c *gc.C) { c.Assert(err, jc.ErrorIsNil) // The new public key won't be observed until the // corresponding private key exists. - checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub") + checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_ed25519.pub") err = ioutil.WriteFile(gitjujutesting.HomePath(".juju", "ssh", "whatever"), []byte(priv), 0600) c.Assert(err, jc.ErrorIsNil) err = ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, jc.ErrorIsNil) - checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub", "~/.juju/ssh/whatever.pub") + checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_ed25519.pub", "~/.juju/ssh/whatever.pub") } func (s *ClientKeysSuite) TestPrivateKeyFiles(c *gc.C) { @@ -75,7 +76,7 @@ func (s *ClientKeysSuite) TestPrivateKeyFiles(c *gc.C) { // unless LoadClientKeys is called again. err := ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, jc.ErrorIsNil) - checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa") + checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_ed25519") priv, pub, err := ssh.GenerateKey("whatever") c.Assert(err, jc.ErrorIsNil) err = ioutil.WriteFile(gitjujutesting.HomePath(".juju", "ssh", "whatever"), []byte(priv), 0600) @@ -84,16 +85,16 @@ func (s *ClientKeysSuite) TestPrivateKeyFiles(c *gc.C) { c.Assert(err, jc.ErrorIsNil) // The new private key won't be observed until the // corresponding public key exists. - checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa") + checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_ed25519") err = ioutil.WriteFile(gitjujutesting.HomePath(".juju", "ssh", "whatever.pub"), []byte(pub), 0600) c.Assert(err, jc.ErrorIsNil) // new keys won't be reported until we call LoadClientKeys again - checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub") - checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa") + checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_ed25519.pub") + checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_ed25519") err = ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, jc.ErrorIsNil) - checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub", "~/.juju/ssh/whatever.pub") - checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa", "~/.juju/ssh/whatever") + checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_ed25519.pub", "~/.juju/ssh/whatever.pub") + checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_ed25519", "~/.juju/ssh/whatever") } func (s *ClientKeysSuite) TestLoadClientKeysDirExists(c *gc.C) { @@ -101,5 +102,5 @@ func (s *ClientKeysSuite) TestLoadClientKeysDirExists(c *gc.C) { c.Assert(err, jc.ErrorIsNil) err = ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, jc.ErrorIsNil) - checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa") + checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_ed25519") } diff --git a/ssh/generate.go b/ssh/generate.go index 280158fd..235ae46f 100644 --- a/ssh/generate.go +++ b/ssh/generate.go @@ -6,7 +6,6 @@ package ssh import ( "crypto/ed25519" "crypto/rand" - "crypto/x509" "encoding/pem" "fmt" "strings" @@ -28,15 +27,11 @@ func GenerateKey(comment string) (private, public string, err error) { return "", "", errors.Trace(err) } - keyData, err := x509.MarshalPKCS8PrivateKey(privateKey) + pemBlock, err := ssh.MarshalPrivateKey(privateKey, comment) if err != nil { return "", "", errors.Trace(err) } - identity := pem.EncodeToMemory( - &pem.Block{ - Type: "PRIVATE KEY", - Bytes: keyData, - }) + identity := pem.EncodeToMemory(pemBlock) public, err = PublicKey(identity, comment) if err != nil { diff --git a/ssh/generate_test.go b/ssh/generate_test.go index 4fae71e1..ac305f50 100644 --- a/ssh/generate_test.go +++ b/ssh/generate_test.go @@ -27,7 +27,7 @@ var ( // overrideGenerateKey patches out rsa.GenerateKey to create a single testing // key which is saved and used between tests to save computation time. -func overrideGenerateKey(c *gc.C) testing.Restorer { +func overrideGenerateKey() testing.Restorer { restorer := testing.PatchValue(ssh.ED25519GenerateKey, func(random io.Reader) (ed25519.PublicKey, ed25519.PrivateKey, error) { if pregeneratedKey != nil { return ed25519.PublicKey{}, pregeneratedKey, nil @@ -63,11 +63,11 @@ func generateDSAKey(random io.Reader) (*dsa.PrivateKey, error) { } func (s *GenerateSuite) TestGenerate(c *gc.C) { - defer overrideGenerateKey(c).Restore() + defer overrideGenerateKey().Restore() private, public, err := ssh.GenerateKey("some-comment") c.Check(err, jc.ErrorIsNil) - c.Check(private, jc.HasPrefix, "-----BEGIN PRIVATE KEY-----\n") - c.Check(private, jc.HasSuffix, "-----END PRIVATE KEY-----\n") + c.Check(private, jc.HasPrefix, "-----BEGIN OPENSSH PRIVATE KEY-----\n") + c.Check(private, jc.HasSuffix, "-----END OPENSSH PRIVATE KEY-----\n") c.Check(public, jc.HasPrefix, "ssh-ed25519 ") c.Check(public, jc.HasSuffix, " some-comment\n") } diff --git a/ssh/ssh_gocrypto_test.go b/ssh/ssh_gocrypto_test.go index 344a6d4e..3a2196d8 100644 --- a/ssh/ssh_gocrypto_test.go +++ b/ssh/ssh_gocrypto_test.go @@ -180,7 +180,7 @@ func (s *SSHGoCryptoCommandSuite) SetUpSuite(c *gc.C) { func (s *SSHGoCryptoCommandSuite) SetUpTest(c *gc.C) { s.IsolationSuite.SetUpTest(c) - generateKeyRestorer := overrideGenerateKey(c) + generateKeyRestorer := overrideGenerateKey() s.AddCleanup(func(*gc.C) { generateKeyRestorer.Restore() }) client, err := ssh.NewGoCryptoClient() diff --git a/ssh/ssh_test.go b/ssh/ssh_test.go index 10bf6520..751dca4f 100644 --- a/ssh/ssh_test.go +++ b/ssh/ssh_test.go @@ -205,12 +205,12 @@ func (s *SSHCommandSuite) TestCopy(c *gc.C) { } func (s *SSHCommandSuite) TestCommandClientKeys(c *gc.C) { - defer overrideGenerateKey(c).Restore() + defer overrideGenerateKey().Restore() clientKeysDir := c.MkDir() defer ssh.ClearClientKeys() err := ssh.LoadClientKeys(clientKeysDir) c.Assert(err, jc.ErrorIsNil) - ck := filepath.Join(clientKeysDir, "juju_id_rsa") + ck := filepath.Join(clientKeysDir, "juju_id_ed25519") var opts ssh.Options opts.SetIdentities("x", "y") s.assertCommandArgs(c, s.commandOptions([]string{echoCommand, "123"}, &opts),