diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/ssh/keys.go')
-rw-r--r-- | vendor/golang.org/x/crypto/ssh/keys.go | 90 |
1 files changed, 71 insertions, 19 deletions
diff --git a/vendor/golang.org/x/crypto/ssh/keys.go b/vendor/golang.org/x/crypto/ssh/keys.go index f38de9898..cf6853232 100644 --- a/vendor/golang.org/x/crypto/ssh/keys.go +++ b/vendor/golang.org/x/crypto/ssh/keys.go @@ -824,7 +824,7 @@ func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { // Implemented based on the documentation at // https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key -func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) { +func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) { magic := append([]byte("openssh-key-v1"), 0) if !bytes.Equal(magic, key[0:len(magic)]) { return nil, errors.New("ssh: invalid openssh private key format") @@ -844,14 +844,15 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) { return nil, err } + if w.KdfName != "none" || w.CipherName != "none" { + return nil, errors.New("ssh: cannot decode encrypted private keys") + } + pk1 := struct { Check1 uint32 Check2 uint32 Keytype string - Pub []byte - Priv []byte - Comment string - Pad []byte `ssh:"rest"` + Rest []byte `ssh:"rest"` }{} if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil { @@ -862,24 +863,75 @@ func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) { return nil, errors.New("ssh: checkint mismatch") } - // we only handle ed25519 keys currently - if pk1.Keytype != KeyAlgoED25519 { - return nil, errors.New("ssh: unhandled key type") - } + // we only handle ed25519 and rsa keys currently + switch pk1.Keytype { + case KeyAlgoRSA: + // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773 + key := struct { + N *big.Int + E *big.Int + D *big.Int + Iqmp *big.Int + P *big.Int + Q *big.Int + Comment string + Pad []byte `ssh:"rest"` + }{} + + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } - for i, b := range pk1.Pad { - if int(b) != i+1 { - return nil, errors.New("ssh: padding not as expected") + for i, b := range key.Pad { + if int(b) != i+1 { + return nil, errors.New("ssh: padding not as expected") + } } - } - if len(pk1.Priv) != ed25519.PrivateKeySize { - return nil, errors.New("ssh: private key unexpected length") - } + pk := &rsa.PrivateKey{ + PublicKey: rsa.PublicKey{ + N: key.N, + E: int(key.E.Int64()), + }, + D: key.D, + Primes: []*big.Int{key.P, key.Q}, + } - pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) - copy(pk, pk1.Priv) - return &pk, nil + if err := pk.Validate(); err != nil { + return nil, err + } + + pk.Precompute() + + return pk, nil + case KeyAlgoED25519: + key := struct { + Pub []byte + Priv []byte + Comment string + Pad []byte `ssh:"rest"` + }{} + + if err := Unmarshal(pk1.Rest, &key); err != nil { + return nil, err + } + + if len(key.Priv) != ed25519.PrivateKeySize { + return nil, errors.New("ssh: private key unexpected length") + } + + for i, b := range key.Pad { + if int(b) != i+1 { + return nil, errors.New("ssh: padding not as expected") + } + } + + pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize)) + copy(pk, key.Priv) + return &pk, nil + default: + return nil, errors.New("ssh: unhandled key type") + } } // FingerprintLegacyMD5 returns the user presentation of the key's |