Как использовать зашифрованный закрытый ключ с golang ssh

Я был бы признателен указатели, потому что я не могу понять, как расшифровать зашифрованный ключ, чтобы использовать его с golang СШ. Я пытаюсь объединить два других источника кода (включая этой один), но не может получить эту работу.

Я думаю, что я добираюсь до DER, но мне нужно Маршалл это обратно в PEM, чтобы использовать его с crypto / ssh

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

Я прочел:

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

С незашифрованной (!) ключ, я могу затем:

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),
    },
}

и это будет работать.

Я повторно использовал какой-то код, который, я думаю, дает мне расшифрованный PEM как 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
}

но как мне добраться от DER до подписывающего?

или, каков наилучший способ решить эту проблему?

3 ответов


если у вас есть блок DER с закрытым ключом RSA, вы используете x509.ParsePKCS1PrivateKey для разбора ключа и ssh.NewSignerFromKey для получения ssh.Signer

key, err := x509.ParsePKCS1PrivateKey(der)
if err != nil {
    log.Fatal(err)
}
signer := ssh.NewSignerFromKey(key)

Я просто собираюсь предоставить альтернативу здесь, которая позволяет повторно использовать ssh.ParsePrivateKey(key). Я изменил decrypt функция для расшифровки и кодирования закрытого ключа, если он зашифрован, и вернуть его, так что возвращается key может использоваться непосредственно в ssh.ParsePrivateKey(key). Он использует pem.EncodeToMemory чтобы получить ключ от расшифрованного блока PEM.

func decrypt(key []byte, password []byte) []byte {
    block, rest := pem.Decode(key)
    if len(rest) > 0 {
        log.Fatalf("Extra data included in key")
    }

    if x509.IsEncryptedPEMBlock(block) {
        der, err := x509.DecryptPEMBlock(block, password)
        if err != nil {
            log.Fatalf("Decrypt failed: %v", err)
        }
        return pem.EncodeToMemory(&pem.Block{Type: block.Type, Bytes: der})
    }
    return key
}

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

с незашифрованным ключом:

signer, err := ssh.ParsePrivateKey(key)

С зашифрованным ключом:

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

затем:

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