Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use an encrypted private key with golang ssh

Tags:

ssh

go

x509

I would appreciate pointers because I cannot work out how to decrypt an encrypted key in order to use it with golang ssh. I'm attempting to mash together two other sources of code (including this one) but unable to get this to work.

I think I'm getting to a DER but need to marshall this back to PEM in order to use it with crypto/ssh

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,D7C72273BE168626E5B2D1BC72E56326
...
-----END RSA PRIVATE KEY-----

I read it:

key, err := ioutil.ReadFile(privateKey)
if err != nil {
    log.Fatalf("Unable to read private key: %v", err)
}

With an unencrypted (!) key, I can then:

signer, err := ssh.ParsePrivateKey(key)
if err != nil {
    log.Fatalf("Unable to parse private key: %v", err)
}

config := &ssh.ClientConfig{
    User: username,
    Auth: []ssh.AuthMethod{
        ssh.PublicKeys(signer),
    },
}

And this would work.

I reused some code that I think gets me the decrypted PEM as a DER:

func decrypt(key []byte, password []byte) []byte {
    block, rest := pem.Decode(key)
    if len(rest) > 0 {
        log.Fatalf("Extra data included in key")
    }
    der, err := x509.DecryptPEMBlock(block, password)
    if err != nil {
        log.Fatalf("Decrypt failed: %v", err)
    }
    return der
}

But, how do I get from the DER to a signer?

Or, what's the best way to solve this?

like image 863
DazWilkin Avatar asked Feb 08 '17 05:02

DazWilkin


People also ask

Does SSH use private key encryption?

The SSH keys themselves are private keys; the private key is further encrypted using a symmetric encryption key derived from a passphrase. The key derivation is done using a hash function. Passphrases are commonly used for keys belonging to interactive users.


1 Answers

import "golang.org/x/crypto/ssh"

With unencrypted key:

signer, err := ssh.ParsePrivateKey(key)

With encrypted key:

signer, err := ssh.ParsePrivateKeyWithPassphrase(key, []byte("password"))

Then:

config := &ssh.ClientConfig{
    User: username,
    Auth: []ssh.AuthMethod{
        ssh.PublicKeys(signer),
    },
}
like image 73
Łukasz Avatar answered Oct 19 '22 21:10

Łukasz