1// Copyright 2012 The Go Authors. All rights reserved.
   2// Use of this source code is governed by a BSD-style
   3// license that can be found in the LICENSE file.
   4
   5package ssh
   6
   7import (
   8	"bytes"
   9	"crypto"
  10	"crypto/aes"
  11	"crypto/cipher"
  12	"crypto/dsa"
  13	"crypto/ecdsa"
  14	"crypto/ed25519"
  15	"crypto/elliptic"
  16	"crypto/md5"
  17	"crypto/rand"
  18	"crypto/rsa"
  19	"crypto/sha256"
  20	"crypto/x509"
  21	"encoding/asn1"
  22	"encoding/base64"
  23	"encoding/binary"
  24	"encoding/hex"
  25	"encoding/pem"
  26	"errors"
  27	"fmt"
  28	"io"
  29	"math/big"
  30	"slices"
  31	"strings"
  32
  33	"golang.org/x/crypto/ssh/internal/bcrypt_pbkdf"
  34)
  35
  36// Public key algorithms names. These values can appear in PublicKey.Type,
  37// ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner
  38// arguments.
  39const (
  40	KeyAlgoRSA = "ssh-rsa"
  41	// Deprecated: DSA is only supported at insecure key sizes, and was removed
  42	// from major implementations.
  43	KeyAlgoDSA = InsecureKeyAlgoDSA
  44	// Deprecated: DSA is only supported at insecure key sizes, and was removed
  45	// from major implementations.
  46	InsecureKeyAlgoDSA = "ssh-dss"
  47	KeyAlgoECDSA256    = "ecdsa-sha2-nistp256"
  48	KeyAlgoSKECDSA256  = "sk-ecdsa-sha2-nistp256@openssh.com"
  49	KeyAlgoECDSA384    = "ecdsa-sha2-nistp384"
  50	KeyAlgoECDSA521    = "ecdsa-sha2-nistp521"
  51	KeyAlgoED25519     = "ssh-ed25519"
  52	KeyAlgoSKED25519   = "sk-ssh-ed25519@openssh.com"
  53
  54	// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not
  55	// public key formats, so they can't appear as a PublicKey.Type. The
  56	// corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2.
  57	KeyAlgoRSASHA256 = "rsa-sha2-256"
  58	KeyAlgoRSASHA512 = "rsa-sha2-512"
  59)
  60
  61const (
  62	// Deprecated: use KeyAlgoRSA.
  63	SigAlgoRSA = KeyAlgoRSA
  64	// Deprecated: use KeyAlgoRSASHA256.
  65	SigAlgoRSASHA2256 = KeyAlgoRSASHA256
  66	// Deprecated: use KeyAlgoRSASHA512.
  67	SigAlgoRSASHA2512 = KeyAlgoRSASHA512
  68)
  69
  70// parsePubKey parses a public key of the given algorithm.
  71// Use ParsePublicKey for keys with prepended algorithm.
  72func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
  73	switch algo {
  74	case KeyAlgoRSA:
  75		return parseRSA(in)
  76	case InsecureKeyAlgoDSA:
  77		return parseDSA(in)
  78	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
  79		return parseECDSA(in)
  80	case KeyAlgoSKECDSA256:
  81		return parseSKECDSA(in)
  82	case KeyAlgoED25519:
  83		return parseED25519(in)
  84	case KeyAlgoSKED25519:
  85		return parseSKEd25519(in)
  86	case CertAlgoRSAv01, InsecureCertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoSKECDSA256v01, CertAlgoED25519v01, CertAlgoSKED25519v01:
  87		cert, err := parseCert(in, certKeyAlgoNames[algo])
  88		if err != nil {
  89			return nil, nil, err
  90		}
  91		return cert, nil, nil
  92	}
  93	if keyFormat := keyFormatForAlgorithm(algo); keyFormat != "" {
  94		return nil, nil, fmt.Errorf("ssh: signature algorithm %q isn't a key format; key is malformed and should be re-encoded with type %q",
  95			algo, keyFormat)
  96	}
  97
  98	return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
  99}
 100
 101// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
 102// (see sshd(8) manual page) once the options and key type fields have been
 103// removed.
 104func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
 105	in = bytes.TrimSpace(in)
 106
 107	i := bytes.IndexAny(in, " \t")
 108	if i == -1 {
 109		i = len(in)
 110	}
 111	base64Key := in[:i]
 112
 113	key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
 114	n, err := base64.StdEncoding.Decode(key, base64Key)
 115	if err != nil {
 116		return nil, "", err
 117	}
 118	key = key[:n]
 119	out, err = ParsePublicKey(key)
 120	if err != nil {
 121		return nil, "", err
 122	}
 123	comment = string(bytes.TrimSpace(in[i:]))
 124	return out, comment, nil
 125}
 126
 127// ParseKnownHosts parses an entry in the format of the known_hosts file.
 128//
 129// The known_hosts format is documented in the sshd(8) manual page. This
 130// function will parse a single entry from in. On successful return, marker
 131// will contain the optional marker value (i.e. "cert-authority" or "revoked")
 132// or else be empty, hosts will contain the hosts that this entry matches,
 133// pubKey will contain the public key and comment will contain any trailing
 134// comment at the end of the line. See the sshd(8) manual page for the various
 135// forms that a host string can take.
 136//
 137// The unparsed remainder of the input will be returned in rest. This function
 138// can be called repeatedly to parse multiple entries.
 139//
 140// If no entries were found in the input then err will be io.EOF. Otherwise a
 141// non-nil err value indicates a parse error.
 142func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) {
 143	for len(in) > 0 {
 144		end := bytes.IndexByte(in, '\n')
 145		if end != -1 {
 146			rest = in[end+1:]
 147			in = in[:end]
 148		} else {
 149			rest = nil
 150		}
 151
 152		end = bytes.IndexByte(in, '\r')
 153		if end != -1 {
 154			in = in[:end]
 155		}
 156
 157		in = bytes.TrimSpace(in)
 158		if len(in) == 0 || in[0] == '#' {
 159			in = rest
 160			continue
 161		}
 162
 163		i := bytes.IndexAny(in, " \t")
 164		if i == -1 {
 165			in = rest
 166			continue
 167		}
 168
 169		// Strip out the beginning of the known_host key.
 170		// This is either an optional marker or a (set of) hostname(s).
 171		keyFields := bytes.Fields(in)
 172		if len(keyFields) < 3 || len(keyFields) > 5 {
 173			return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
 174		}
 175
 176		// keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
 177		// list of hosts
 178		marker := ""
 179		if keyFields[0][0] == '@' {
 180			marker = string(keyFields[0][1:])
 181			keyFields = keyFields[1:]
 182		}
 183
 184		hosts := string(keyFields[0])
 185		// keyFields[1] contains the key type (e.g. “ssh-rsa”).
 186		// However, that information is duplicated inside the
 187		// base64-encoded key and so is ignored here.
 188
 189		key := bytes.Join(keyFields[2:], []byte(" "))
 190		if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
 191			return "", nil, nil, "", nil, err
 192		}
 193
 194		return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
 195	}
 196
 197	return "", nil, nil, "", nil, io.EOF
 198}
 199
 200// ParseAuthorizedKey parses a public key from an authorized_keys file used in
 201// OpenSSH according to the sshd(8) manual page. Invalid lines are ignored.
 202func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
 203	var lastErr error
 204	for len(in) > 0 {
 205		end := bytes.IndexByte(in, '\n')
 206		if end != -1 {
 207			rest = in[end+1:]
 208			in = in[:end]
 209		} else {
 210			rest = nil
 211		}
 212
 213		end = bytes.IndexByte(in, '\r')
 214		if end != -1 {
 215			in = in[:end]
 216		}
 217
 218		in = bytes.TrimSpace(in)
 219		if len(in) == 0 || in[0] == '#' {
 220			in = rest
 221			continue
 222		}
 223
 224		i := bytes.IndexAny(in, " \t")
 225		if i == -1 {
 226			in = rest
 227			continue
 228		}
 229
 230		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
 231			return out, comment, options, rest, nil
 232		} else {
 233			lastErr = err
 234		}
 235
 236		// No key type recognised. Maybe there's an options field at
 237		// the beginning.
 238		var b byte
 239		inQuote := false
 240		var candidateOptions []string
 241		optionStart := 0
 242		for i, b = range in {
 243			isEnd := !inQuote && (b == ' ' || b == '\t')
 244			if (b == ',' && !inQuote) || isEnd {
 245				if i-optionStart > 0 {
 246					candidateOptions = append(candidateOptions, string(in[optionStart:i]))
 247				}
 248				optionStart = i + 1
 249			}
 250			if isEnd {
 251				break
 252			}
 253			if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
 254				inQuote = !inQuote
 255			}
 256		}
 257		for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
 258			i++
 259		}
 260		if i == len(in) {
 261			// Invalid line: unmatched quote
 262			in = rest
 263			continue
 264		}
 265
 266		in = in[i:]
 267		i = bytes.IndexAny(in, " \t")
 268		if i == -1 {
 269			in = rest
 270			continue
 271		}
 272
 273		if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
 274			options = candidateOptions
 275			return out, comment, options, rest, nil
 276		} else {
 277			lastErr = err
 278		}
 279
 280		in = rest
 281		continue
 282	}
 283
 284	if lastErr != nil {
 285		return nil, "", nil, nil, fmt.Errorf("ssh: no key found; last parsing error for ignored line: %w", lastErr)
 286	}
 287
 288	return nil, "", nil, nil, errors.New("ssh: no key found")
 289}
 290
 291// ParsePublicKey parses an SSH public key or certificate formatted for use in
 292// the SSH wire protocol according to RFC 4253, section 6.6.
 293func ParsePublicKey(in []byte) (out PublicKey, err error) {
 294	algo, in, ok := parseString(in)
 295	if !ok {
 296		return nil, errShortRead
 297	}
 298	var rest []byte
 299	out, rest, err = parsePubKey(in, string(algo))
 300	if len(rest) > 0 {
 301		return nil, errors.New("ssh: trailing junk in public key")
 302	}
 303
 304	return out, err
 305}
 306
 307// MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
 308// authorized_keys file. The return value ends with newline.
 309func MarshalAuthorizedKey(key PublicKey) []byte {
 310	b := &bytes.Buffer{}
 311	b.WriteString(key.Type())
 312	b.WriteByte(' ')
 313	e := base64.NewEncoder(base64.StdEncoding, b)
 314	e.Write(key.Marshal())
 315	e.Close()
 316	b.WriteByte('\n')
 317	return b.Bytes()
 318}
 319
 320// MarshalPrivateKey returns a PEM block with the private key serialized in the
 321// OpenSSH format.
 322func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error) {
 323	return marshalOpenSSHPrivateKey(key, comment, unencryptedOpenSSHMarshaler)
 324}
 325
 326// MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted
 327// private key serialized in the OpenSSH format.
 328func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment string, passphrase []byte) (*pem.Block, error) {
 329	return marshalOpenSSHPrivateKey(key, comment, passphraseProtectedOpenSSHMarshaler(passphrase))
 330}
 331
 332// PublicKey represents a public key using an unspecified algorithm.
 333//
 334// Some PublicKeys provided by this package also implement CryptoPublicKey.
 335type PublicKey interface {
 336	// Type returns the key format name, e.g. "ssh-rsa".
 337	Type() string
 338
 339	// Marshal returns the serialized key data in SSH wire format, with the name
 340	// prefix. To unmarshal the returned data, use the ParsePublicKey function.
 341	Marshal() []byte
 342
 343	// Verify that sig is a signature on the given data using this key. This
 344	// method will hash the data appropriately first. sig.Format is allowed to
 345	// be any signature algorithm compatible with the key type, the caller
 346	// should check if it has more stringent requirements.
 347	Verify(data []byte, sig *Signature) error
 348}
 349
 350// CryptoPublicKey, if implemented by a PublicKey,
 351// returns the underlying crypto.PublicKey form of the key.
 352type CryptoPublicKey interface {
 353	CryptoPublicKey() crypto.PublicKey
 354}
 355
 356// A Signer can create signatures that verify against a public key.
 357//
 358// Some Signers provided by this package also implement MultiAlgorithmSigner.
 359type Signer interface {
 360	// PublicKey returns the associated PublicKey.
 361	PublicKey() PublicKey
 362
 363	// Sign returns a signature for the given data. This method will hash the
 364	// data appropriately first. The signature algorithm is expected to match
 365	// the key format returned by the PublicKey.Type method (and not to be any
 366	// alternative algorithm supported by the key format).
 367	Sign(rand io.Reader, data []byte) (*Signature, error)
 368}
 369
 370// An AlgorithmSigner is a Signer that also supports specifying an algorithm to
 371// use for signing.
 372//
 373// An AlgorithmSigner can't advertise the algorithms it supports, unless it also
 374// implements MultiAlgorithmSigner, so it should be prepared to be invoked with
 375// every algorithm supported by the public key format.
 376type AlgorithmSigner interface {
 377	Signer
 378
 379	// SignWithAlgorithm is like Signer.Sign, but allows specifying a desired
 380	// signing algorithm. Callers may pass an empty string for the algorithm in
 381	// which case the AlgorithmSigner will use a default algorithm. This default
 382	// doesn't currently control any behavior in this package.
 383	SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error)
 384}
 385
 386// MultiAlgorithmSigner is an AlgorithmSigner that also reports the algorithms
 387// supported by that signer.
 388type MultiAlgorithmSigner interface {
 389	AlgorithmSigner
 390
 391	// Algorithms returns the available algorithms in preference order. The list
 392	// must not be empty, and it must not include certificate types.
 393	Algorithms() []string
 394}
 395
 396// NewSignerWithAlgorithms returns a signer restricted to the specified
 397// algorithms. The algorithms must be set in preference order. The list must not
 398// be empty, and it must not include certificate types. An error is returned if
 399// the specified algorithms are incompatible with the public key type.
 400func NewSignerWithAlgorithms(signer AlgorithmSigner, algorithms []string) (MultiAlgorithmSigner, error) {
 401	if len(algorithms) == 0 {
 402		return nil, errors.New("ssh: please specify at least one valid signing algorithm")
 403	}
 404	var signerAlgos []string
 405	supportedAlgos := algorithmsForKeyFormat(underlyingAlgo(signer.PublicKey().Type()))
 406	if s, ok := signer.(*multiAlgorithmSigner); ok {
 407		signerAlgos = s.Algorithms()
 408	} else {
 409		signerAlgos = supportedAlgos
 410	}
 411
 412	for _, algo := range algorithms {
 413		if !slices.Contains(supportedAlgos, algo) {
 414			return nil, fmt.Errorf("ssh: algorithm %q is not supported for key type %q",
 415				algo, signer.PublicKey().Type())
 416		}
 417		if !slices.Contains(signerAlgos, algo) {
 418			return nil, fmt.Errorf("ssh: algorithm %q is restricted for the provided signer", algo)
 419		}
 420	}
 421	return &multiAlgorithmSigner{
 422		AlgorithmSigner:     signer,
 423		supportedAlgorithms: algorithms,
 424	}, nil
 425}
 426
 427type multiAlgorithmSigner struct {
 428	AlgorithmSigner
 429	supportedAlgorithms []string
 430}
 431
 432func (s *multiAlgorithmSigner) Algorithms() []string {
 433	return s.supportedAlgorithms
 434}
 435
 436func (s *multiAlgorithmSigner) isAlgorithmSupported(algorithm string) bool {
 437	if algorithm == "" {
 438		algorithm = underlyingAlgo(s.PublicKey().Type())
 439	}
 440	for _, algo := range s.supportedAlgorithms {
 441		if algorithm == algo {
 442			return true
 443		}
 444	}
 445	return false
 446}
 447
 448func (s *multiAlgorithmSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
 449	if !s.isAlgorithmSupported(algorithm) {
 450		return nil, fmt.Errorf("ssh: algorithm %q is not supported: %v", algorithm, s.supportedAlgorithms)
 451	}
 452	return s.AlgorithmSigner.SignWithAlgorithm(rand, data, algorithm)
 453}
 454
 455type rsaPublicKey rsa.PublicKey
 456
 457func (r *rsaPublicKey) Type() string {
 458	return "ssh-rsa"
 459}
 460
 461// parseRSA parses an RSA key according to RFC 4253, section 6.6.
 462func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
 463	var w struct {
 464		E    *big.Int
 465		N    *big.Int
 466		Rest []byte `ssh:"rest"`
 467	}
 468	if err := Unmarshal(in, &w); err != nil {
 469		return nil, nil, err
 470	}
 471
 472	if w.E.BitLen() > 24 {
 473		return nil, nil, errors.New("ssh: exponent too large")
 474	}
 475	e := w.E.Int64()
 476	if e < 3 || e&1 == 0 {
 477		return nil, nil, errors.New("ssh: incorrect exponent")
 478	}
 479
 480	var key rsa.PublicKey
 481	key.E = int(e)
 482	key.N = w.N
 483	return (*rsaPublicKey)(&key), w.Rest, nil
 484}
 485
 486func (r *rsaPublicKey) Marshal() []byte {
 487	e := new(big.Int).SetInt64(int64(r.E))
 488	// RSA publickey struct layout should match the struct used by
 489	// parseRSACert in the x/crypto/ssh/agent package.
 490	wirekey := struct {
 491		Name string
 492		E    *big.Int
 493		N    *big.Int
 494	}{
 495		KeyAlgoRSA,
 496		e,
 497		r.N,
 498	}
 499	return Marshal(&wirekey)
 500}
 501
 502func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
 503	supportedAlgos := algorithmsForKeyFormat(r.Type())
 504	if !slices.Contains(supportedAlgos, sig.Format) {
 505		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
 506	}
 507	hash, err := hashFunc(sig.Format)
 508	if err != nil {
 509		return err
 510	}
 511	h := hash.New()
 512	h.Write(data)
 513	digest := h.Sum(nil)
 514
 515	// Signatures in PKCS1v15 must match the key's modulus in
 516	// length. However with SSH, some signers provide RSA
 517	// signatures which are missing the MSB 0's of the bignum
 518	// represented. With ssh-rsa signatures, this is encouraged by
 519	// the spec (even though e.g. OpenSSH will give the full
 520	// length unconditionally). With rsa-sha2-* signatures, the
 521	// verifier is allowed to support these, even though they are
 522	// out of spec. See RFC 4253 Section 6.6 for ssh-rsa and RFC
 523	// 8332 Section 3 for rsa-sha2-* details.
 524	//
 525	// In practice:
 526	// * OpenSSH always allows "short" signatures:
 527	//   https://github.com/openssh/openssh-portable/blob/V_9_8_P1/ssh-rsa.c#L526
 528	//   but always generates padded signatures:
 529	//   https://github.com/openssh/openssh-portable/blob/V_9_8_P1/ssh-rsa.c#L439
 530	//
 531	// * PuTTY versions 0.81 and earlier will generate short
 532	//   signatures for all RSA signature variants. Note that
 533	//   PuTTY is embedded in other software, such as WinSCP and
 534	//   FileZilla. At the time of writing, a patch has been
 535	//   applied to PuTTY to generate padded signatures for
 536	//   rsa-sha2-*, but not yet released:
 537	//   https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=a5bcf3d384e1bf15a51a6923c3724cbbee022d8e
 538	//
 539	// * SSH.NET versions 2024.0.0 and earlier will generate short
 540	//   signatures for all RSA signature variants, fixed in 2024.1.0:
 541	//   https://github.com/sshnet/SSH.NET/releases/tag/2024.1.0
 542	//
 543	// As a result, we pad these up to the key size by inserting
 544	// leading 0's.
 545	//
 546	// Note that support for short signatures with rsa-sha2-* may
 547	// be removed in the future due to such signatures not being
 548	// allowed by the spec.
 549	blob := sig.Blob
 550	keySize := (*rsa.PublicKey)(r).Size()
 551	if len(blob) < keySize {
 552		padded := make([]byte, keySize)
 553		copy(padded[keySize-len(blob):], blob)
 554		blob = padded
 555	}
 556	return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), hash, digest, blob)
 557}
 558
 559func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
 560	return (*rsa.PublicKey)(r)
 561}
 562
 563type dsaPublicKey dsa.PublicKey
 564
 565func (k *dsaPublicKey) Type() string {
 566	return "ssh-dss"
 567}
 568
 569func checkDSAParams(param *dsa.Parameters) error {
 570	// SSH specifies FIPS 186-2, which only provided a single size
 571	// (1024 bits) DSA key. FIPS 186-3 allows for larger key
 572	// sizes, which would confuse SSH.
 573	if l := param.P.BitLen(); l != 1024 {
 574		return fmt.Errorf("ssh: unsupported DSA key size %d", l)
 575	}
 576
 577	return nil
 578}
 579
 580// parseDSA parses an DSA key according to RFC 4253, section 6.6.
 581func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
 582	var w struct {
 583		P, Q, G, Y *big.Int
 584		Rest       []byte `ssh:"rest"`
 585	}
 586	if err := Unmarshal(in, &w); err != nil {
 587		return nil, nil, err
 588	}
 589
 590	param := dsa.Parameters{
 591		P: w.P,
 592		Q: w.Q,
 593		G: w.G,
 594	}
 595	if err := checkDSAParams(&param); err != nil {
 596		return nil, nil, err
 597	}
 598
 599	key := &dsaPublicKey{
 600		Parameters: param,
 601		Y:          w.Y,
 602	}
 603	return key, w.Rest, nil
 604}
 605
 606func (k *dsaPublicKey) Marshal() []byte {
 607	// DSA publickey struct layout should match the struct used by
 608	// parseDSACert in the x/crypto/ssh/agent package.
 609	w := struct {
 610		Name       string
 611		P, Q, G, Y *big.Int
 612	}{
 613		k.Type(),
 614		k.P,
 615		k.Q,
 616		k.G,
 617		k.Y,
 618	}
 619
 620	return Marshal(&w)
 621}
 622
 623func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
 624	if sig.Format != k.Type() {
 625		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
 626	}
 627	hash, err := hashFunc(sig.Format)
 628	if err != nil {
 629		return err
 630	}
 631	h := hash.New()
 632	h.Write(data)
 633	digest := h.Sum(nil)
 634
 635	// Per RFC 4253, section 6.6,
 636	// The value for 'dss_signature_blob' is encoded as a string containing
 637	// r, followed by s (which are 160-bit integers, without lengths or
 638	// padding, unsigned, and in network byte order).
 639	// For DSS purposes, sig.Blob should be exactly 40 bytes in length.
 640	if len(sig.Blob) != 40 {
 641		return errors.New("ssh: DSA signature parse error")
 642	}
 643	r := new(big.Int).SetBytes(sig.Blob[:20])
 644	s := new(big.Int).SetBytes(sig.Blob[20:])
 645	if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
 646		return nil
 647	}
 648	return errors.New("ssh: signature did not verify")
 649}
 650
 651func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
 652	return (*dsa.PublicKey)(k)
 653}
 654
 655type dsaPrivateKey struct {
 656	*dsa.PrivateKey
 657}
 658
 659func (k *dsaPrivateKey) PublicKey() PublicKey {
 660	return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
 661}
 662
 663func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
 664	return k.SignWithAlgorithm(rand, data, k.PublicKey().Type())
 665}
 666
 667func (k *dsaPrivateKey) Algorithms() []string {
 668	return []string{k.PublicKey().Type()}
 669}
 670
 671func (k *dsaPrivateKey) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
 672	if algorithm != "" && algorithm != k.PublicKey().Type() {
 673		return nil, fmt.Errorf("ssh: unsupported signature algorithm %s", algorithm)
 674	}
 675
 676	hash, err := hashFunc(k.PublicKey().Type())
 677	if err != nil {
 678		return nil, err
 679	}
 680	h := hash.New()
 681	h.Write(data)
 682	digest := h.Sum(nil)
 683	r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
 684	if err != nil {
 685		return nil, err
 686	}
 687
 688	sig := make([]byte, 40)
 689	rb := r.Bytes()
 690	sb := s.Bytes()
 691
 692	copy(sig[20-len(rb):20], rb)
 693	copy(sig[40-len(sb):], sb)
 694
 695	return &Signature{
 696		Format: k.PublicKey().Type(),
 697		Blob:   sig,
 698	}, nil
 699}
 700
 701type ecdsaPublicKey ecdsa.PublicKey
 702
 703func (k *ecdsaPublicKey) Type() string {
 704	return "ecdsa-sha2-" + k.nistID()
 705}
 706
 707func (k *ecdsaPublicKey) nistID() string {
 708	switch k.Params().BitSize {
 709	case 256:
 710		return "nistp256"
 711	case 384:
 712		return "nistp384"
 713	case 521:
 714		return "nistp521"
 715	}
 716	panic("ssh: unsupported ecdsa key size")
 717}
 718
 719type ed25519PublicKey ed25519.PublicKey
 720
 721func (k ed25519PublicKey) Type() string {
 722	return KeyAlgoED25519
 723}
 724
 725func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
 726	var w struct {
 727		KeyBytes []byte
 728		Rest     []byte `ssh:"rest"`
 729	}
 730
 731	if err := Unmarshal(in, &w); err != nil {
 732		return nil, nil, err
 733	}
 734
 735	if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
 736		return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
 737	}
 738
 739	return ed25519PublicKey(w.KeyBytes), w.Rest, nil
 740}
 741
 742func (k ed25519PublicKey) Marshal() []byte {
 743	w := struct {
 744		Name     string
 745		KeyBytes []byte
 746	}{
 747		KeyAlgoED25519,
 748		[]byte(k),
 749	}
 750	return Marshal(&w)
 751}
 752
 753func (k ed25519PublicKey) Verify(b []byte, sig *Signature) error {
 754	if sig.Format != k.Type() {
 755		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
 756	}
 757	if l := len(k); l != ed25519.PublicKeySize {
 758		return fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
 759	}
 760
 761	if ok := ed25519.Verify(ed25519.PublicKey(k), b, sig.Blob); !ok {
 762		return errors.New("ssh: signature did not verify")
 763	}
 764
 765	return nil
 766}
 767
 768func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
 769	return ed25519.PublicKey(k)
 770}
 771
 772func supportedEllipticCurve(curve elliptic.Curve) bool {
 773	return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
 774}
 775
 776// parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
 777func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
 778	var w struct {
 779		Curve    string
 780		KeyBytes []byte
 781		Rest     []byte `ssh:"rest"`
 782	}
 783
 784	if err := Unmarshal(in, &w); err != nil {
 785		return nil, nil, err
 786	}
 787
 788	key := new(ecdsa.PublicKey)
 789
 790	switch w.Curve {
 791	case "nistp256":
 792		key.Curve = elliptic.P256()
 793	case "nistp384":
 794		key.Curve = elliptic.P384()
 795	case "nistp521":
 796		key.Curve = elliptic.P521()
 797	default:
 798		return nil, nil, errors.New("ssh: unsupported curve")
 799	}
 800
 801	key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
 802	if key.X == nil || key.Y == nil {
 803		return nil, nil, errors.New("ssh: invalid curve point")
 804	}
 805	return (*ecdsaPublicKey)(key), w.Rest, nil
 806}
 807
 808func (k *ecdsaPublicKey) Marshal() []byte {
 809	// See RFC 5656, section 3.1.
 810	keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
 811	// ECDSA publickey struct layout should match the struct used by
 812	// parseECDSACert in the x/crypto/ssh/agent package.
 813	w := struct {
 814		Name string
 815		ID   string
 816		Key  []byte
 817	}{
 818		k.Type(),
 819		k.nistID(),
 820		keyBytes,
 821	}
 822
 823	return Marshal(&w)
 824}
 825
 826func (k *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
 827	if sig.Format != k.Type() {
 828		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
 829	}
 830	hash, err := hashFunc(sig.Format)
 831	if err != nil {
 832		return err
 833	}
 834	h := hash.New()
 835	h.Write(data)
 836	digest := h.Sum(nil)
 837
 838	// Per RFC 5656, section 3.1.2,
 839	// The ecdsa_signature_blob value has the following specific encoding:
 840	//    mpint    r
 841	//    mpint    s
 842	var ecSig struct {
 843		R *big.Int
 844		S *big.Int
 845	}
 846
 847	if err := Unmarshal(sig.Blob, &ecSig); err != nil {
 848		return err
 849	}
 850
 851	if ecdsa.Verify((*ecdsa.PublicKey)(k), digest, ecSig.R, ecSig.S) {
 852		return nil
 853	}
 854	return errors.New("ssh: signature did not verify")
 855}
 856
 857func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
 858	return (*ecdsa.PublicKey)(k)
 859}
 860
 861// skFields holds the additional fields present in U2F/FIDO2 signatures.
 862// See openssh/PROTOCOL.u2f 'SSH U2F Signatures' for details.
 863type skFields struct {
 864	// Flags contains U2F/FIDO2 flags such as 'user present'
 865	Flags byte
 866	// Counter is a monotonic signature counter which can be
 867	// used to detect concurrent use of a private key, should
 868	// it be extracted from hardware.
 869	Counter uint32
 870}
 871
 872type skECDSAPublicKey struct {
 873	// application is a URL-like string, typically "ssh:" for SSH.
 874	// see openssh/PROTOCOL.u2f for details.
 875	application string
 876	ecdsa.PublicKey
 877}
 878
 879func (k *skECDSAPublicKey) Type() string {
 880	return KeyAlgoSKECDSA256
 881}
 882
 883func (k *skECDSAPublicKey) nistID() string {
 884	return "nistp256"
 885}
 886
 887func parseSKECDSA(in []byte) (out PublicKey, rest []byte, err error) {
 888	var w struct {
 889		Curve       string
 890		KeyBytes    []byte
 891		Application string
 892		Rest        []byte `ssh:"rest"`
 893	}
 894
 895	if err := Unmarshal(in, &w); err != nil {
 896		return nil, nil, err
 897	}
 898
 899	key := new(skECDSAPublicKey)
 900	key.application = w.Application
 901
 902	if w.Curve != "nistp256" {
 903		return nil, nil, errors.New("ssh: unsupported curve")
 904	}
 905	key.Curve = elliptic.P256()
 906
 907	key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
 908	if key.X == nil || key.Y == nil {
 909		return nil, nil, errors.New("ssh: invalid curve point")
 910	}
 911
 912	return key, w.Rest, nil
 913}
 914
 915func (k *skECDSAPublicKey) Marshal() []byte {
 916	// See RFC 5656, section 3.1.
 917	keyBytes := elliptic.Marshal(k.Curve, k.X, k.Y)
 918	w := struct {
 919		Name        string
 920		ID          string
 921		Key         []byte
 922		Application string
 923	}{
 924		k.Type(),
 925		k.nistID(),
 926		keyBytes,
 927		k.application,
 928	}
 929
 930	return Marshal(&w)
 931}
 932
 933func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error {
 934	if sig.Format != k.Type() {
 935		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
 936	}
 937	hash, err := hashFunc(sig.Format)
 938	if err != nil {
 939		return err
 940	}
 941	h := hash.New()
 942	h.Write([]byte(k.application))
 943	appDigest := h.Sum(nil)
 944
 945	h.Reset()
 946	h.Write(data)
 947	dataDigest := h.Sum(nil)
 948
 949	var ecSig struct {
 950		R *big.Int
 951		S *big.Int
 952	}
 953	if err := Unmarshal(sig.Blob, &ecSig); err != nil {
 954		return err
 955	}
 956
 957	var skf skFields
 958	if err := Unmarshal(sig.Rest, &skf); err != nil {
 959		return err
 960	}
 961
 962	blob := struct {
 963		ApplicationDigest []byte `ssh:"rest"`
 964		Flags             byte
 965		Counter           uint32
 966		MessageDigest     []byte `ssh:"rest"`
 967	}{
 968		appDigest,
 969		skf.Flags,
 970		skf.Counter,
 971		dataDigest,
 972	}
 973
 974	original := Marshal(blob)
 975
 976	h.Reset()
 977	h.Write(original)
 978	digest := h.Sum(nil)
 979
 980	if ecdsa.Verify((*ecdsa.PublicKey)(&k.PublicKey), digest, ecSig.R, ecSig.S) {
 981		return nil
 982	}
 983	return errors.New("ssh: signature did not verify")
 984}
 985
 986func (k *skECDSAPublicKey) CryptoPublicKey() crypto.PublicKey {
 987	return &k.PublicKey
 988}
 989
 990type skEd25519PublicKey struct {
 991	// application is a URL-like string, typically "ssh:" for SSH.
 992	// see openssh/PROTOCOL.u2f for details.
 993	application string
 994	ed25519.PublicKey
 995}
 996
 997func (k *skEd25519PublicKey) Type() string {
 998	return KeyAlgoSKED25519
 999}
1000
1001func parseSKEd25519(in []byte) (out PublicKey, rest []byte, err error) {
1002	var w struct {
1003		KeyBytes    []byte
1004		Application string
1005		Rest        []byte `ssh:"rest"`
1006	}
1007
1008	if err := Unmarshal(in, &w); err != nil {
1009		return nil, nil, err
1010	}
1011
1012	if l := len(w.KeyBytes); l != ed25519.PublicKeySize {
1013		return nil, nil, fmt.Errorf("invalid size %d for Ed25519 public key", l)
1014	}
1015
1016	key := new(skEd25519PublicKey)
1017	key.application = w.Application
1018	key.PublicKey = ed25519.PublicKey(w.KeyBytes)
1019
1020	return key, w.Rest, nil
1021}
1022
1023func (k *skEd25519PublicKey) Marshal() []byte {
1024	w := struct {
1025		Name        string
1026		KeyBytes    []byte
1027		Application string
1028	}{
1029		KeyAlgoSKED25519,
1030		[]byte(k.PublicKey),
1031		k.application,
1032	}
1033	return Marshal(&w)
1034}
1035
1036func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error {
1037	if sig.Format != k.Type() {
1038		return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
1039	}
1040	if l := len(k.PublicKey); l != ed25519.PublicKeySize {
1041		return fmt.Errorf("invalid size %d for Ed25519 public key", l)
1042	}
1043
1044	hash, err := hashFunc(sig.Format)
1045	if err != nil {
1046		return err
1047	}
1048	h := hash.New()
1049	h.Write([]byte(k.application))
1050	appDigest := h.Sum(nil)
1051
1052	h.Reset()
1053	h.Write(data)
1054	dataDigest := h.Sum(nil)
1055
1056	var edSig struct {
1057		Signature []byte `ssh:"rest"`
1058	}
1059
1060	if err := Unmarshal(sig.Blob, &edSig); err != nil {
1061		return err
1062	}
1063
1064	var skf skFields
1065	if err := Unmarshal(sig.Rest, &skf); err != nil {
1066		return err
1067	}
1068
1069	blob := struct {
1070		ApplicationDigest []byte `ssh:"rest"`
1071		Flags             byte
1072		Counter           uint32
1073		MessageDigest     []byte `ssh:"rest"`
1074	}{
1075		appDigest,
1076		skf.Flags,
1077		skf.Counter,
1078		dataDigest,
1079	}
1080
1081	original := Marshal(blob)
1082
1083	if ok := ed25519.Verify(k.PublicKey, original, edSig.Signature); !ok {
1084		return errors.New("ssh: signature did not verify")
1085	}
1086
1087	return nil
1088}
1089
1090func (k *skEd25519PublicKey) CryptoPublicKey() crypto.PublicKey {
1091	return k.PublicKey
1092}
1093
1094// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
1095// *ecdsa.PrivateKey or any other crypto.Signer and returns a
1096// corresponding Signer instance. ECDSA keys must use P-256, P-384 or
1097// P-521. DSA keys must use parameter size L1024N160.
1098func NewSignerFromKey(key interface{}) (Signer, error) {
1099	switch key := key.(type) {
1100	case crypto.Signer:
1101		return NewSignerFromSigner(key)
1102	case *dsa.PrivateKey:
1103		return newDSAPrivateKey(key)
1104	default:
1105		return nil, fmt.Errorf("ssh: unsupported key type %T", key)
1106	}
1107}
1108
1109func newDSAPrivateKey(key *dsa.PrivateKey) (Signer, error) {
1110	if err := checkDSAParams(&key.PublicKey.Parameters); err != nil {
1111		return nil, err
1112	}
1113
1114	return &dsaPrivateKey{key}, nil
1115}
1116
1117type wrappedSigner struct {
1118	signer crypto.Signer
1119	pubKey PublicKey
1120}
1121
1122// NewSignerFromSigner takes any crypto.Signer implementation and
1123// returns a corresponding Signer interface. This can be used, for
1124// example, with keys kept in hardware modules.
1125func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
1126	pubKey, err := NewPublicKey(signer.Public())
1127	if err != nil {
1128		return nil, err
1129	}
1130
1131	return &wrappedSigner{signer, pubKey}, nil
1132}
1133
1134func (s *wrappedSigner) PublicKey() PublicKey {
1135	return s.pubKey
1136}
1137
1138func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
1139	return s.SignWithAlgorithm(rand, data, s.pubKey.Type())
1140}
1141
1142func (s *wrappedSigner) Algorithms() []string {
1143	return algorithmsForKeyFormat(s.pubKey.Type())
1144}
1145
1146func (s *wrappedSigner) SignWithAlgorithm(rand io.Reader, data []byte, algorithm string) (*Signature, error) {
1147	if algorithm == "" {
1148		algorithm = s.pubKey.Type()
1149	}
1150
1151	if !slices.Contains(s.Algorithms(), algorithm) {
1152		return nil, fmt.Errorf("ssh: unsupported signature algorithm %q for key format %q", algorithm, s.pubKey.Type())
1153	}
1154
1155	hashFunc, err := hashFunc(algorithm)
1156	if err != nil {
1157		return nil, err
1158	}
1159	var digest []byte
1160	if hashFunc != 0 {
1161		h := hashFunc.New()
1162		h.Write(data)
1163		digest = h.Sum(nil)
1164	} else {
1165		digest = data
1166	}
1167
1168	signature, err := s.signer.Sign(rand, digest, hashFunc)
1169	if err != nil {
1170		return nil, err
1171	}
1172
1173	// crypto.Signer.Sign is expected to return an ASN.1-encoded signature
1174	// for ECDSA and DSA, but that's not the encoding expected by SSH, so
1175	// re-encode.
1176	switch s.pubKey.(type) {
1177	case *ecdsaPublicKey, *dsaPublicKey:
1178		type asn1Signature struct {
1179			R, S *big.Int
1180		}
1181		asn1Sig := new(asn1Signature)
1182		_, err := asn1.Unmarshal(signature, asn1Sig)
1183		if err != nil {
1184			return nil, err
1185		}
1186
1187		switch s.pubKey.(type) {
1188		case *ecdsaPublicKey:
1189			signature = Marshal(asn1Sig)
1190
1191		case *dsaPublicKey:
1192			signature = make([]byte, 40)
1193			r := asn1Sig.R.Bytes()
1194			s := asn1Sig.S.Bytes()
1195			copy(signature[20-len(r):20], r)
1196			copy(signature[40-len(s):40], s)
1197		}
1198	}
1199
1200	return &Signature{
1201		Format: algorithm,
1202		Blob:   signature,
1203	}, nil
1204}
1205
1206// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
1207// or ed25519.PublicKey returns a corresponding PublicKey instance.
1208// ECDSA keys must use P-256, P-384 or P-521.
1209func NewPublicKey(key interface{}) (PublicKey, error) {
1210	switch key := key.(type) {
1211	case *rsa.PublicKey:
1212		return (*rsaPublicKey)(key), nil
1213	case *ecdsa.PublicKey:
1214		if !supportedEllipticCurve(key.Curve) {
1215			return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported")
1216		}
1217		return (*ecdsaPublicKey)(key), nil
1218	case *dsa.PublicKey:
1219		return (*dsaPublicKey)(key), nil
1220	case ed25519.PublicKey:
1221		if l := len(key); l != ed25519.PublicKeySize {
1222			return nil, fmt.Errorf("ssh: invalid size %d for Ed25519 public key", l)
1223		}
1224		return ed25519PublicKey(key), nil
1225	default:
1226		return nil, fmt.Errorf("ssh: unsupported key type %T", key)
1227	}
1228}
1229
1230// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
1231// the same keys as ParseRawPrivateKey. If the private key is encrypted, it
1232// will return a PassphraseMissingError.
1233func ParsePrivateKey(pemBytes []byte) (Signer, error) {
1234	key, err := ParseRawPrivateKey(pemBytes)
1235	if err != nil {
1236		return nil, err
1237	}
1238
1239	return NewSignerFromKey(key)
1240}
1241
1242// ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
1243// key and passphrase. It supports the same keys as
1244// ParseRawPrivateKeyWithPassphrase.
1245func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error) {
1246	key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase)
1247	if err != nil {
1248		return nil, err
1249	}
1250
1251	return NewSignerFromKey(key)
1252}
1253
1254// encryptedBlock tells whether a private key is
1255// encrypted by examining its Proc-Type header
1256// for a mention of ENCRYPTED
1257// according to RFC 1421 Section 4.6.1.1.
1258func encryptedBlock(block *pem.Block) bool {
1259	return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
1260}
1261
1262// A PassphraseMissingError indicates that parsing this private key requires a
1263// passphrase. Use ParsePrivateKeyWithPassphrase.
1264type PassphraseMissingError struct {
1265	// PublicKey will be set if the private key format includes an unencrypted
1266	// public key along with the encrypted private key.
1267	PublicKey PublicKey
1268}
1269
1270func (*PassphraseMissingError) Error() string {
1271	return "ssh: this private key is passphrase protected"
1272}
1273
1274// ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports
1275// RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH
1276// formats. If the private key is encrypted, it will return a PassphraseMissingError.
1277func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
1278	block, _ := pem.Decode(pemBytes)
1279	if block == nil {
1280		return nil, errors.New("ssh: no key found")
1281	}
1282
1283	if encryptedBlock(block) {
1284		return nil, &PassphraseMissingError{}
1285	}
1286
1287	switch block.Type {
1288	case "RSA PRIVATE KEY":
1289		return x509.ParsePKCS1PrivateKey(block.Bytes)
1290	// RFC5208 - https://tools.ietf.org/html/rfc5208
1291	case "PRIVATE KEY":
1292		return x509.ParsePKCS8PrivateKey(block.Bytes)
1293	case "EC PRIVATE KEY":
1294		return x509.ParseECPrivateKey(block.Bytes)
1295	case "DSA PRIVATE KEY":
1296		return ParseDSAPrivateKey(block.Bytes)
1297	case "OPENSSH PRIVATE KEY":
1298		return parseOpenSSHPrivateKey(block.Bytes, unencryptedOpenSSHKey)
1299	default:
1300		return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
1301	}
1302}
1303
1304// ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
1305// passphrase from a PEM encoded private key. If the passphrase is wrong, it
1306// will return x509.IncorrectPasswordError.
1307func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (interface{}, error) {
1308	block, _ := pem.Decode(pemBytes)
1309	if block == nil {
1310		return nil, errors.New("ssh: no key found")
1311	}
1312
1313	if block.Type == "OPENSSH PRIVATE KEY" {
1314		return parseOpenSSHPrivateKey(block.Bytes, passphraseProtectedOpenSSHKey(passphrase))
1315	}
1316
1317	if !encryptedBlock(block) || !x509.IsEncryptedPEMBlock(block) {
1318		return nil, errors.New("ssh: not an encrypted key")
1319	}
1320
1321	buf, err := x509.DecryptPEMBlock(block, passphrase)
1322	if err != nil {
1323		if err == x509.IncorrectPasswordError {
1324			return nil, err
1325		}
1326		return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
1327	}
1328
1329	var result interface{}
1330
1331	switch block.Type {
1332	case "RSA PRIVATE KEY":
1333		result, err = x509.ParsePKCS1PrivateKey(buf)
1334	case "EC PRIVATE KEY":
1335		result, err = x509.ParseECPrivateKey(buf)
1336	case "DSA PRIVATE KEY":
1337		result, err = ParseDSAPrivateKey(buf)
1338	default:
1339		err = fmt.Errorf("ssh: unsupported key type %q", block.Type)
1340	}
1341	// Because of deficiencies in the format, DecryptPEMBlock does not always
1342	// detect an incorrect password. In these cases decrypted DER bytes is
1343	// random noise. If the parsing of the key returns an asn1.StructuralError
1344	// we return x509.IncorrectPasswordError.
1345	if _, ok := err.(asn1.StructuralError); ok {
1346		return nil, x509.IncorrectPasswordError
1347	}
1348
1349	return result, err
1350}
1351
1352// ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
1353// specified by the OpenSSL DSA man page.
1354func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
1355	var k struct {
1356		Version int
1357		P       *big.Int
1358		Q       *big.Int
1359		G       *big.Int
1360		Pub     *big.Int
1361		Priv    *big.Int
1362	}
1363	rest, err := asn1.Unmarshal(der, &k)
1364	if err != nil {
1365		return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
1366	}
1367	if len(rest) > 0 {
1368		return nil, errors.New("ssh: garbage after DSA key")
1369	}
1370
1371	return &dsa.PrivateKey{
1372		PublicKey: dsa.PublicKey{
1373			Parameters: dsa.Parameters{
1374				P: k.P,
1375				Q: k.Q,
1376				G: k.G,
1377			},
1378			Y: k.Pub,
1379		},
1380		X: k.Priv,
1381	}, nil
1382}
1383
1384func unencryptedOpenSSHKey(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
1385	if kdfName != "none" || cipherName != "none" {
1386		return nil, &PassphraseMissingError{}
1387	}
1388	if kdfOpts != "" {
1389		return nil, errors.New("ssh: invalid openssh private key")
1390	}
1391	return privKeyBlock, nil
1392}
1393
1394func passphraseProtectedOpenSSHKey(passphrase []byte) openSSHDecryptFunc {
1395	return func(cipherName, kdfName, kdfOpts string, privKeyBlock []byte) ([]byte, error) {
1396		if kdfName == "none" || cipherName == "none" {
1397			return nil, errors.New("ssh: key is not password protected")
1398		}
1399		if kdfName != "bcrypt" {
1400			return nil, fmt.Errorf("ssh: unknown KDF %q, only supports %q", kdfName, "bcrypt")
1401		}
1402
1403		var opts struct {
1404			Salt   string
1405			Rounds uint32
1406		}
1407		if err := Unmarshal([]byte(kdfOpts), &opts); err != nil {
1408			return nil, err
1409		}
1410
1411		k, err := bcrypt_pbkdf.Key(passphrase, []byte(opts.Salt), int(opts.Rounds), 32+16)
1412		if err != nil {
1413			return nil, err
1414		}
1415		key, iv := k[:32], k[32:]
1416
1417		c, err := aes.NewCipher(key)
1418		if err != nil {
1419			return nil, err
1420		}
1421		switch cipherName {
1422		case "aes256-ctr":
1423			ctr := cipher.NewCTR(c, iv)
1424			ctr.XORKeyStream(privKeyBlock, privKeyBlock)
1425		case "aes256-cbc":
1426			if len(privKeyBlock)%c.BlockSize() != 0 {
1427				return nil, fmt.Errorf("ssh: invalid encrypted private key length, not a multiple of the block size")
1428			}
1429			cbc := cipher.NewCBCDecrypter(c, iv)
1430			cbc.CryptBlocks(privKeyBlock, privKeyBlock)
1431		default:
1432			return nil, fmt.Errorf("ssh: unknown cipher %q, only supports %q or %q", cipherName, "aes256-ctr", "aes256-cbc")
1433		}
1434
1435		return privKeyBlock, nil
1436	}
1437}
1438
1439func unencryptedOpenSSHMarshaler(privKeyBlock []byte) ([]byte, string, string, string, error) {
1440	key := generateOpenSSHPadding(privKeyBlock, 8)
1441	return key, "none", "none", "", nil
1442}
1443
1444func passphraseProtectedOpenSSHMarshaler(passphrase []byte) openSSHEncryptFunc {
1445	return func(privKeyBlock []byte) ([]byte, string, string, string, error) {
1446		salt := make([]byte, 16)
1447		if _, err := rand.Read(salt); err != nil {
1448			return nil, "", "", "", err
1449		}
1450
1451		opts := struct {
1452			Salt   []byte
1453			Rounds uint32
1454		}{salt, 16}
1455
1456		// Derive key to encrypt the private key block.
1457		k, err := bcrypt_pbkdf.Key(passphrase, salt, int(opts.Rounds), 32+aes.BlockSize)
1458		if err != nil {
1459			return nil, "", "", "", err
1460		}
1461
1462		// Add padding matching the block size of AES.
1463		keyBlock := generateOpenSSHPadding(privKeyBlock, aes.BlockSize)
1464
1465		// Encrypt the private key using the derived secret.
1466
1467		dst := make([]byte, len(keyBlock))
1468		key, iv := k[:32], k[32:]
1469		block, err := aes.NewCipher(key)
1470		if err != nil {
1471			return nil, "", "", "", err
1472		}
1473
1474		stream := cipher.NewCTR(block, iv)
1475		stream.XORKeyStream(dst, keyBlock)
1476
1477		return dst, "aes256-ctr", "bcrypt", string(Marshal(opts)), nil
1478	}
1479}
1480
1481const privateKeyAuthMagic = "openssh-key-v1\x00"
1482
1483type openSSHDecryptFunc func(CipherName, KdfName, KdfOpts string, PrivKeyBlock []byte) ([]byte, error)
1484type openSSHEncryptFunc func(PrivKeyBlock []byte) (ProtectedKeyBlock []byte, cipherName, kdfName, kdfOptions string, err error)
1485
1486type openSSHEncryptedPrivateKey struct {
1487	CipherName   string
1488	KdfName      string
1489	KdfOpts      string
1490	NumKeys      uint32
1491	PubKey       []byte
1492	PrivKeyBlock []byte
1493	Rest         []byte `ssh:"rest"`
1494}
1495
1496type openSSHPrivateKey struct {
1497	Check1  uint32
1498	Check2  uint32
1499	Keytype string
1500	Rest    []byte `ssh:"rest"`
1501}
1502
1503type openSSHRSAPrivateKey struct {
1504	N       *big.Int
1505	E       *big.Int
1506	D       *big.Int
1507	Iqmp    *big.Int
1508	P       *big.Int
1509	Q       *big.Int
1510	Comment string
1511	Pad     []byte `ssh:"rest"`
1512}
1513
1514type openSSHEd25519PrivateKey struct {
1515	Pub     []byte
1516	Priv    []byte
1517	Comment string
1518	Pad     []byte `ssh:"rest"`
1519}
1520
1521type openSSHECDSAPrivateKey struct {
1522	Curve   string
1523	Pub     []byte
1524	D       *big.Int
1525	Comment string
1526	Pad     []byte `ssh:"rest"`
1527}
1528
1529// parseOpenSSHPrivateKey parses an OpenSSH private key, using the decrypt
1530// function to unwrap the encrypted portion. unencryptedOpenSSHKey can be used
1531// as the decrypt function to parse an unencrypted private key. See
1532// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key.
1533func parseOpenSSHPrivateKey(key []byte, decrypt openSSHDecryptFunc) (crypto.PrivateKey, error) {
1534	if len(key) < len(privateKeyAuthMagic) || string(key[:len(privateKeyAuthMagic)]) != privateKeyAuthMagic {
1535		return nil, errors.New("ssh: invalid openssh private key format")
1536	}
1537	remaining := key[len(privateKeyAuthMagic):]
1538
1539	var w openSSHEncryptedPrivateKey
1540	if err := Unmarshal(remaining, &w); err != nil {
1541		return nil, err
1542	}
1543	if w.NumKeys != 1 {
1544		// We only support single key files, and so does OpenSSH.
1545		// https://github.com/openssh/openssh-portable/blob/4103a3ec7/sshkey.c#L4171
1546		return nil, errors.New("ssh: multi-key files are not supported")
1547	}
1548
1549	privKeyBlock, err := decrypt(w.CipherName, w.KdfName, w.KdfOpts, w.PrivKeyBlock)
1550	if err != nil {
1551		if err, ok := err.(*PassphraseMissingError); ok {
1552			pub, errPub := ParsePublicKey(w.PubKey)
1553			if errPub != nil {
1554				return nil, fmt.Errorf("ssh: failed to parse embedded public key: %v", errPub)
1555			}
1556			err.PublicKey = pub
1557		}
1558		return nil, err
1559	}
1560
1561	var pk1 openSSHPrivateKey
1562	if err := Unmarshal(privKeyBlock, &pk1); err != nil || pk1.Check1 != pk1.Check2 {
1563		if w.CipherName != "none" {
1564			return nil, x509.IncorrectPasswordError
1565		}
1566		return nil, errors.New("ssh: malformed OpenSSH key")
1567	}
1568
1569	switch pk1.Keytype {
1570	case KeyAlgoRSA:
1571		var key openSSHRSAPrivateKey
1572		if err := Unmarshal(pk1.Rest, &key); err != nil {
1573			return nil, err
1574		}
1575
1576		if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
1577			return nil, err
1578		}
1579
1580		pk := &rsa.PrivateKey{
1581			PublicKey: rsa.PublicKey{
1582				N: key.N,
1583				E: int(key.E.Int64()),
1584			},
1585			D:      key.D,
1586			Primes: []*big.Int{key.P, key.Q},
1587		}
1588
1589		if err := pk.Validate(); err != nil {
1590			return nil, err
1591		}
1592
1593		pk.Precompute()
1594
1595		return pk, nil
1596	case KeyAlgoED25519:
1597		var key openSSHEd25519PrivateKey
1598		if err := Unmarshal(pk1.Rest, &key); err != nil {
1599			return nil, err
1600		}
1601
1602		if len(key.Priv) != ed25519.PrivateKeySize {
1603			return nil, errors.New("ssh: private key unexpected length")
1604		}
1605
1606		if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
1607			return nil, err
1608		}
1609
1610		pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
1611		copy(pk, key.Priv)
1612		return &pk, nil
1613	case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
1614		var key openSSHECDSAPrivateKey
1615		if err := Unmarshal(pk1.Rest, &key); err != nil {
1616			return nil, err
1617		}
1618
1619		if err := checkOpenSSHKeyPadding(key.Pad); err != nil {
1620			return nil, err
1621		}
1622
1623		var curve elliptic.Curve
1624		switch key.Curve {
1625		case "nistp256":
1626			curve = elliptic.P256()
1627		case "nistp384":
1628			curve = elliptic.P384()
1629		case "nistp521":
1630			curve = elliptic.P521()
1631		default:
1632			return nil, errors.New("ssh: unhandled elliptic curve: " + key.Curve)
1633		}
1634
1635		X, Y := elliptic.Unmarshal(curve, key.Pub)
1636		if X == nil || Y == nil {
1637			return nil, errors.New("ssh: failed to unmarshal public key")
1638		}
1639
1640		if key.D.Cmp(curve.Params().N) >= 0 {
1641			return nil, errors.New("ssh: scalar is out of range")
1642		}
1643
1644		x, y := curve.ScalarBaseMult(key.D.Bytes())
1645		if x.Cmp(X) != 0 || y.Cmp(Y) != 0 {
1646			return nil, errors.New("ssh: public key does not match private key")
1647		}
1648
1649		return &ecdsa.PrivateKey{
1650			PublicKey: ecdsa.PublicKey{
1651				Curve: curve,
1652				X:     X,
1653				Y:     Y,
1654			},
1655			D: key.D,
1656		}, nil
1657	default:
1658		return nil, errors.New("ssh: unhandled key type")
1659	}
1660}
1661
1662func marshalOpenSSHPrivateKey(key crypto.PrivateKey, comment string, encrypt openSSHEncryptFunc) (*pem.Block, error) {
1663	var w openSSHEncryptedPrivateKey
1664	var pk1 openSSHPrivateKey
1665
1666	// Random check bytes.
1667	var check uint32
1668	if err := binary.Read(rand.Reader, binary.BigEndian, &check); err != nil {
1669		return nil, err
1670	}
1671
1672	pk1.Check1 = check
1673	pk1.Check2 = check
1674	w.NumKeys = 1
1675
1676	// Use a []byte directly on ed25519 keys.
1677	if k, ok := key.(*ed25519.PrivateKey); ok {
1678		key = *k
1679	}
1680
1681	switch k := key.(type) {
1682	case *rsa.PrivateKey:
1683		E := new(big.Int).SetInt64(int64(k.PublicKey.E))
1684		// Marshal public key:
1685		// E and N are in reversed order in the public and private key.
1686		pubKey := struct {
1687			KeyType string
1688			E       *big.Int
1689			N       *big.Int
1690		}{
1691			KeyAlgoRSA,
1692			E, k.PublicKey.N,
1693		}
1694		w.PubKey = Marshal(pubKey)
1695
1696		// Marshal private key.
1697		key := openSSHRSAPrivateKey{
1698			N:       k.PublicKey.N,
1699			E:       E,
1700			D:       k.D,
1701			Iqmp:    k.Precomputed.Qinv,
1702			P:       k.Primes[0],
1703			Q:       k.Primes[1],
1704			Comment: comment,
1705		}
1706		pk1.Keytype = KeyAlgoRSA
1707		pk1.Rest = Marshal(key)
1708	case ed25519.PrivateKey:
1709		pub := make([]byte, ed25519.PublicKeySize)
1710		priv := make([]byte, ed25519.PrivateKeySize)
1711		copy(pub, k[32:])
1712		copy(priv, k)
1713
1714		// Marshal public key.
1715		pubKey := struct {
1716			KeyType string
1717			Pub     []byte
1718		}{
1719			KeyAlgoED25519, pub,
1720		}
1721		w.PubKey = Marshal(pubKey)
1722
1723		// Marshal private key.
1724		key := openSSHEd25519PrivateKey{
1725			Pub:     pub,
1726			Priv:    priv,
1727			Comment: comment,
1728		}
1729		pk1.Keytype = KeyAlgoED25519
1730		pk1.Rest = Marshal(key)
1731	case *ecdsa.PrivateKey:
1732		var curve, keyType string
1733		switch name := k.Curve.Params().Name; name {
1734		case "P-256":
1735			curve = "nistp256"
1736			keyType = KeyAlgoECDSA256
1737		case "P-384":
1738			curve = "nistp384"
1739			keyType = KeyAlgoECDSA384
1740		case "P-521":
1741			curve = "nistp521"
1742			keyType = KeyAlgoECDSA521
1743		default:
1744			return nil, errors.New("ssh: unhandled elliptic curve " + name)
1745		}
1746
1747		pub := elliptic.Marshal(k.Curve, k.PublicKey.X, k.PublicKey.Y)
1748
1749		// Marshal public key.
1750		pubKey := struct {
1751			KeyType string
1752			Curve   string
1753			Pub     []byte
1754		}{
1755			keyType, curve, pub,
1756		}
1757		w.PubKey = Marshal(pubKey)
1758
1759		// Marshal private key.
1760		key := openSSHECDSAPrivateKey{
1761			Curve:   curve,
1762			Pub:     pub,
1763			D:       k.D,
1764			Comment: comment,
1765		}
1766		pk1.Keytype = keyType
1767		pk1.Rest = Marshal(key)
1768	default:
1769		return nil, fmt.Errorf("ssh: unsupported key type %T", k)
1770	}
1771
1772	var err error
1773	// Add padding and encrypt the key if necessary.
1774	w.PrivKeyBlock, w.CipherName, w.KdfName, w.KdfOpts, err = encrypt(Marshal(pk1))
1775	if err != nil {
1776		return nil, err
1777	}
1778
1779	b := Marshal(w)
1780	block := &pem.Block{
1781		Type:  "OPENSSH PRIVATE KEY",
1782		Bytes: append([]byte(privateKeyAuthMagic), b...),
1783	}
1784	return block, nil
1785}
1786
1787func checkOpenSSHKeyPadding(pad []byte) error {
1788	for i, b := range pad {
1789		if int(b) != i+1 {
1790			return errors.New("ssh: padding not as expected")
1791		}
1792	}
1793	return nil
1794}
1795
1796func generateOpenSSHPadding(block []byte, blockSize int) []byte {
1797	for i, l := 0, len(block); (l+i)%blockSize != 0; i++ {
1798		block = append(block, byte(i+1))
1799	}
1800	return block
1801}
1802
1803// FingerprintLegacyMD5 returns the user presentation of the key's
1804// fingerprint as described by RFC 4716 section 4.
1805func FingerprintLegacyMD5(pubKey PublicKey) string {
1806	md5sum := md5.Sum(pubKey.Marshal())
1807	hexarray := make([]string, len(md5sum))
1808	for i, c := range md5sum {
1809		hexarray[i] = hex.EncodeToString([]byte{c})
1810	}
1811	return strings.Join(hexarray, ":")
1812}
1813
1814// FingerprintSHA256 returns the user presentation of the key's
1815// fingerprint as unpadded base64 encoded sha256 hash.
1816// This format was introduced from OpenSSH 6.8.
1817// https://www.openssh.com/txt/release-6.8
1818// https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
1819func FingerprintSHA256(pubKey PublicKey) string {
1820	sha256sum := sha256.Sum256(pubKey.Marshal())
1821	hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
1822	return "SHA256:" + hash
1823}