diff --git a/cmd/ssh-chat/cmd.go b/cmd/ssh-chat/cmd.go index 7d76783..bd89b19 100644 --- a/cmd/ssh-chat/cmd.go +++ b/cmd/ssh-chat/cmd.go @@ -112,14 +112,9 @@ func main() { } } - privateKey, err := ReadPrivateKey(privateKeyPath) + signer, err := ReadPrivateKey(privateKeyPath) if err != nil { - fail(2, "Couldn't read private key: %v\n", err) - } - - signer, err := ssh.ParsePrivateKey(privateKey) - if err != nil { - fail(3, "Failed to parse key: %v\n", err) + fail(3, "Failed to read identity private key: %v\n", err) } auth := sshchat.NewAuth() diff --git a/cmd/ssh-chat/key.go b/cmd/ssh-chat/key.go index e7135a9..470efa4 100644 --- a/cmd/ssh-chat/key.go +++ b/cmd/ssh-chat/key.go @@ -1,50 +1,37 @@ package main import ( - "crypto/x509" - "encoding/pem" "fmt" "io/ioutil" "os" "github.com/howeyc/gopass" + "golang.org/x/crypto/ssh" ) // ReadPrivateKey attempts to read your private key and possibly decrypt it if it // requires a passphrase. // This function will prompt for a passphrase on STDIN if the environment variable (`IDENTITY_PASSPHRASE`), // is not set. -func ReadPrivateKey(path string) ([]byte, error) { +func ReadPrivateKey(path string) (ssh.Signer, error) { privateKey, err := ioutil.ReadFile(path) if err != nil { return nil, fmt.Errorf("failed to load identity: %v", err) } - block, rest := pem.Decode(privateKey) - if len(rest) > 0 { - return nil, fmt.Errorf("extra data when decoding private key") - } - if !x509.IsEncryptedPEMBlock(block) { - return privateKey, nil - } - - passphrase := []byte(os.Getenv("IDENTITY_PASSPHRASE")) - if len(passphrase) == 0 { - fmt.Print("Enter passphrase: ") - passphrase, err = gopass.GetPasswd() - if err != nil { - return nil, fmt.Errorf("couldn't read passphrase: %v", err) + pk, err := ssh.ParsePrivateKey(privateKey) + if err == nil { + } else if _, ok := err.(*ssh.PassphraseMissingError); ok { + passphrase := []byte(os.Getenv("IDENTITY_PASSPHRASE")) + if len(passphrase) == 0 { + fmt.Print("Enter passphrase: ") + passphrase, err = gopass.GetPasswd() + if err != nil { + return nil, fmt.Errorf("couldn't read passphrase: %v", err) + } } - } - der, err := x509.DecryptPEMBlock(block, passphrase) - if err != nil { - return nil, fmt.Errorf("decrypt failed: %v", err) + return ssh.ParsePrivateKeyWithPassphrase(privateKey, passphrase) } - privateKey = pem.EncodeToMemory(&pem.Block{ - Type: block.Type, - Bytes: der, - }) - - return privateKey, nil + return pk, err } diff --git a/go.mod b/go.mod index 447b14d..edc6d42 100644 --- a/go.mod +++ b/go.mod @@ -2,11 +2,11 @@ module github.com/shazow/ssh-chat require ( github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58 - github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c + github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c github.com/jessevdk/go-flags v1.4.0 - github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1 - golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576 - golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54 + github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 + golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 + golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f golang.org/x/text v0.3.2 ) diff --git a/go.sum b/go.sum index 52d7b84..8ef74f9 100644 --- a/go.sum +++ b/go.sum @@ -2,15 +2,27 @@ github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58 h1:MkpmYfld/S8kXqTY github.com/alexcesaro/log v0.0.0-20150915221235-61e686294e58/go.mod h1:YNfsMyWSs+h+PaYkxGeMVmVCX75Zj/pqdjbu12ciCYE= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= +github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c h1:aY2hhxLhjEAbfXOx2nRJxCXezC6CO2V/yN+OCr1srtk= +github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1 h1:Lx3BlDGFElJt4u/zKc9A3BuGYbQAGlEFyPuUA3jeMD0= github.com/shazow/rateio v0.0.0-20150116013248-e8e00881e5c1/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI= +github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 h1:zwQ1HBo5FYwn1ksMd19qBCKO8JAWE9wmHivEpkw/DvE= +github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4/go.mod h1:vt2jWY/3Qw1bIzle5thrJWucsLuuX9iUNnp20CqCciI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576 h1:aUX/1G2gFSs4AsJJg2cL3HuoRhCSCz733FE5GUSuaT4= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200420104511-884d27f42877 h1:IhZPbxNd1UjBCaD5AfpSSbJTRlp+ZSuyuH5uoksNS04= +golang.org/x/crypto v0.0.0-20200420104511-884d27f42877/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54 h1:xe1/2UUJRmA9iDglQSlkx8c5n3twv58+K0mPpC2zmhA= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f h1:gWF768j/LaZugp8dyS4UwsslYCYz9XgFxvlgsn0n9H8= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=