Copyright 2012 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package ssh

import (
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
	
)
These constants represent the algorithm names for key types supported by this package.
const (
	KeyAlgoRSA        = "ssh-rsa"
	KeyAlgoDSA        = "ssh-dss"
	KeyAlgoECDSA256   = "ecdsa-sha2-nistp256"
	KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
	KeyAlgoECDSA384   = "ecdsa-sha2-nistp384"
	KeyAlgoECDSA521   = "ecdsa-sha2-nistp521"
	KeyAlgoED25519    = "ssh-ed25519"
	KeyAlgoSKED25519  = "sk-ssh-ed25519@openssh.com"
)
These constants represent non-default signature algorithms that are supported as algorithm parameters to AlgorithmSigner.SignWithAlgorithm methods. See [PROTOCOL.agent] section 4.5.1 and https://tools.ietf.org/html/draft-ietf-curdle-rsa-sha2-10
const (
	SigAlgoRSA        = "ssh-rsa"
	SigAlgoRSASHA2256 = "rsa-sha2-256"
	SigAlgoRSASHA2512 = "rsa-sha2-512"
)
parsePubKey parses a public key of the given algorithm. Use ParsePublicKey for keys with prepended algorithm.
func ( []byte,  string) ( PublicKey,  []byte,  error) {
	switch  {
	case KeyAlgoRSA:
		return parseRSA()
	case KeyAlgoDSA:
		return parseDSA()
	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
		return parseECDSA()
	case KeyAlgoSKECDSA256:
		return parseSKECDSA()
	case KeyAlgoED25519:
		return parseED25519()
	case KeyAlgoSKED25519:
		return parseSKEd25519()
	case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
		,  := parseCert(, certToPrivAlgo())
		if  != nil {
			return nil, nil, 
		}
		return , nil, nil
	}
	return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", )
}
parseAuthorizedKey parses a public key in OpenSSH authorized_keys format (see sshd(8) manual page) once the options and key type fields have been removed.
func ( []byte) ( PublicKey,  string,  error) {
	 = bytes.TrimSpace()

	 := bytes.IndexAny(, " \t")
	if  == -1 {
		 = len()
	}
	 := [:]

	 := make([]byte, base64.StdEncoding.DecodedLen(len()))
	,  := base64.StdEncoding.Decode(, )
	if  != nil {
		return nil, "", 
	}
	 = [:]
	,  = ParsePublicKey()
	if  != nil {
		return nil, "", 
	}
	 = string(bytes.TrimSpace([:]))
	return , , nil
}
ParseKnownHosts parses an entry in the format of the known_hosts file. The known_hosts format is documented in the sshd(8) manual page. This function will parse a single entry from in. On successful return, marker will contain the optional marker value (i.e. "cert-authority" or "revoked") or else be empty, hosts will contain the hosts that this entry matches, pubKey will contain the public key and comment will contain any trailing comment at the end of the line. See the sshd(8) manual page for the various forms that a host string can take. The unparsed remainder of the input will be returned in rest. This function can be called repeatedly to parse multiple entries. If no entries were found in the input then err will be io.EOF. Otherwise a non-nil err value indicates a parse error.
func ( []byte) ( string,  []string,  PublicKey,  string,  []byte,  error) {
	for len() > 0 {
		 := bytes.IndexByte(, '\n')
		if  != -1 {
			 = [+1:]
			 = [:]
		} else {
			 = nil
		}

		 = bytes.IndexByte(, '\r')
		if  != -1 {
			 = [:]
		}

		 = bytes.TrimSpace()
		if len() == 0 || [0] == '#' {
			 = 
			continue
		}

		 := bytes.IndexAny(, " \t")
		if  == -1 {
			 = 
			continue
		}
Strip out the beginning of the known_host key. This is either an optional marker or a (set of) hostname(s).
		 := bytes.Fields()
		if len() < 3 || len() > 5 {
			return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
		}
keyFields[0] is either "@cert-authority", "@revoked" or a comma separated list of hosts
		 := ""
		if [0][0] == '@' {
			 = string([0][1:])
			 = [1:]
		}

keyFields[1] contains the key type (e.g. “ssh-rsa”). However, that information is duplicated inside the base64-encoded key and so is ignored here.

		 := bytes.Join([2:], []byte(" "))
		if , ,  = parseAuthorizedKey();  != nil {
			return "", nil, nil, "", nil, 
		}

		return , strings.Split(, ","), , , , nil
	}

	return "", nil, nil, "", nil, io.EOF
}
ParseAuthorizedKeys parses a public key from an authorized_keys file used in OpenSSH according to the sshd(8) manual page.
func ( []byte) ( PublicKey,  string,  []string,  []byte,  error) {
	for len() > 0 {
		 := bytes.IndexByte(, '\n')
		if  != -1 {
			 = [+1:]
			 = [:]
		} else {
			 = nil
		}

		 = bytes.IndexByte(, '\r')
		if  != -1 {
			 = [:]
		}

		 = bytes.TrimSpace()
		if len() == 0 || [0] == '#' {
			 = 
			continue
		}

		 := bytes.IndexAny(, " \t")
		if  == -1 {
			 = 
			continue
		}

		if , ,  = parseAuthorizedKey([:]);  == nil {
			return , , , , nil
		}
No key type recognised. Maybe there's an options field at the beginning.
		var  byte
		 := false
		var  []string
		 := 0
		for ,  = range  {
			 := ! && ( == ' ' ||  == '\t')
			if ( == ',' && !) ||  {
				if - > 0 {
					 = append(, string([:]))
				}
				 =  + 1
			}
			if  {
				break
			}
			if  == '"' && ( == 0 || ( > 0 && [-1] != '\\')) {
				 = !
			}
		}
		for  < len() && ([] == ' ' || [] == '\t') {
			++
		}
Invalid line: unmatched quote
			 = 
			continue
		}

		 = [:]
		 = bytes.IndexAny(, " \t")
		if  == -1 {
			 = 
			continue
		}

		if , ,  = parseAuthorizedKey([:]);  == nil {
			 = 
			return , , , , nil
		}

		 = 
		continue
	}

	return nil, "", nil, nil, errors.New("ssh: no key found")
}
ParsePublicKey parses an SSH public key formatted for use in the SSH wire protocol according to RFC 4253, section 6.6.
func ( []byte) ( PublicKey,  error) {
	, ,  := parseString()
	if ! {
		return nil, errShortRead
	}
	var  []byte
	, ,  = parsePubKey(, string())
	if len() > 0 {
		return nil, errors.New("ssh: trailing junk in public key")
	}

	return , 
}
MarshalAuthorizedKey serializes key for inclusion in an OpenSSH authorized_keys file. The return value ends with newline.
func ( PublicKey) []byte {
	 := &bytes.Buffer{}
	.WriteString(.Type())
	.WriteByte(' ')
	 := base64.NewEncoder(base64.StdEncoding, )
	.Write(.Marshal())
	.Close()
	.WriteByte('\n')
	return .Bytes()
}
PublicKey is an abstraction of different types of public keys.
Type returns the key's type, e.g. "ssh-rsa".
	Type() string
Marshal returns the serialized key data in SSH wire format, with the name prefix. To unmarshal the returned data, use the ParsePublicKey function.
	Marshal() []byte
Verify that sig is a signature on the given data using this key. This function will hash the data appropriately first.
	Verify(data []byte, sig *Signature) error
}
CryptoPublicKey, if implemented by a PublicKey, returns the underlying crypto.PublicKey form of the key.
type CryptoPublicKey interface {
	CryptoPublicKey() crypto.PublicKey
}
A Signer can create signatures that verify against a public key.
PublicKey returns an associated PublicKey instance.
	PublicKey() PublicKey
Sign returns raw signature for the given data. This method will apply the hash specified for the keytype to the data.
	Sign(rand io.Reader, data []byte) (*Signature, error)
}
A AlgorithmSigner is a Signer that also supports specifying a specific algorithm to use for signing.
type AlgorithmSigner interface {
	Signer
SignWithAlgorithm is like Signer.Sign, but allows specification of a non-default signing algorithm. See the SigAlgo* constants in this package for signature algorithms supported by this package. Callers may pass an empty string for the algorithm in which case the AlgorithmSigner will use its default algorithm.
	SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
}

type rsaPublicKey rsa.PublicKey

func ( *rsaPublicKey) () string {
	return "ssh-rsa"
}
parseRSA parses an RSA key according to RFC 4253, section 6.6.
func ( []byte) ( PublicKey,  []byte,  error) {
	var  struct {
		    *big.Int
		    *big.Int
		 []byte `ssh:"rest"`
	}
	if  := Unmarshal(, &);  != nil {
		return nil, nil, 
	}

	if ..BitLen() > 24 {
		return nil, nil, errors.New("ssh: exponent too large")
	}
	 := ..Int64()
	if  < 3 || &1 == 0 {
		return nil, nil, errors.New("ssh: incorrect exponent")
	}

	var  rsa.PublicKey
	.E = int()
	.N = .
	return (*rsaPublicKey)(&), ., nil
}

func ( *rsaPublicKey) () []byte {
RSA publickey struct layout should match the struct used by parseRSACert in the x/crypto/ssh/agent package.
	 := struct {
		 string
		    *big.Int
		    *big.Int
	}{
		KeyAlgoRSA,
		,
		.N,
	}
	return Marshal(&)
}

func ( *rsaPublicKey) ( []byte,  *Signature) error {
	var  crypto.Hash
	switch .Format {
	case SigAlgoRSA:
		 = crypto.SHA1
	case SigAlgoRSASHA2256:
		 = crypto.SHA256
	case SigAlgoRSASHA2512:
		 = crypto.SHA512
	default:
		return fmt.Errorf("ssh: signature type %s for key type %s", .Format, .Type())
	}
	 := .New()
	.Write()
	 := .Sum(nil)
	return rsa.VerifyPKCS1v15((*rsa.PublicKey)(), , , .Blob)
}

func ( *rsaPublicKey) () crypto.PublicKey {
	return (*rsa.PublicKey)()
}

type dsaPublicKey dsa.PublicKey

func ( *dsaPublicKey) () string {
	return "ssh-dss"
}

SSH specifies FIPS 186-2, which only provided a single size (1024 bits) DSA key. FIPS 186-3 allows for larger key sizes, which would confuse SSH.
	if  := .P.BitLen();  != 1024 {
		return fmt.Errorf("ssh: unsupported DSA key size %d", )
	}

	return nil
}
parseDSA parses an DSA key according to RFC 4253, section 6.6.
func ( []byte) ( PublicKey,  []byte,  error) {
	var  struct {
		, , ,  *big.Int
		       []byte `ssh:"rest"`
	}
	if  := Unmarshal(, &);  != nil {
		return nil, nil, 
	}

	 := dsa.Parameters{
		P: .,
		Q: .,
		G: .,
	}
	if  := checkDSAParams(&);  != nil {
		return nil, nil, 
	}

	 := &dsaPublicKey{
		Parameters: ,
		Y:          .,
	}
	return , ., nil
}

DSA publickey struct layout should match the struct used by parseDSACert in the x/crypto/ssh/agent package.
	 := struct {
		       string
		, , ,  *big.Int
	}{
		.Type(),
		.P,
		.Q,
		.G,
		.Y,
	}

	return Marshal(&)
}

func ( *dsaPublicKey) ( []byte,  *Signature) error {
	if .Format != .Type() {
		return fmt.Errorf("ssh: signature type %s for key type %s", .Format, .Type())
	}
	 := crypto.SHA1.New()
	.Write()
	 := .Sum(nil)
Per RFC 4253, section 6.6, The value for 'dss_signature_blob' is encoded as a string containing r, followed by s (which are 160-bit integers, without lengths or padding, unsigned, and in network byte order). For DSS purposes, sig.Blob should be exactly 40 bytes in length.
	if len(.Blob) != 40 {
		return errors.New("ssh: DSA signature parse error")
	}
	 := new(big.Int).SetBytes(.Blob[:20])
	 := new(big.Int).SetBytes(.Blob[20:])
	if dsa.Verify((*dsa.PublicKey)(), , , ) {
		return nil
	}
	return errors.New("ssh: signature did not verify")
}

func ( *dsaPublicKey) () crypto.PublicKey {
	return (*dsa.PublicKey)()
}

type dsaPrivateKey struct {
	*dsa.PrivateKey
}

func ( *dsaPrivateKey) () PublicKey {
	return (*dsaPublicKey)(&.PrivateKey.PublicKey)
}

func ( *dsaPrivateKey) ( io.Reader,  []byte) (*Signature, error) {
	return .SignWithAlgorithm(, , "")
}

func ( *dsaPrivateKey) ( io.Reader,  []byte,  string) (*Signature, error) {
	if  != "" &&  != .PublicKey().Type() {
		return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", )
	}

	 := crypto.SHA1.New()
	.Write()
	 := .Sum(nil)
	, ,  := dsa.Sign(, .PrivateKey, )
	if  != nil {
		return nil, 
	}

	 := make([]byte, 40)
	 := .Bytes()
	 := .Bytes()

	copy([20-len():20], )
	copy([40-len():], )

	return &Signature{
		Format: .PublicKey().Type(),
		Blob:   ,
	}, nil
}

type ecdsaPublicKey ecdsa.PublicKey

func ( *ecdsaPublicKey) () string {
	return "ecdsa-sha2-" + .nistID()
}

func ( *ecdsaPublicKey) () string {
	switch .Params().BitSize {
	case 256:
		return "nistp256"
	case 384:
		return "nistp384"
	case 521:
		return "nistp521"
	}
	panic("ssh: unsupported ecdsa key size")
}

type ed25519PublicKey ed25519.PublicKey

func ( ed25519PublicKey) () string {
	return KeyAlgoED25519
}

func ( []byte) ( PublicKey,  []byte,  error) {
	var  struct {
		 []byte
		     []byte `ssh:"rest"`
	}

	if  := Unmarshal(, &);  != nil {
		return nil, nil, 
	}

	if  := len(.);  != ed25519.PublicKeySize {
		return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", )
	}

	return ed25519PublicKey(.), ., nil
}

func ( ed25519PublicKey) () []byte {
	 := struct {
		     string
		 []byte
	}{
		KeyAlgoED25519,
		[]byte(),
	}
	return Marshal(&)
}

func ( ed25519PublicKey) ( []byte,  *Signature) error {
	if .Format != .Type() {
		return fmt.Errorf("ssh: signature type %s for key type %s", .Format, .Type())
	}
	if  := len();  != ed25519.PublicKeySize {
		return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", )
	}

	if  := ed25519.Verify(ed25519.PublicKey(), , .Blob); ! {
		return errors.New("ssh: signature did not verify")
	}

	return nil
}

func ( ed25519PublicKey) () crypto.PublicKey {
	return ed25519.PublicKey()
}

func ( elliptic.Curve) bool {
	return  == elliptic.P256() ||  == elliptic.P384() ||  == elliptic.P521()
}
ecHash returns the hash to match the given elliptic curve, see RFC 5656, section 6.2.1
func ( elliptic.Curve) crypto.Hash {
	 := .Params().BitSize
	switch {
	case  <= 256:
		return crypto.SHA256
	case  <= 384:
		return crypto.SHA384
	}
	return crypto.SHA512
}
parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
func ( []byte) ( PublicKey,  []byte,  error) {
	var  struct {
		    string
		 []byte
		     []byte `ssh:"rest"`
	}

	if  := Unmarshal(, &);  != nil {
		return nil, nil, 
	}

	 := new(ecdsa.PublicKey)

	switch . {
	case "nistp256":
		.Curve = elliptic.P256()
	case "nistp384":
		.Curve = elliptic.P384()
	case "nistp521":
		.Curve = elliptic.P521()
	default:
		return nil, nil, errors.New("ssh: unsupported curve")
	}

	.X, .Y = elliptic.Unmarshal(.Curve, .)
	if .X == nil || .Y == nil {
		return nil, nil, errors.New("ssh: invalid curve point")
	}
	return (*ecdsaPublicKey)(), ., nil
}

See RFC 5656, section 3.1.
ECDSA publickey struct layout should match the struct used by parseECDSACert in the x/crypto/ssh/agent package.
	 := struct {
		 string
		   string
		  []byte
	}{
		.Type(),
		.nistID(),
		,
	}

	return Marshal(&)
}

func ( *ecdsaPublicKey) ( []byte,  *Signature) error {
	if .Format != .Type() {
		return fmt.Errorf("ssh: signature type %s for key type %s", .Format, .Type())
	}

	 := ecHash(.Curve).New()
	.Write()
	 := .Sum(nil)
Per RFC 5656, section 3.1.2, The ecdsa_signature_blob value has the following specific encoding: mpint r mpint s
	var  struct {
		 *big.Int
		 *big.Int
	}

	if  := Unmarshal(.Blob, &);  != nil {
		return 
	}

	if ecdsa.Verify((*ecdsa.PublicKey)(), , ., .) {
		return nil
	}
	return errors.New("ssh: signature did not verify")
}

func ( *ecdsaPublicKey) () crypto.PublicKey {
	return (*ecdsa.PublicKey)()
}
skFields holds the additional fields present in U2F/FIDO2 signatures. See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details.
Flags contains U2F/FIDO2 flags such as 'user present'
Counter is a monotonic signature counter which can be used to detect concurrent use of a private key, should it be extracted from hardware.
application is a URL-like string, typically "ssh:" for SSH. see openssh/PROTOCOL.u2f for details.
	application string
	ecdsa.PublicKey
}

func ( *skECDSAPublicKey) () string {
	return KeyAlgoSKECDSA256
}

func ( *skECDSAPublicKey) () string {
	return "nistp256"
}

func ( []byte) ( PublicKey,  []byte,  error) {
	var  struct {
		       string
		    []byte
		 string
		        []byte `ssh:"rest"`
	}

	if  := Unmarshal(, &);  != nil {
		return nil, nil, 
	}

	 := new(skECDSAPublicKey)
	.application = .

	if . != "nistp256" {
		return nil, nil, errors.New("ssh: unsupported curve")
	}
	.Curve = elliptic.P256()

	.X, .Y = elliptic.Unmarshal(.Curve, .)
	if .X == nil || .Y == nil {
		return nil, nil, errors.New("ssh: invalid curve point")
	}

	return , ., nil
}

See RFC 5656, section 3.1.
	 := elliptic.Marshal(.Curve, .X, .Y)
	 := struct {
		        string
		          string
		         []byte
		 string
	}{
		.Type(),
		.nistID(),
		,
		.application,
	}

	return Marshal(&)
}

func ( *skECDSAPublicKey) ( []byte,  *Signature) error {
	if .Format != .Type() {
		return fmt.Errorf("ssh: signature type %s for key type %s", .Format, .Type())
	}

	 := ecHash(.Curve).New()
	.Write([]byte(.application))
	 := .Sum(nil)

	.Reset()
	.Write()
	 := .Sum(nil)

	var  struct {
		 *big.Int
		 *big.Int
	}
	if  := Unmarshal(.Blob, &);  != nil {
		return 
	}

	var  skFields
	if  := Unmarshal(.Rest, &);  != nil {
		return 
	}

	 := struct {
		 []byte `ssh:"rest"`
		             byte
		           uint32
		     []byte `ssh:"rest"`
	}{
		,
		.Flags,
		.Counter,
		,
	}

	 := Marshal()

	.Reset()
	.Write()
	 := .Sum(nil)

	if ecdsa.Verify((*ecdsa.PublicKey)(&.PublicKey), , ., .) {
		return nil
	}
	return errors.New("ssh: signature did not verify")
}

application is a URL-like string, typically "ssh:" for SSH. see openssh/PROTOCOL.u2f for details.
	application string
	ed25519.PublicKey
}

func ( *skEd25519PublicKey) () string {
	return KeyAlgoSKED25519
}

func ( []byte) ( PublicKey,  []byte,  error) {
	var  struct {
		    []byte
		 string
		        []byte `ssh:"rest"`
	}

	if  := Unmarshal(, &);  != nil {
		return nil, nil, 
	}

	if  := len(.);  != ed25519.PublicKeySize {
		return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", )
	}

	 := new(skEd25519PublicKey)
	.application = .
	.PublicKey = ed25519.PublicKey(.)

	return , ., nil
}

func ( *skEd25519PublicKey) () []byte {
	 := struct {
		        string
		    []byte
		 string
	}{
		KeyAlgoSKED25519,
		[]byte(.PublicKey),
		.application,
	}
	return Marshal(&)
}

func ( *skEd25519PublicKey) ( []byte,  *Signature) error {
	if .Format != .Type() {
		return fmt.Errorf("ssh: signature type %s for key type %s", .Format, .Type())
	}
	if  := len(.PublicKey);  != ed25519.PublicKeySize {
		return fmt.Errorf("invalid size %d for Ed25519 public key", )
	}

	 := sha256.New()
	.Write([]byte(.application))
	 := .Sum(nil)

	.Reset()
	.Write()
	 := .Sum(nil)

	var  struct {
		 []byte `ssh:"rest"`
	}

	if  := Unmarshal(.Blob, &);  != nil {
		return 
	}

	var  skFields
	if  := Unmarshal(.Rest, &);  != nil {
		return 
	}

	 := struct {
		 []byte `ssh:"rest"`
		             byte
		           uint32
		     []byte `ssh:"rest"`
	}{
		,
		.Flags,
		.Counter,
		,
	}

	 := Marshal()

	if  := ed25519.Verify(.PublicKey, , .); ! {
		return errors.New("ssh: signature did not verify")
	}

	return nil
}
NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding Signer instance. ECDSA keys must use P-256, P-384 or P-521. DSA keys must use parameter size L1024N160.
func ( interface{}) (Signer, error) {
	switch key := .(type) {
	case crypto.Signer:
		return NewSignerFromSigner()
	case *dsa.PrivateKey:
		return newDSAPrivateKey()
	default:
		return nil, fmt.Errorf("ssh: unsupported key type %T", )
	}
}

func ( *dsa.PrivateKey) (Signer, error) {
	if  := checkDSAParams(&.PublicKey.Parameters);  != nil {
		return nil, 
	}

	return &dsaPrivateKey{}, nil
}

type wrappedSigner struct {
	signer crypto.Signer
	pubKey PublicKey
}
NewSignerFromSigner takes any crypto.Signer implementation and returns a corresponding Signer interface. This can be used, for example, with keys kept in hardware modules.
func ( crypto.Signer) (Signer, error) {
	,  := NewPublicKey(.Public())
	if  != nil {
		return nil, 
	}

	return &wrappedSigner{, }, nil
}

func ( *wrappedSigner) () PublicKey {
	return .pubKey
}

func ( *wrappedSigner) ( io.Reader,  []byte) (*Signature, error) {
	return .SignWithAlgorithm(, , "")
}

func ( *wrappedSigner) ( io.Reader,  []byte,  string) (*Signature, error) {
	var  crypto.Hash

RSA keys support a few hash functions determined by the requested signature algorithm
		switch  {
		case "", SigAlgoRSA:
			 = SigAlgoRSA
			 = crypto.SHA1
		case SigAlgoRSASHA2256:
			 = crypto.SHA256
		case SigAlgoRSASHA2512:
			 = crypto.SHA512
		default:
			return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", )
		}
The only supported algorithm for all other key types is the same as the type of the key
		if  == "" {
			 = .pubKey.Type()
		} else if  != .pubKey.Type() {
			return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", )
		}

		switch key := .pubKey.(type) {
		case *dsaPublicKey:
			 = crypto.SHA1
		case *ecdsaPublicKey:
			 = ecHash(.Curve)
		case ed25519PublicKey:
		default:
			return nil, fmt.Errorf("ssh: unsupported key type %T", )
		}
	}

	var  []byte
	if  != 0 {
		 := .New()
		.Write()
		 = .Sum(nil)
	} else {
		 = 
	}

	,  := .signer.Sign(, , )
	if  != nil {
		return nil, 
	}
crypto.Signer.Sign is expected to return an ASN.1-encoded signature for ECDSA and DSA, but that's not the encoding expected by SSH, so re-encode.
	switch .pubKey.(type) {
	case *ecdsaPublicKey, *dsaPublicKey:
		type  struct {
			,  *big.Int
		}
		 := new()
		,  := asn1.Unmarshal(, )
		if  != nil {
			return nil, 
		}

		switch .pubKey.(type) {
		case *ecdsaPublicKey:
			 = Marshal()

		case *dsaPublicKey:
			 = make([]byte, 40)
			 := ..Bytes()
			 := ..Bytes()
			copy([20-len():20], )
			copy([40-len():40], )
		}
	}

	return &Signature{
		Format: ,
		Blob:   ,
	}, nil
}
NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, or ed25519.PublicKey returns a corresponding PublicKey instance. ECDSA keys must use P-256, P-384 or P-521.
func ( interface{}) (PublicKey, error) {
	switch key := .(type) {
	case *rsa.PublicKey:
		return (*rsaPublicKey)(), nil
	case *ecdsa.PublicKey:
		if !supportedEllipticCurve(.Curve) {
			return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported")
		}
		return (*ecdsaPublicKey)(), nil
	case *dsa.PublicKey:
		return (*dsaPublicKey)(), nil
	case ed25519.PublicKey:
		if  := len();  != ed25519.PublicKeySize {
			return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", )
		}
		return ed25519PublicKey(), nil
	default:
		return nil, fmt.Errorf("ssh: unsupported key type %T", )
	}
}
ParsePrivateKey returns a Signer from a PEM encoded private key. It supports the same keys as ParseRawPrivateKey. If the private key is encrypted, it will return a PassphraseMissingError.
func ( []byte) (Signer, error) {
	,  := ParseRawPrivateKey()
	if  != nil {
		return nil, 
	}

	return NewSignerFromKey()
}
ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private key and passphrase. It supports the same keys as ParseRawPrivateKeyWithPassphrase.
func (,  []byte) (Signer, error) {
	,  := ParseRawPrivateKeyWithPassphrase(, )
	if  != nil {
		return nil, 
	}

	return NewSignerFromKey()
}
encryptedBlock tells whether a private key is encrypted by examining its Proc-Type header for a mention of ENCRYPTED according to RFC 1421 Section 4.6.1.1.
func ( *pem.Block) bool {
	return strings.Contains(.Headers["Proc-Type"], "ENCRYPTED")
}
A PassphraseMissingError indicates that parsing this private key requires a passphrase. Use ParsePrivateKeyWithPassphrase.
PublicKey will be set if the private key format includes an unencrypted public key along with the encrypted private key.
	PublicKey PublicKey
}

func (*PassphraseMissingError) () string {
	return "ssh: this private key is passphrase protected"
}
ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports RSA (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys. If the private key is encrypted, it will return a PassphraseMissingError.
func ( []byte) (interface{}, error) {
	,  := pem.Decode()
	if  == nil {
		return nil, errors.New("ssh: no key found")
	}

	if encryptedBlock() {
		return nil, &PassphraseMissingError{}
	}

	switch .Type {
	case "RSA PRIVATE KEY":
RFC5208 - https://tools.ietf.org/html/rfc5208
	case "PRIVATE KEY":
		return x509.ParsePKCS8PrivateKey(.Bytes)
	case "EC PRIVATE KEY":
		return x509.ParseECPrivateKey(.Bytes)
	case "DSA PRIVATE KEY":
		return ParseDSAPrivateKey(.Bytes)
	case "OPENSSH PRIVATE KEY":
		return parseOpenSSHPrivateKey(.Bytes, unencryptedOpenSSHKey)
	default:
		return nil, fmt.Errorf("ssh: unsupported key type %q", .Type)
	}
}
ParseRawPrivateKeyWithPassphrase returns a private key decrypted with passphrase from a PEM encoded private key. If the passphrase is wrong, it will return x509.IncorrectPasswordError.
func (,  []byte) (interface{}, error) {
	,  := pem.Decode()
	if  == nil {
		return nil, errors.New("ssh: no key found")
	}

	if .Type == "OPENSSH PRIVATE KEY" {
		return parseOpenSSHPrivateKey(.Bytes, passphraseProtectedOpenSSHKey())
	}

	if !encryptedBlock() || !x509.IsEncryptedPEMBlock() {
		return nil, errors.New("ssh: not an encrypted key")
	}

	,  := x509.DecryptPEMBlock(, )
	if  != nil {
		if  == x509.IncorrectPasswordError {
			return nil, 
		}
		return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", )
	}

	switch .Type {
	case "RSA PRIVATE KEY":
		return x509.ParsePKCS1PrivateKey()
	case "EC PRIVATE KEY":
		return x509.ParseECPrivateKey()
	case "DSA PRIVATE KEY":
		return ParseDSAPrivateKey()
	default:
		return nil, fmt.Errorf("ssh: unsupported key type %q", .Type)
	}
}
ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as specified by the OpenSSL DSA man page.
func ( []byte) (*dsa.PrivateKey, error) {
	var  struct {
		 int
		       *big.Int
		       *big.Int
		       *big.Int
		     *big.Int
		    *big.Int
	}
	,  := asn1.Unmarshal(, &)
	if  != nil {
		return nil, errors.New("ssh: failed to parse DSA key: " + .Error())
	}
	if len() > 0 {
		return nil, errors.New("ssh: garbage after DSA key")
	}

	return &dsa.PrivateKey{
		PublicKey: dsa.PublicKey{
			Parameters: dsa.Parameters{
				P: .,
				Q: .,
				G: .,
			},
			Y: .,
		},
		X: .,
	}, nil
}

func (, ,  string,  []byte) ([]byte, error) {
	if  != "none" ||  != "none" {
		return nil, &PassphraseMissingError{}
	}
	if  != "" {
		return nil, errors.New("ssh: invalid openssh private key")
	}
	return , nil
}

func ( []byte) openSSHDecryptFunc {
	return func(, ,  string,  []byte) ([]byte, error) {
		if  == "none" ||  == "none" {
			return nil, errors.New("ssh: key is not password protected")
		}
		if  != "bcrypt" {
			return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", , "bcrypt")
		}

		var  struct {
			   string
			 uint32
		}
		if  := Unmarshal([]byte(), &);  != nil {
			return nil, 
		}

		,  := bcrypt_pbkdf.Key(, []byte(.), int(.), 32+16)
		if  != nil {
			return nil, 
		}
		,  := [:32], [32:]

		,  := aes.NewCipher()
		if  != nil {
			return nil, 
		}
		switch  {
		case "aes256-ctr":
			 := cipher.NewCTR(, )
			.XORKeyStream(, )
		case "aes256-cbc":
			if len()%.BlockSize() != 0 {
				return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size")
			}
			 := cipher.NewCBCDecrypter(, )
			.CryptBlocks(, )
		default:
			return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", , "aes256-ctr", "aes256-cbc")
		}

		return , nil
	}
}

type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used as the decrypt function to parse an unencrypted private key. See https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key.
func ( []byte,  openSSHDecryptFunc) (crypto.PrivateKey, error) {
	const  = "openssh-key-v1\x00"
	if len() < len() || string([:len()]) !=  {
		return nil, errors.New("ssh: invalid openssh private key format")
	}
	 := [len():]

	var  struct {
		   string
		      string
		      string
		      uint32
		       []byte
		 []byte
	}

	if  := Unmarshal(, &);  != nil {
		return nil, 
	}
We only support single key files, and so does OpenSSH. https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171
		return nil, errors.New("ssh: multi-key files are not supported")
	}

	,  := (., ., ., .)
	if  != nil {
		if ,  := .(*PassphraseMissingError);  {
			,  := ParsePublicKey(.)
			if  != nil {
				return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", )
			}
			.PublicKey = 
		}
		return nil, 
	}

	 := struct {
		  uint32
		  uint32
		 string
		    []byte `ssh:"rest"`
	}{}

	if  := Unmarshal(, &);  != nil || . != . {
		if . != "none" {
			return nil, x509.IncorrectPasswordError
		}
		return nil, errors.New("ssh: malformed OpenSSH key")
	}

	switch . {
https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
		 := struct {
			       *big.Int
			       *big.Int
			       *big.Int
			    *big.Int
			       *big.Int
			       *big.Int
			 string
			     []byte `ssh:"rest"`
		}{}

		if  := Unmarshal(., &);  != nil {
			return nil, 
		}

		if  := checkOpenSSHKeyPadding(.);  != nil {
			return nil, 
		}

		 := &rsa.PrivateKey{
			PublicKey: rsa.PublicKey{
				N: .,
				E: int(..Int64()),
			},
			D:      .,
			Primes: []*big.Int{., .},
		}

		if  := .Validate();  != nil {
			return nil, 
		}

		.Precompute()

		return , nil
	case KeyAlgoED25519:
		 := struct {
			     []byte
			    []byte
			 string
			     []byte `ssh:"rest"`
		}{}

		if  := Unmarshal(., &);  != nil {
			return nil, 
		}

		if len(.) != ed25519.PrivateKeySize {
			return nil, errors.New("ssh: private key unexpected length")
		}

		if  := checkOpenSSHKeyPadding(.);  != nil {
			return nil, 
		}

		 := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
		copy(, .)
		return &, nil
	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
		 := struct {
			   string
			     []byte
			       *big.Int
			 string
			     []byte `ssh:"rest"`
		}{}

		if  := Unmarshal(., &);  != nil {
			return nil, 
		}

		if  := checkOpenSSHKeyPadding(.);  != nil {
			return nil, 
		}

		var  elliptic.Curve
		switch . {
		case "nistp256":
			 = elliptic.P256()
		case "nistp384":
			 = elliptic.P384()
		case "nistp521":
			 = elliptic.P521()
		default:
			return nil, errors.New("ssh: unhandled elliptic curve: " + .)
		}

		,  := elliptic.Unmarshal(, .)
		if  == nil ||  == nil {
			return nil, errors.New("ssh: failed to unmarshal public key")
		}

		if ..Cmp(.Params().N) >= 0 {
			return nil, errors.New("ssh: scalar is out of range")
		}

		,  := .ScalarBaseMult(..Bytes())
		if .Cmp() != 0 || .Cmp() != 0 {
			return nil, errors.New("ssh: public key does not match private key")
		}

		return &ecdsa.PrivateKey{
			PublicKey: ecdsa.PublicKey{
				Curve: ,
				X:     ,
				Y:     ,
			},
			D: .,
		}, nil
	default:
		return nil, errors.New("ssh: unhandled key type")
	}
}

func ( []byte) error {
	for ,  := range  {
		if int() != +1 {
			return errors.New("ssh: padding not as expected")
		}
	}
	return nil
}
FingerprintLegacyMD5 returns the user presentation of the key's fingerprint as described by RFC 4716 section 4.
func ( PublicKey) string {
	 := md5.Sum(.Marshal())
	 := make([]string, len())
	for ,  := range  {
		[] = hex.EncodeToString([]byte{})
	}
	return strings.Join(, ":")
}
FingerprintSHA256 returns the user presentation of the key's fingerprint as unpadded base64 encoded sha256 hash. This format was introduced from OpenSSH 6.8. https://www.openssh.com/txt/release-6.8 https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
func ( PublicKey) string {
	 := sha256.Sum256(.Marshal())
	 := base64.RawStdEncoding.EncodeToString([:])
	return "SHA256:" +