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