// 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 (
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	

	
)

// Public key algorithms names. These values can appear in PublicKey.Type,
// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner
// arguments.
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"

	// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not
	// public key formats, so they can't appear as a PublicKey.Type. The
	// corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
	KeyAlgoRSASHA256 = "rsa-sha2-256"
	KeyAlgoRSASHA512 = "rsa-sha2-512"
)

const (
	// Deprecated: use KeyAlgoRSA.
	SigAlgoRSA = KeyAlgoRSA
	// Deprecated: use KeyAlgoRSASHA256.
	SigAlgoRSASHA2256 = KeyAlgoRSASHA256
	// Deprecated: use KeyAlgoRSASHA512.
	SigAlgoRSASHA2512 = KeyAlgoRSASHA512
)

// parsePubKey parses a public key of the given algorithm.
// Use ParsePublicKey for keys with prepended algorithm.
func parsePubKey( []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(, certKeyAlgoNames[])
		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 parseAuthorizedKey( []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:]
		}

		 := string([0])
		// 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
}

// ParseAuthorizedKey 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') {
			++
		}
		if  == len() {
			// 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()
}

// MarshalPrivateKey returns a PEM block with the private key serialized in the
// OpenSSH format.
func ( crypto.PrivateKey,  string) (*pem.Block, error) {
	return marshalOpenSSHPrivateKey(, , unencryptedOpenSSHMarshaler)
}

// MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted
// private key serialized in the OpenSSH format.
func ( crypto.PrivateKey,  string,  []byte) (*pem.Block, error) {
	return marshalOpenSSHPrivateKey(, , passphraseProtectedOpenSSHMarshaler())
}

// PublicKey represents a public key using an unspecified algorithm.
//
// Some PublicKeys provided by this package also implement CryptoPublicKey.
type PublicKey interface {
	// Type returns the key format name, 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
	// method will hash the data appropriately first. sig.Format is allowed to
	// be any signature algorithm compatible with the key type, the caller
	// should check if it has more stringent requirements.
	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.
//
// Some Signers provided by this package also implement MultiAlgorithmSigner.
type Signer interface {
	// PublicKey returns the associated PublicKey.
	PublicKey() PublicKey

	// Sign returns a signature for the given data. This method will hash the
	// data appropriately first. The signature algorithm is expected to match
	// the key format returned by the PublicKey.Type method (and not to be any
	// alternative algorithm supported by the key format).
	Sign(rand io.Reader, data []byte) (*Signature, error)
}

// An AlgorithmSigner is a Signer that also supports specifying an algorithm to
// use for signing.
//
// An AlgorithmSigner can't advertise the algorithms it supports, unless it also
// implements MultiAlgorithmSigner, so it should be prepared to be invoked with
// every algorithm supported by the public key format.
type AlgorithmSigner interface {
	Signer

	// SignWithAlgorithm is like Signer.Sign, but allows specifying a desired
	// signing algorithm. Callers may pass an empty string for the algorithm in
	// which case the AlgorithmSigner will use a default algorithm. This default
	// doesn't currently control any behavior in this package.
	SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
}

// MultiAlgorithmSigner is an AlgorithmSigner that also reports the algorithms
// supported by that signer.
type MultiAlgorithmSigner interface {
	AlgorithmSigner

	// Algorithms returns the available algorithms in preference order. The list
	// must not be empty, and it must not include certificate types.
	Algorithms() []string
}

// NewSignerWithAlgorithms returns a signer restricted to the specified
// algorithms. The algorithms must be set in preference order. The list must not
// be empty, and it must not include certificate types. An error is returned if
// the specified algorithms are incompatible with the public key type.
func ( AlgorithmSigner,  []string) (MultiAlgorithmSigner, error) {
	if len() == 0 {
		return nil, errors.New("ssh: please specify at least one valid signing algorithm")
	}
	var  []string
	 := algorithmsForKeyFormat(underlyingAlgo(.PublicKey().Type()))
	if ,  := .(*multiAlgorithmSigner);  {
		 = .Algorithms()
	} else {
		 = 
	}

	for ,  := range  {
		if !contains(, ) {
			return nil, fmt.Errorf("ssh: algorithm %q is not supported for key type %q",
				, .PublicKey().Type())
		}
		if !contains(, ) {
			return nil, fmt.Errorf("ssh: algorithm %q is restricted for the provided signer", )
		}
	}
	return &multiAlgorithmSigner{
		AlgorithmSigner:     ,
		supportedAlgorithms: ,
	}, nil
}

type multiAlgorithmSigner struct {
	AlgorithmSigner
	supportedAlgorithms []string
}

func ( *multiAlgorithmSigner) () []string {
	return .supportedAlgorithms
}

func ( *multiAlgorithmSigner) ( string) bool {
	if  == "" {
		 = underlyingAlgo(.PublicKey().Type())
	}
	for ,  := range .supportedAlgorithms {
		if  ==  {
			return true
		}
	}
	return false
}

func ( *multiAlgorithmSigner) ( io.Reader,  []byte,  string) (*Signature, error) {
	if !.isAlgorithmSupported() {
		return nil, fmt.Errorf("ssh: algorithm %q is not supported: %v", , .supportedAlgorithms)
	}
	return .AlgorithmSigner.SignWithAlgorithm(, , )
}

type rsaPublicKey rsa.PublicKey

func ( *rsaPublicKey) () string {
	return "ssh-rsa"
}

// parseRSA parses an RSA key according to RFC 4253, section 6.6.
func parseRSA( []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 {
	 := new(big.Int).SetInt64(int64(.E))
	// 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 {
	 := algorithmsForKeyFormat(.Type())
	if !contains(, .Format) {
		return fmt.Errorf("ssh: signature type %s for key type %s", .Format, .Type())
	}
	 := hashFuncs[.Format]
	 := .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"
}

func checkDSAParams( *dsa.Parameters) error {
	// 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 parseDSA( []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
}

func ( *dsaPublicKey) () []byte {
	// 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())
	}
	 := hashFuncs[.Format].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(, , .PublicKey().Type())
}

func ( *dsaPrivateKey) () []string {
	return []string{.PublicKey().Type()}
}

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

	 := hashFuncs[.PublicKey().Type()].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 parseED25519( []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 supportedEllipticCurve( elliptic.Curve) bool {
	return  == elliptic.P256() ||  == elliptic.P384() ||  == elliptic.P521()
}

// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
func parseECDSA( []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
}

func ( *ecdsaPublicKey) () []byte {
	// See RFC 5656, section 3.1.
	 := elliptic.Marshal(.Curve, .X, .Y)
	// 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())
	}

	 := hashFuncs[.Format].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.
type skFields struct {
	// Flags contains U2F/FIDO2 flags such as 'user present'
	Flags byte
	// Counter is a monotonic signature counter which can be
	// used to detect concurrent use of a private key, should
	// it be extracted from hardware.
	Counter uint32
}

type skECDSAPublicKey struct {
	// 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 parseSKECDSA( []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
}

func ( *skECDSAPublicKey) () []byte {
	// 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())
	}

	 := hashFuncs[.Format].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")
}

type skEd25519PublicKey struct {
	// 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 parseSKEd25519( []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", )
	}

	 := hashFuncs[.Format].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 newDSAPrivateKey( *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(, , .pubKey.Type())
}

func ( *wrappedSigner) () []string {
	return algorithmsForKeyFormat(.pubKey.Type())
}

func ( *wrappedSigner) ( io.Reader,  []byte,  string) (*Signature, error) {
	if  == "" {
		 = .pubKey.Type()
	}

	if !contains(.Algorithms(), ) {
		return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", , .pubKey.Type())
	}

	 := hashFuncs[]
	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 encryptedBlock( *pem.Block) bool {
	return strings.Contains(.Headers["Proc-Type"], "ENCRYPTED")
}

// A PassphraseMissingError indicates that parsing this private key requires a
// passphrase. Use ParsePrivateKeyWithPassphrase.
type PassphraseMissingError struct {
	// 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, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH
// formats. 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":
		return x509.ParsePKCS1PrivateKey(.Bytes)
	// 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 unencryptedOpenSSHKey(, ,  string,  []byte) ([]byte, error) {
	if  != "none" ||  != "none" {
		return nil, &PassphraseMissingError{}
	}
	if  != "" {
		return nil, errors.New("ssh: invalid openssh private key")
	}
	return , nil
}

func passphraseProtectedOpenSSHKey( []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
	}
}

func unencryptedOpenSSHMarshaler( []byte) ([]byte, string, string, string, error) {
	 := generateOpenSSHPadding(, 8)
	return , "none", "none", "", nil
}

func passphraseProtectedOpenSSHMarshaler( []byte) openSSHEncryptFunc {
	return func( []byte) ([]byte, string, string, string, error) {
		 := make([]byte, 16)
		if ,  := rand.Read();  != nil {
			return nil, "", "", "", 
		}

		 := struct {
			   []byte
			 uint32
		}{, 16}

		// Derive key to encrypt the private key block.
		,  := bcrypt_pbkdf.Key(, , int(.), 32+aes.BlockSize)
		if  != nil {
			return nil, "", "", "", 
		}

		// Add padding matching the block size of AES.
		 := generateOpenSSHPadding(, aes.BlockSize)

		// Encrypt the private key using the derived secret.

		 := make([]byte, len())
		,  := [:32], [32:]
		,  := aes.NewCipher()
		if  != nil {
			return nil, "", "", "", 
		}

		 := cipher.NewCTR(, )
		.XORKeyStream(, )

		return , "aes256-ctr", "bcrypt", string(Marshal()), nil
	}
}

const privateKeyAuthMagic = "openssh-key-v1\x00"

type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
type openSSHEncryptFunc func(PrivKeyBlock []byte) (ProtectedKeyBlock []byte, cipherName, kdfName, kdfOptions string, err error)

type openSSHEncryptedPrivateKey struct {
	CipherName   string
	KdfName      string
	KdfOpts      string
	NumKeys      uint32
	PubKey       []byte
	PrivKeyBlock []byte
}

type openSSHPrivateKey struct {
	Check1  uint32
	Check2  uint32
	Keytype string
	Rest    []byte `ssh:"rest"`
}

type openSSHRSAPrivateKey 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"`
}

type openSSHEd25519PrivateKey struct {
	Pub     []byte
	Priv    []byte
	Comment string
	Pad     []byte `ssh:"rest"`
}

type openSSHECDSAPrivateKey struct {
	Curve   string
	Pub     []byte
	D       *big.Int
	Comment string
	Pad     []byte `ssh:"rest"`
}

// 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 parseOpenSSHPrivateKey( []byte,  openSSHDecryptFunc) (crypto.PrivateKey, error) {
	if len() < len(privateKeyAuthMagic) || string([:len(privateKeyAuthMagic)]) != privateKeyAuthMagic {
		return nil, errors.New("ssh: invalid openssh private key format")
	}
	 := [len(privateKeyAuthMagic):]

	var  openSSHEncryptedPrivateKey
	if  := Unmarshal(, &);  != nil {
		return nil, 
	}
	if .NumKeys != 1 {
		// 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")
	}

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

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

	switch .Keytype {
	case KeyAlgoRSA:
		var  openSSHRSAPrivateKey
		if  := Unmarshal(.Rest, &);  != nil {
			return nil, 
		}

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

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

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

		.Precompute()

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

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

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

		 := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
		copy(, .Priv)
		return &, nil
	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
		var  openSSHECDSAPrivateKey
		if  := Unmarshal(.Rest, &);  != nil {
			return nil, 
		}

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

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

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

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

		,  := .ScalarBaseMult(.D.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: .D,
		}, nil
	default:
		return nil, errors.New("ssh: unhandled key type")
	}
}

func marshalOpenSSHPrivateKey( crypto.PrivateKey,  string,  openSSHEncryptFunc) (*pem.Block, error) {
	var  openSSHEncryptedPrivateKey
	var  openSSHPrivateKey

	// Random check bytes.
	var  uint32
	if  := binary.Read(rand.Reader, binary.BigEndian, &);  != nil {
		return nil, 
	}

	.Check1 = 
	.Check2 = 
	.NumKeys = 1

	// Use a []byte directly on ed25519 keys.
	if ,  := .(*ed25519.PrivateKey);  {
		 = *
	}

	switch k := .(type) {
	case *rsa.PrivateKey:
		 := new(big.Int).SetInt64(int64(.PublicKey.E))
		// Marshal public key:
		// E and N are in reversed order in the public and private key.
		 := struct {
			 string
			       *big.Int
			       *big.Int
		}{
			KeyAlgoRSA,
			, .PublicKey.N,
		}
		.PubKey = Marshal()

		// Marshal private key.
		 := openSSHRSAPrivateKey{
			N:       .PublicKey.N,
			E:       ,
			D:       .D,
			Iqmp:    .Precomputed.Qinv,
			P:       .Primes[0],
			Q:       .Primes[1],
			Comment: ,
		}
		.Keytype = KeyAlgoRSA
		.Rest = Marshal()
	case ed25519.PrivateKey:
		 := make([]byte, ed25519.PublicKeySize)
		 := make([]byte, ed25519.PrivateKeySize)
		copy(, [32:])
		copy(, )

		// Marshal public key.
		 := struct {
			 string
			     []byte
		}{
			KeyAlgoED25519, ,
		}
		.PubKey = Marshal()

		// Marshal private key.
		 := openSSHEd25519PrivateKey{
			Pub:     ,
			Priv:    ,
			Comment: ,
		}
		.Keytype = KeyAlgoED25519
		.Rest = Marshal()
	case *ecdsa.PrivateKey:
		var ,  string
		switch  := .Curve.Params().Name;  {
		case "P-256":
			 = "nistp256"
			 = KeyAlgoECDSA256
		case "P-384":
			 = "nistp384"
			 = KeyAlgoECDSA384
		case "P-521":
			 = "nistp521"
			 = KeyAlgoECDSA521
		default:
			return nil, errors.New("ssh: unhandled elliptic curve " + )
		}

		 := elliptic.Marshal(.Curve, .PublicKey.X, .PublicKey.Y)

		// Marshal public key.
		 := struct {
			 string
			   string
			     []byte
		}{
			, , ,
		}
		.PubKey = Marshal()

		// Marshal private key.
		 := openSSHECDSAPrivateKey{
			Curve:   ,
			Pub:     ,
			D:       .D,
			Comment: ,
		}
		.Keytype = 
		.Rest = Marshal()
	default:
		return nil, fmt.Errorf("ssh: unsupported key type %T", )
	}

	var  error
	// Add padding and encrypt the key if necessary.
	.PrivKeyBlock, .CipherName, .KdfName, .KdfOpts,  = (Marshal())
	if  != nil {
		return nil, 
	}

	 := Marshal()
	 := &pem.Block{
		Type:  "OPENSSH PRIVATE KEY",
		Bytes: append([]byte(privateKeyAuthMagic), ...),
	}
	return , nil
}

func checkOpenSSHKeyPadding( []byte) error {
	for ,  := range  {
		if int() != +1 {
			return errors.New("ssh: padding not as expected")
		}
	}
	return nil
}

func generateOpenSSHPadding( []byte,  int) []byte {
	for ,  := 0, len(); (+)% != 0; ++ {
		 = append(, byte(+1))
	}
	return 
}

// 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:" + 
}