diff --git a/api/crypto/ecdsa.go b/api/crypto/ecdsa.go index 35cc0b283..210b65bd7 100644 --- a/api/crypto/ecdsa.go +++ b/api/crypto/ecdsa.go @@ -7,6 +7,8 @@ import ( "crypto/x509" "encoding/base64" "encoding/hex" + "encoding/pem" + "golang.org/x/crypto/ssh" "math/big" ) @@ -135,3 +137,28 @@ func (service *ECDSAService) CreateSignature(message string) (string, error) { return base64.RawStdEncoding.EncodeToString(signature), nil } + +// GenerateDeploymentKeyPair will create a new PEM encoded key pairs with ECDSA. +func (service *ECDSAService) GenerateDeploymentKeyPair() ([]byte, string, error) { + pubkeyCurve := elliptic.P256() + + privateKey, err := ecdsa.GenerateKey(pubkeyCurve, rand.Reader) + if err != nil { + return nil, "", err + } + + x509EncodedBytes, _ := x509.MarshalECPrivateKey(privateKey) + if err != nil { + return nil, "", err + } + + pemEncodedPrivate := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: x509EncodedBytes}) + + publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + return nil, "", err + } + publicKeyAutorizedKey := ssh.MarshalAuthorizedKey(publicKey) + + return pemEncodedPrivate, string(publicKeyAutorizedKey), nil +} diff --git a/api/http/handler/deploymentkeys/deploymentkey_create.go b/api/http/handler/deploymentkeys/deploymentkey_create.go index da60a3084..c79eb8d40 100644 --- a/api/http/handler/deploymentkeys/deploymentkey_create.go +++ b/api/http/handler/deploymentkeys/deploymentkey_create.go @@ -38,10 +38,15 @@ func (handler *Handler) deploymentkeyCreate(w http.ResponseWriter, r *http.Reque // Add a function to call and create public key and private key + private, public, err := handler.SignatureService.GenerateDeploymentKeyPair() + if err != nil { + return &httperror.HandlerError{http.StatusInternalServerError, "Unable to create private and public key pairs", err} + } + deploymentkey = &portainer.DeploymentKey{ Name: payload.Name, - PublicKey: "SHA256:hellotherepublic", - PrivateKey: "SHA256:hellothereprivate", + PublicKey: public, + PrivateKey: private, } err = handler.DeploymentKeyService.CreateDeploymentKey(deploymentkey) @@ -49,7 +54,7 @@ func (handler *Handler) deploymentkeyCreate(w http.ResponseWriter, r *http.Reque return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist the deployment key inside the database", err} } - hideFields(deploymentkey) + // hideFields(deploymentkey) return response.JSON(w, deploymentkey) } diff --git a/api/http/handler/deploymentkeys/handler.go b/api/http/handler/deploymentkeys/handler.go index 125039757..d93ee35a0 100644 --- a/api/http/handler/deploymentkeys/handler.go +++ b/api/http/handler/deploymentkeys/handler.go @@ -13,10 +13,11 @@ import ( type Handler struct { *mux.Router DeploymentKeyService portainer.DeploymentKeyService + SignatureService portainer.DigitalSignatureService } func hideFields(deploymentkey *portainer.DeploymentKey) { - deploymentkey.PrivateKey = "" + deploymentkey.PrivateKey = nil } // NewHandler creates a handler to manage settings operations. diff --git a/api/http/server.go b/api/http/server.go index d735a184f..d7ceba92b 100644 --- a/api/http/server.go +++ b/api/http/server.go @@ -226,6 +226,7 @@ func (server *Server) Start() error { var deploymentKeyHandler = deploymentkeys.NewHandler(requestBouncer) deploymentKeyHandler.DeploymentKeyService = server.DeploymentKeyService + deploymentKeyHandler.SignatureService = server.SignatureService server.Handler = &handler.Handler{ RoleHandler: roleHandler, diff --git a/api/portainer.go b/api/portainer.go index a3875f7d5..e79eb6e19 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -225,7 +225,7 @@ type ( ID DeploymentKeyID `json:"Id` Name string `json:"Name"` PublicKey string `json:"PublicKey"` - PrivateKey string `json:"PrivateKey"` + PrivateKey []byte `json:"PrivateKey"` } // DockerHub represents all the required information to connect and use the @@ -778,6 +778,7 @@ type ( DigitalSignatureService interface { ParseKeyPair(private, public []byte) error GenerateKeyPair() ([]byte, []byte, error) + GenerateDeploymentKeyPair() ([]byte, string, error) EncodedPublicKey() string PEMHeaders() (string, string) CreateSignature(message string) (string, error)