From 7934e62c93e2633e2340657bdd4ea3b126301356 Mon Sep 17 00:00:00 2001 From: braginini Date: Sat, 4 Jun 2022 22:09:25 +0200 Subject: [PATCH] Add hostkey to the ssh server --- client/ssh/server.go | 54 +++++++++++++------------------------------- client/ssh/ssh.go | 52 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 38 deletions(-) create mode 100644 client/ssh/ssh.go diff --git a/client/ssh/server.go b/client/ssh/server.go index ea89e7427..7eb9c5000 100644 --- a/client/ssh/server.go +++ b/client/ssh/server.go @@ -1,8 +1,6 @@ -package main +package ssh import ( - "crypto/rand" - "crypto/rsa" "fmt" "github.com/gliderlabs/ssh" gossh "golang.org/x/crypto/ssh" @@ -16,6 +14,16 @@ type Server struct { listener net.Listener allowedKeys map[string]ssh.PublicKey mu sync.Mutex + hostKeyPEM []byte +} + +// NewSSHServer creates new server with provided host key +func NewSSHServer(hostKeyPEM []byte) (*Server, error) { + ln, err := net.Listen("tcp", ":2222") + if err != nil { + return nil, err + } + return &Server{listener: ln, mu: sync.Mutex{}, hostKeyPEM: hostKeyPEM}, nil } func (srv *Server) UpdateKeys(newKeys []string) error { @@ -34,14 +42,6 @@ func (srv *Server) UpdateKeys(newKeys []string) error { return nil } -func NewSSHServer() (*Server, error) { - ln, err := net.Listen("tcp", ":2222") - if err != nil { - return nil, err - } - return &Server{listener: ln, mu: sync.Mutex{}}, nil -} - // Stop stops SSH server. Blocking func (srv *Server) Stop() error { err := srv.listener.Close() @@ -73,7 +73,9 @@ func (srv *Server) Start() error { return false }) - err := ssh.Serve(srv.listener, handler, publicKeyOption) + hostKeyPEM := ssh.HostKeyPEM(srv.hostKeyPEM) + + err := ssh.Serve(srv.listener, handler, publicKeyOption, hostKeyPEM) if err != nil { return err } @@ -83,7 +85,8 @@ func (srv *Server) Start() error { func main() { - server, err := NewSSHServer() + strKey := "-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n" + server, err := NewSSHServer([]byte(strKey)) if err != nil { return } @@ -98,28 +101,3 @@ func main() { // will throw error when Stop has been called } } - -// generatePrivateKey creates RSA Private Key of specified byte size -func generatePrivateKey(bitSize int) (*rsa.PrivateKey, error) { - privateKey, err := rsa.GenerateKey(rand.Reader, bitSize) - if err != nil { - return nil, err - } - - err = privateKey.Validate() - if err != nil { - return nil, err - } - - return privateKey, nil -} - -// generatePublicKey takes a rsa.PublicKey and return bytes suitable for writing to .pub file -// returns the key in format format "ssh-rsa ..." -func generatePublicKey(privateKey *rsa.PublicKey) ([]byte, error) { - publicRsaKey, err := gossh.NewPublicKey(privateKey) - if err != nil { - return nil, err - } - return gossh.MarshalAuthorizedKey(publicRsaKey), nil -} diff --git a/client/ssh/ssh.go b/client/ssh/ssh.go new file mode 100644 index 000000000..4998f9119 --- /dev/null +++ b/client/ssh/ssh.go @@ -0,0 +1,52 @@ +package ssh + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + gossh "golang.org/x/crypto/ssh" +) + +// GeneratePrivateKey creates RSA Private Key of specified byte size +func GeneratePrivateKey(bitSize int) (*rsa.PrivateKey, error) { + privateKey, err := rsa.GenerateKey(rand.Reader, bitSize) + if err != nil { + return nil, err + } + + err = privateKey.Validate() + if err != nil { + return nil, err + } + + return privateKey, nil +} + +// GeneratePublicKey takes a rsa.PublicKey and return bytes suitable for writing to .pub file +// returns the key in format format "ssh-rsa ..." +func GeneratePublicKey(privateKey *rsa.PublicKey) ([]byte, error) { + publicRsaKey, err := gossh.NewPublicKey(privateKey) + if err != nil { + return nil, err + } + return gossh.MarshalAuthorizedKey(publicRsaKey), nil +} + +// EncodePrivateKeyToPEM encodes Private Key from RSA to PEM format +func EncodePrivateKeyToPEM(privateKey *rsa.PrivateKey) []byte { + // Get ASN.1 DER format + privDER := x509.MarshalPKCS1PrivateKey(privateKey) + + // pem.Block + privBlock := pem.Block{ + Type: "RSA PRIVATE KEY", + Headers: nil, + Bytes: privDER, + } + + // Private key in PEM format + privatePEM := pem.EncodeToMemory(&privBlock) + + return privatePEM +}