OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / ssh / keys.go
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
5 package ssh
6
7 import (
8         "bytes"
9         "crypto"
10         "crypto/dsa"
11         "crypto/ecdsa"
12         "crypto/elliptic"
13         "crypto/md5"
14         "crypto/rsa"
15         "crypto/sha256"
16         "crypto/x509"
17         "encoding/asn1"
18         "encoding/base64"
19         "encoding/hex"
20         "encoding/pem"
21         "errors"
22         "fmt"
23         "io"
24         "math/big"
25         "strings"
26
27         "golang.org/x/crypto/ed25519"
28 )
29
30 // These constants represent the algorithm names for key types supported by this
31 // package.
32 const (
33         KeyAlgoRSA      = "ssh-rsa"
34         KeyAlgoDSA      = "ssh-dss"
35         KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
36         KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
37         KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
38         KeyAlgoED25519  = "ssh-ed25519"
39 )
40
41 // parsePubKey parses a public key of the given algorithm.
42 // Use ParsePublicKey for keys with prepended algorithm.
43 func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) {
44         switch algo {
45         case KeyAlgoRSA:
46                 return parseRSA(in)
47         case KeyAlgoDSA:
48                 return parseDSA(in)
49         case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
50                 return parseECDSA(in)
51         case KeyAlgoED25519:
52                 return parseED25519(in)
53         case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
54                 cert, err := parseCert(in, certToPrivAlgo(algo))
55                 if err != nil {
56                         return nil, nil, err
57                 }
58                 return cert, nil, nil
59         }
60         return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
61 }
62
63 // parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
64 // (see sshd(8) manual page) once the options and key type fields have been
65 // removed.
66 func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) {
67         in = bytes.TrimSpace(in)
68
69         i := bytes.IndexAny(in, " \t")
70         if i == -1 {
71                 i = len(in)
72         }
73         base64Key := in[:i]
74
75         key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key)))
76         n, err := base64.StdEncoding.Decode(key, base64Key)
77         if err != nil {
78                 return nil, "", err
79         }
80         key = key[:n]
81         out, err = ParsePublicKey(key)
82         if err != nil {
83                 return nil, "", err
84         }
85         comment = string(bytes.TrimSpace(in[i:]))
86         return out, comment, nil
87 }
88
89 // ParseKnownHosts parses an entry in the format of the known_hosts file.
90 //
91 // The known_hosts format is documented in the sshd(8) manual page. This
92 // function will parse a single entry from in. On successful return, marker
93 // will contain the optional marker value (i.e. "cert-authority" or "revoked")
94 // or else be empty, hosts will contain the hosts that this entry matches,
95 // pubKey will contain the public key and comment will contain any trailing
96 // comment at the end of the line. See the sshd(8) manual page for the various
97 // forms that a host string can take.
98 //
99 // The unparsed remainder of the input will be returned in rest. This function
100 // can be called repeatedly to parse multiple entries.
101 //
102 // If no entries were found in the input then err will be io.EOF. Otherwise a
103 // non-nil err value indicates a parse error.
104 func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) {
105         for len(in) > 0 {
106                 end := bytes.IndexByte(in, '\n')
107                 if end != -1 {
108                         rest = in[end+1:]
109                         in = in[:end]
110                 } else {
111                         rest = nil
112                 }
113
114                 end = bytes.IndexByte(in, '\r')
115                 if end != -1 {
116                         in = in[:end]
117                 }
118
119                 in = bytes.TrimSpace(in)
120                 if len(in) == 0 || in[0] == '#' {
121                         in = rest
122                         continue
123                 }
124
125                 i := bytes.IndexAny(in, " \t")
126                 if i == -1 {
127                         in = rest
128                         continue
129                 }
130
131                 // Strip out the beginning of the known_host key.
132                 // This is either an optional marker or a (set of) hostname(s).
133                 keyFields := bytes.Fields(in)
134                 if len(keyFields) < 3 || len(keyFields) > 5 {
135                         return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
136                 }
137
138                 // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
139                 // list of hosts
140                 marker := ""
141                 if keyFields[0][0] == '@' {
142                         marker = string(keyFields[0][1:])
143                         keyFields = keyFields[1:]
144                 }
145
146                 hosts := string(keyFields[0])
147                 // keyFields[1] contains the key type (e.g. “ssh-rsa”).
148                 // However, that information is duplicated inside the
149                 // base64-encoded key and so is ignored here.
150
151                 key := bytes.Join(keyFields[2:], []byte(" "))
152                 if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
153                         return "", nil, nil, "", nil, err
154                 }
155
156                 return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
157         }
158
159         return "", nil, nil, "", nil, io.EOF
160 }
161
162 // ParseAuthorizedKeys parses a public key from an authorized_keys
163 // file used in OpenSSH according to the sshd(8) manual page.
164 func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
165         for len(in) > 0 {
166                 end := bytes.IndexByte(in, '\n')
167                 if end != -1 {
168                         rest = in[end+1:]
169                         in = in[:end]
170                 } else {
171                         rest = nil
172                 }
173
174                 end = bytes.IndexByte(in, '\r')
175                 if end != -1 {
176                         in = in[:end]
177                 }
178
179                 in = bytes.TrimSpace(in)
180                 if len(in) == 0 || in[0] == '#' {
181                         in = rest
182                         continue
183                 }
184
185                 i := bytes.IndexAny(in, " \t")
186                 if i == -1 {
187                         in = rest
188                         continue
189                 }
190
191                 if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
192                         return out, comment, options, rest, nil
193                 }
194
195                 // No key type recognised. Maybe there's an options field at
196                 // the beginning.
197                 var b byte
198                 inQuote := false
199                 var candidateOptions []string
200                 optionStart := 0
201                 for i, b = range in {
202                         isEnd := !inQuote && (b == ' ' || b == '\t')
203                         if (b == ',' && !inQuote) || isEnd {
204                                 if i-optionStart > 0 {
205                                         candidateOptions = append(candidateOptions, string(in[optionStart:i]))
206                                 }
207                                 optionStart = i + 1
208                         }
209                         if isEnd {
210                                 break
211                         }
212                         if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) {
213                                 inQuote = !inQuote
214                         }
215                 }
216                 for i < len(in) && (in[i] == ' ' || in[i] == '\t') {
217                         i++
218                 }
219                 if i == len(in) {
220                         // Invalid line: unmatched quote
221                         in = rest
222                         continue
223                 }
224
225                 in = in[i:]
226                 i = bytes.IndexAny(in, " \t")
227                 if i == -1 {
228                         in = rest
229                         continue
230                 }
231
232                 if out, comment, err = parseAuthorizedKey(in[i:]); err == nil {
233                         options = candidateOptions
234                         return out, comment, options, rest, nil
235                 }
236
237                 in = rest
238                 continue
239         }
240
241         return nil, "", nil, nil, errors.New("ssh: no key found")
242 }
243
244 // ParsePublicKey parses an SSH public key formatted for use in
245 // the SSH wire protocol according to RFC 4253, section 6.6.
246 func ParsePublicKey(in []byte) (out PublicKey, err error) {
247         algo, in, ok := parseString(in)
248         if !ok {
249                 return nil, errShortRead
250         }
251         var rest []byte
252         out, rest, err = parsePubKey(in, string(algo))
253         if len(rest) > 0 {
254                 return nil, errors.New("ssh: trailing junk in public key")
255         }
256
257         return out, err
258 }
259
260 // MarshalAuthorizedKey serializes key for inclusion in an OpenSSH
261 // authorized_keys file. The return value ends with newline.
262 func MarshalAuthorizedKey(key PublicKey) []byte {
263         b := &bytes.Buffer{}
264         b.WriteString(key.Type())
265         b.WriteByte(' ')
266         e := base64.NewEncoder(base64.StdEncoding, b)
267         e.Write(key.Marshal())
268         e.Close()
269         b.WriteByte('\n')
270         return b.Bytes()
271 }
272
273 // PublicKey is an abstraction of different types of public keys.
274 type PublicKey interface {
275         // Type returns the key's type, e.g. "ssh-rsa".
276         Type() string
277
278         // Marshal returns the serialized key data in SSH wire format,
279         // with the name prefix.
280         Marshal() []byte
281
282         // Verify that sig is a signature on the given data using this
283         // key. This function will hash the data appropriately first.
284         Verify(data []byte, sig *Signature) error
285 }
286
287 // CryptoPublicKey, if implemented by a PublicKey,
288 // returns the underlying crypto.PublicKey form of the key.
289 type CryptoPublicKey interface {
290         CryptoPublicKey() crypto.PublicKey
291 }
292
293 // A Signer can create signatures that verify against a public key.
294 type Signer interface {
295         // PublicKey returns an associated PublicKey instance.
296         PublicKey() PublicKey
297
298         // Sign returns raw signature for the given data. This method
299         // will apply the hash specified for the keytype to the data.
300         Sign(rand io.Reader, data []byte) (*Signature, error)
301 }
302
303 type rsaPublicKey rsa.PublicKey
304
305 func (r *rsaPublicKey) Type() string {
306         return "ssh-rsa"
307 }
308
309 // parseRSA parses an RSA key according to RFC 4253, section 6.6.
310 func parseRSA(in []byte) (out PublicKey, rest []byte, err error) {
311         var w struct {
312                 E    *big.Int
313                 N    *big.Int
314                 Rest []byte `ssh:"rest"`
315         }
316         if err := Unmarshal(in, &w); err != nil {
317                 return nil, nil, err
318         }
319
320         if w.E.BitLen() > 24 {
321                 return nil, nil, errors.New("ssh: exponent too large")
322         }
323         e := w.E.Int64()
324         if e < 3 || e&1 == 0 {
325                 return nil, nil, errors.New("ssh: incorrect exponent")
326         }
327
328         var key rsa.PublicKey
329         key.E = int(e)
330         key.N = w.N
331         return (*rsaPublicKey)(&key), w.Rest, nil
332 }
333
334 func (r *rsaPublicKey) Marshal() []byte {
335         e := new(big.Int).SetInt64(int64(r.E))
336         // RSA publickey struct layout should match the struct used by
337         // parseRSACert in the x/crypto/ssh/agent package.
338         wirekey := struct {
339                 Name string
340                 E    *big.Int
341                 N    *big.Int
342         }{
343                 KeyAlgoRSA,
344                 e,
345                 r.N,
346         }
347         return Marshal(&wirekey)
348 }
349
350 func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error {
351         if sig.Format != r.Type() {
352                 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type())
353         }
354         h := crypto.SHA1.New()
355         h.Write(data)
356         digest := h.Sum(nil)
357         return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
358 }
359
360 func (r *rsaPublicKey) CryptoPublicKey() crypto.PublicKey {
361         return (*rsa.PublicKey)(r)
362 }
363
364 type dsaPublicKey dsa.PublicKey
365
366 func (r *dsaPublicKey) Type() string {
367         return "ssh-dss"
368 }
369
370 // parseDSA parses an DSA key according to RFC 4253, section 6.6.
371 func parseDSA(in []byte) (out PublicKey, rest []byte, err error) {
372         var w struct {
373                 P, Q, G, Y *big.Int
374                 Rest       []byte `ssh:"rest"`
375         }
376         if err := Unmarshal(in, &w); err != nil {
377                 return nil, nil, err
378         }
379
380         key := &dsaPublicKey{
381                 Parameters: dsa.Parameters{
382                         P: w.P,
383                         Q: w.Q,
384                         G: w.G,
385                 },
386                 Y: w.Y,
387         }
388         return key, w.Rest, nil
389 }
390
391 func (k *dsaPublicKey) Marshal() []byte {
392         // DSA publickey struct layout should match the struct used by
393         // parseDSACert in the x/crypto/ssh/agent package.
394         w := struct {
395                 Name       string
396                 P, Q, G, Y *big.Int
397         }{
398                 k.Type(),
399                 k.P,
400                 k.Q,
401                 k.G,
402                 k.Y,
403         }
404
405         return Marshal(&w)
406 }
407
408 func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error {
409         if sig.Format != k.Type() {
410                 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type())
411         }
412         h := crypto.SHA1.New()
413         h.Write(data)
414         digest := h.Sum(nil)
415
416         // Per RFC 4253, section 6.6,
417         // The value for 'dss_signature_blob' is encoded as a string containing
418         // r, followed by s (which are 160-bit integers, without lengths or
419         // padding, unsigned, and in network byte order).
420         // For DSS purposes, sig.Blob should be exactly 40 bytes in length.
421         if len(sig.Blob) != 40 {
422                 return errors.New("ssh: DSA signature parse error")
423         }
424         r := new(big.Int).SetBytes(sig.Blob[:20])
425         s := new(big.Int).SetBytes(sig.Blob[20:])
426         if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) {
427                 return nil
428         }
429         return errors.New("ssh: signature did not verify")
430 }
431
432 func (k *dsaPublicKey) CryptoPublicKey() crypto.PublicKey {
433         return (*dsa.PublicKey)(k)
434 }
435
436 type dsaPrivateKey struct {
437         *dsa.PrivateKey
438 }
439
440 func (k *dsaPrivateKey) PublicKey() PublicKey {
441         return (*dsaPublicKey)(&k.PrivateKey.PublicKey)
442 }
443
444 func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
445         h := crypto.SHA1.New()
446         h.Write(data)
447         digest := h.Sum(nil)
448         r, s, err := dsa.Sign(rand, k.PrivateKey, digest)
449         if err != nil {
450                 return nil, err
451         }
452
453         sig := make([]byte, 40)
454         rb := r.Bytes()
455         sb := s.Bytes()
456
457         copy(sig[20-len(rb):20], rb)
458         copy(sig[40-len(sb):], sb)
459
460         return &Signature{
461                 Format: k.PublicKey().Type(),
462                 Blob:   sig,
463         }, nil
464 }
465
466 type ecdsaPublicKey ecdsa.PublicKey
467
468 func (key *ecdsaPublicKey) Type() string {
469         return "ecdsa-sha2-" + key.nistID()
470 }
471
472 func (key *ecdsaPublicKey) nistID() string {
473         switch key.Params().BitSize {
474         case 256:
475                 return "nistp256"
476         case 384:
477                 return "nistp384"
478         case 521:
479                 return "nistp521"
480         }
481         panic("ssh: unsupported ecdsa key size")
482 }
483
484 type ed25519PublicKey ed25519.PublicKey
485
486 func (key ed25519PublicKey) Type() string {
487         return KeyAlgoED25519
488 }
489
490 func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
491         var w struct {
492                 KeyBytes []byte
493                 Rest     []byte `ssh:"rest"`
494         }
495
496         if err := Unmarshal(in, &w); err != nil {
497                 return nil, nil, err
498         }
499
500         key := ed25519.PublicKey(w.KeyBytes)
501
502         return (ed25519PublicKey)(key), w.Rest, nil
503 }
504
505 func (key ed25519PublicKey) Marshal() []byte {
506         w := struct {
507                 Name     string
508                 KeyBytes []byte
509         }{
510                 KeyAlgoED25519,
511                 []byte(key),
512         }
513         return Marshal(&w)
514 }
515
516 func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
517         if sig.Format != key.Type() {
518                 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
519         }
520
521         edKey := (ed25519.PublicKey)(key)
522         if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
523                 return errors.New("ssh: signature did not verify")
524         }
525
526         return nil
527 }
528
529 func (k ed25519PublicKey) CryptoPublicKey() crypto.PublicKey {
530         return ed25519.PublicKey(k)
531 }
532
533 func supportedEllipticCurve(curve elliptic.Curve) bool {
534         return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
535 }
536
537 // ecHash returns the hash to match the given elliptic curve, see RFC
538 // 5656, section 6.2.1
539 func ecHash(curve elliptic.Curve) crypto.Hash {
540         bitSize := curve.Params().BitSize
541         switch {
542         case bitSize <= 256:
543                 return crypto.SHA256
544         case bitSize <= 384:
545                 return crypto.SHA384
546         }
547         return crypto.SHA512
548 }
549
550 // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1.
551 func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) {
552         var w struct {
553                 Curve    string
554                 KeyBytes []byte
555                 Rest     []byte `ssh:"rest"`
556         }
557
558         if err := Unmarshal(in, &w); err != nil {
559                 return nil, nil, err
560         }
561
562         key := new(ecdsa.PublicKey)
563
564         switch w.Curve {
565         case "nistp256":
566                 key.Curve = elliptic.P256()
567         case "nistp384":
568                 key.Curve = elliptic.P384()
569         case "nistp521":
570                 key.Curve = elliptic.P521()
571         default:
572                 return nil, nil, errors.New("ssh: unsupported curve")
573         }
574
575         key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes)
576         if key.X == nil || key.Y == nil {
577                 return nil, nil, errors.New("ssh: invalid curve point")
578         }
579         return (*ecdsaPublicKey)(key), w.Rest, nil
580 }
581
582 func (key *ecdsaPublicKey) Marshal() []byte {
583         // See RFC 5656, section 3.1.
584         keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
585         // ECDSA publickey struct layout should match the struct used by
586         // parseECDSACert in the x/crypto/ssh/agent package.
587         w := struct {
588                 Name string
589                 ID   string
590                 Key  []byte
591         }{
592                 key.Type(),
593                 key.nistID(),
594                 keyBytes,
595         }
596
597         return Marshal(&w)
598 }
599
600 func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error {
601         if sig.Format != key.Type() {
602                 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
603         }
604
605         h := ecHash(key.Curve).New()
606         h.Write(data)
607         digest := h.Sum(nil)
608
609         // Per RFC 5656, section 3.1.2,
610         // The ecdsa_signature_blob value has the following specific encoding:
611         //    mpint    r
612         //    mpint    s
613         var ecSig struct {
614                 R *big.Int
615                 S *big.Int
616         }
617
618         if err := Unmarshal(sig.Blob, &ecSig); err != nil {
619                 return err
620         }
621
622         if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) {
623                 return nil
624         }
625         return errors.New("ssh: signature did not verify")
626 }
627
628 func (k *ecdsaPublicKey) CryptoPublicKey() crypto.PublicKey {
629         return (*ecdsa.PublicKey)(k)
630 }
631
632 // NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
633 // *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
634 // Signer instance. ECDSA keys must use P-256, P-384 or P-521.
635 func NewSignerFromKey(key interface{}) (Signer, error) {
636         switch key := key.(type) {
637         case crypto.Signer:
638                 return NewSignerFromSigner(key)
639         case *dsa.PrivateKey:
640                 return &dsaPrivateKey{key}, nil
641         default:
642                 return nil, fmt.Errorf("ssh: unsupported key type %T", key)
643         }
644 }
645
646 type wrappedSigner struct {
647         signer crypto.Signer
648         pubKey PublicKey
649 }
650
651 // NewSignerFromSigner takes any crypto.Signer implementation and
652 // returns a corresponding Signer interface. This can be used, for
653 // example, with keys kept in hardware modules.
654 func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
655         pubKey, err := NewPublicKey(signer.Public())
656         if err != nil {
657                 return nil, err
658         }
659
660         return &wrappedSigner{signer, pubKey}, nil
661 }
662
663 func (s *wrappedSigner) PublicKey() PublicKey {
664         return s.pubKey
665 }
666
667 func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
668         var hashFunc crypto.Hash
669
670         switch key := s.pubKey.(type) {
671         case *rsaPublicKey, *dsaPublicKey:
672                 hashFunc = crypto.SHA1
673         case *ecdsaPublicKey:
674                 hashFunc = ecHash(key.Curve)
675         case ed25519PublicKey:
676         default:
677                 return nil, fmt.Errorf("ssh: unsupported key type %T", key)
678         }
679
680         var digest []byte
681         if hashFunc != 0 {
682                 h := hashFunc.New()
683                 h.Write(data)
684                 digest = h.Sum(nil)
685         } else {
686                 digest = data
687         }
688
689         signature, err := s.signer.Sign(rand, digest, hashFunc)
690         if err != nil {
691                 return nil, err
692         }
693
694         // crypto.Signer.Sign is expected to return an ASN.1-encoded signature
695         // for ECDSA and DSA, but that's not the encoding expected by SSH, so
696         // re-encode.
697         switch s.pubKey.(type) {
698         case *ecdsaPublicKey, *dsaPublicKey:
699                 type asn1Signature struct {
700                         R, S *big.Int
701                 }
702                 asn1Sig := new(asn1Signature)
703                 _, err := asn1.Unmarshal(signature, asn1Sig)
704                 if err != nil {
705                         return nil, err
706                 }
707
708                 switch s.pubKey.(type) {
709                 case *ecdsaPublicKey:
710                         signature = Marshal(asn1Sig)
711
712                 case *dsaPublicKey:
713                         signature = make([]byte, 40)
714                         r := asn1Sig.R.Bytes()
715                         s := asn1Sig.S.Bytes()
716                         copy(signature[20-len(r):20], r)
717                         copy(signature[40-len(s):40], s)
718                 }
719         }
720
721         return &Signature{
722                 Format: s.pubKey.Type(),
723                 Blob:   signature,
724         }, nil
725 }
726
727 // NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
728 // or ed25519.PublicKey returns a corresponding PublicKey instance.
729 // ECDSA keys must use P-256, P-384 or P-521.
730 func NewPublicKey(key interface{}) (PublicKey, error) {
731         switch key := key.(type) {
732         case *rsa.PublicKey:
733                 return (*rsaPublicKey)(key), nil
734         case *ecdsa.PublicKey:
735                 if !supportedEllipticCurve(key.Curve) {
736                         return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.")
737                 }
738                 return (*ecdsaPublicKey)(key), nil
739         case *dsa.PublicKey:
740                 return (*dsaPublicKey)(key), nil
741         case ed25519.PublicKey:
742                 return (ed25519PublicKey)(key), nil
743         default:
744                 return nil, fmt.Errorf("ssh: unsupported key type %T", key)
745         }
746 }
747
748 // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
749 // the same keys as ParseRawPrivateKey.
750 func ParsePrivateKey(pemBytes []byte) (Signer, error) {
751         key, err := ParseRawPrivateKey(pemBytes)
752         if err != nil {
753                 return nil, err
754         }
755
756         return NewSignerFromKey(key)
757 }
758
759 // ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private
760 // key and passphrase. It supports the same keys as
761 // ParseRawPrivateKeyWithPassphrase.
762 func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error) {
763         key, err := ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase)
764         if err != nil {
765                 return nil, err
766         }
767
768         return NewSignerFromKey(key)
769 }
770
771 // encryptedBlock tells whether a private key is
772 // encrypted by examining its Proc-Type header
773 // for a mention of ENCRYPTED
774 // according to RFC 1421 Section 4.6.1.1.
775 func encryptedBlock(block *pem.Block) bool {
776         return strings.Contains(block.Headers["Proc-Type"], "ENCRYPTED")
777 }
778
779 // ParseRawPrivateKey returns a private key from a PEM encoded private key. It
780 // supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.
781 func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) {
782         block, _ := pem.Decode(pemBytes)
783         if block == nil {
784                 return nil, errors.New("ssh: no key found")
785         }
786
787         if encryptedBlock(block) {
788                 return nil, errors.New("ssh: cannot decode encrypted private keys")
789         }
790
791         switch block.Type {
792         case "RSA PRIVATE KEY":
793                 return x509.ParsePKCS1PrivateKey(block.Bytes)
794         case "EC PRIVATE KEY":
795                 return x509.ParseECPrivateKey(block.Bytes)
796         case "DSA PRIVATE KEY":
797                 return ParseDSAPrivateKey(block.Bytes)
798         case "OPENSSH PRIVATE KEY":
799                 return parseOpenSSHPrivateKey(block.Bytes)
800         default:
801                 return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
802         }
803 }
804
805 // ParseRawPrivateKeyWithPassphrase returns a private key decrypted with
806 // passphrase from a PEM encoded private key. If wrong passphrase, return
807 // x509.IncorrectPasswordError.
808 func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error) {
809         block, _ := pem.Decode(pemBytes)
810         if block == nil {
811                 return nil, errors.New("ssh: no key found")
812         }
813         buf := block.Bytes
814
815         if encryptedBlock(block) {
816                 if x509.IsEncryptedPEMBlock(block) {
817                         var err error
818                         buf, err = x509.DecryptPEMBlock(block, passPhrase)
819                         if err != nil {
820                                 if err == x509.IncorrectPasswordError {
821                                         return nil, err
822                                 }
823                                 return nil, fmt.Errorf("ssh: cannot decode encrypted private keys: %v", err)
824                         }
825                 }
826         }
827
828         switch block.Type {
829         case "RSA PRIVATE KEY":
830                 return x509.ParsePKCS1PrivateKey(buf)
831         case "EC PRIVATE KEY":
832                 return x509.ParseECPrivateKey(buf)
833         case "DSA PRIVATE KEY":
834                 return ParseDSAPrivateKey(buf)
835         case "OPENSSH PRIVATE KEY":
836                 return parseOpenSSHPrivateKey(buf)
837         default:
838                 return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
839         }
840 }
841
842 // ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as
843 // specified by the OpenSSL DSA man page.
844 func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) {
845         var k struct {
846                 Version int
847                 P       *big.Int
848                 Q       *big.Int
849                 G       *big.Int
850                 Pub     *big.Int
851                 Priv    *big.Int
852         }
853         rest, err := asn1.Unmarshal(der, &k)
854         if err != nil {
855                 return nil, errors.New("ssh: failed to parse DSA key: " + err.Error())
856         }
857         if len(rest) > 0 {
858                 return nil, errors.New("ssh: garbage after DSA key")
859         }
860
861         return &dsa.PrivateKey{
862                 PublicKey: dsa.PublicKey{
863                         Parameters: dsa.Parameters{
864                                 P: k.P,
865                                 Q: k.Q,
866                                 G: k.G,
867                         },
868                         Y: k.Pub,
869                 },
870                 X: k.Priv,
871         }, nil
872 }
873
874 // Implemented based on the documentation at
875 // https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
876 func parseOpenSSHPrivateKey(key []byte) (crypto.PrivateKey, error) {
877         magic := append([]byte("openssh-key-v1"), 0)
878         if !bytes.Equal(magic, key[0:len(magic)]) {
879                 return nil, errors.New("ssh: invalid openssh private key format")
880         }
881         remaining := key[len(magic):]
882
883         var w struct {
884                 CipherName   string
885                 KdfName      string
886                 KdfOpts      string
887                 NumKeys      uint32
888                 PubKey       []byte
889                 PrivKeyBlock []byte
890         }
891
892         if err := Unmarshal(remaining, &w); err != nil {
893                 return nil, err
894         }
895
896         if w.KdfName != "none" || w.CipherName != "none" {
897                 return nil, errors.New("ssh: cannot decode encrypted private keys")
898         }
899
900         pk1 := struct {
901                 Check1  uint32
902                 Check2  uint32
903                 Keytype string
904                 Rest    []byte `ssh:"rest"`
905         }{}
906
907         if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
908                 return nil, err
909         }
910
911         if pk1.Check1 != pk1.Check2 {
912                 return nil, errors.New("ssh: checkint mismatch")
913         }
914
915         // we only handle ed25519 and rsa keys currently
916         switch pk1.Keytype {
917         case KeyAlgoRSA:
918                 // https://github.com/openssh/openssh-portable/blob/master/sshkey.c#L2760-L2773
919                 key := struct {
920                         N       *big.Int
921                         E       *big.Int
922                         D       *big.Int
923                         Iqmp    *big.Int
924                         P       *big.Int
925                         Q       *big.Int
926                         Comment string
927                         Pad     []byte `ssh:"rest"`
928                 }{}
929
930                 if err := Unmarshal(pk1.Rest, &key); err != nil {
931                         return nil, err
932                 }
933
934                 for i, b := range key.Pad {
935                         if int(b) != i+1 {
936                                 return nil, errors.New("ssh: padding not as expected")
937                         }
938                 }
939
940                 pk := &rsa.PrivateKey{
941                         PublicKey: rsa.PublicKey{
942                                 N: key.N,
943                                 E: int(key.E.Int64()),
944                         },
945                         D:      key.D,
946                         Primes: []*big.Int{key.P, key.Q},
947                 }
948
949                 if err := pk.Validate(); err != nil {
950                         return nil, err
951                 }
952
953                 pk.Precompute()
954
955                 return pk, nil
956         case KeyAlgoED25519:
957                 key := struct {
958                         Pub     []byte
959                         Priv    []byte
960                         Comment string
961                         Pad     []byte `ssh:"rest"`
962                 }{}
963
964                 if err := Unmarshal(pk1.Rest, &key); err != nil {
965                         return nil, err
966                 }
967
968                 if len(key.Priv) != ed25519.PrivateKeySize {
969                         return nil, errors.New("ssh: private key unexpected length")
970                 }
971
972                 for i, b := range key.Pad {
973                         if int(b) != i+1 {
974                                 return nil, errors.New("ssh: padding not as expected")
975                         }
976                 }
977
978                 pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
979                 copy(pk, key.Priv)
980                 return &pk, nil
981         default:
982                 return nil, errors.New("ssh: unhandled key type")
983         }
984 }
985
986 // FingerprintLegacyMD5 returns the user presentation of the key's
987 // fingerprint as described by RFC 4716 section 4.
988 func FingerprintLegacyMD5(pubKey PublicKey) string {
989         md5sum := md5.Sum(pubKey.Marshal())
990         hexarray := make([]string, len(md5sum))
991         for i, c := range md5sum {
992                 hexarray[i] = hex.EncodeToString([]byte{c})
993         }
994         return strings.Join(hexarray, ":")
995 }
996
997 // FingerprintSHA256 returns the user presentation of the key's
998 // fingerprint as unpadded base64 encoded sha256 hash.
999 // This format was introduced from OpenSSH 6.8.
1000 // https://www.openssh.com/txt/release-6.8
1001 // https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)
1002 func FingerprintSHA256(pubKey PublicKey) string {
1003         sha256sum := sha256.Sum256(pubKey.Marshal())
1004         hash := base64.RawStdEncoding.EncodeToString(sha256sum[:])
1005         return "SHA256:" + hash
1006 }