~juju-qa/ubuntu/xenial/juju/2.0-rc2

« back to all changes in this revision

Viewing changes to src/golang.org/x/crypto/ssh/keys.go

  • Committer: Nicholas Skaggs
  • Date: 2016-09-30 14:39:30 UTC
  • mfrom: (1.8.1)
  • Revision ID: nicholas.skaggs@canonical.com-20160930143930-vwwhrefh6ftckccy
import upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
        "fmt"
20
20
        "io"
21
21
        "math/big"
 
22
        "strings"
 
23
 
 
24
        "golang.org/x/crypto/ed25519"
22
25
)
23
26
 
24
27
// These constants represent the algorithm names for key types supported by this
29
32
        KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
30
33
        KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
31
34
        KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
 
35
        KeyAlgoED25519  = "ssh-ed25519"
32
36
)
33
37
 
34
38
// parsePubKey parses a public key of the given algorithm.
41
45
                return parseDSA(in)
42
46
        case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521:
43
47
                return parseECDSA(in)
44
 
        case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
 
48
        case KeyAlgoED25519:
 
49
                return parseED25519(in)
 
50
        case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01:
45
51
                cert, err := parseCert(in, certToPrivAlgo(algo))
46
52
                if err != nil {
47
53
                        return nil, nil, err
48
54
                }
49
55
                return cert, nil, nil
50
56
        }
51
 
        return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", err)
 
57
        return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", algo)
52
58
}
53
59
 
54
60
// parseAuthorizedKey parses a public key in OpenSSH authorized_keys format
77
83
        return out, comment, nil
78
84
}
79
85
 
 
86
// ParseKnownHosts parses an entry in the format of the known_hosts file.
 
87
//
 
88
// The known_hosts format is documented in the sshd(8) manual page. This
 
89
// function will parse a single entry from in. On successful return, marker
 
90
// will contain the optional marker value (i.e. "cert-authority" or "revoked")
 
91
// or else be empty, hosts will contain the hosts that this entry matches,
 
92
// pubKey will contain the public key and comment will contain any trailing
 
93
// comment at the end of the line. See the sshd(8) manual page for the various
 
94
// forms that a host string can take.
 
95
//
 
96
// The unparsed remainder of the input will be returned in rest. This function
 
97
// can be called repeatedly to parse multiple entries.
 
98
//
 
99
// If no entries were found in the input then err will be io.EOF. Otherwise a
 
100
// non-nil err value indicates a parse error.
 
101
func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error) {
 
102
        for len(in) > 0 {
 
103
                end := bytes.IndexByte(in, '\n')
 
104
                if end != -1 {
 
105
                        rest = in[end+1:]
 
106
                        in = in[:end]
 
107
                } else {
 
108
                        rest = nil
 
109
                }
 
110
 
 
111
                end = bytes.IndexByte(in, '\r')
 
112
                if end != -1 {
 
113
                        in = in[:end]
 
114
                }
 
115
 
 
116
                in = bytes.TrimSpace(in)
 
117
                if len(in) == 0 || in[0] == '#' {
 
118
                        in = rest
 
119
                        continue
 
120
                }
 
121
 
 
122
                i := bytes.IndexAny(in, " \t")
 
123
                if i == -1 {
 
124
                        in = rest
 
125
                        continue
 
126
                }
 
127
 
 
128
                // Strip out the beginning of the known_host key.
 
129
                // This is either an optional marker or a (set of) hostname(s).
 
130
                keyFields := bytes.Fields(in)
 
131
                if len(keyFields) < 3 || len(keyFields) > 5 {
 
132
                        return "", nil, nil, "", nil, errors.New("ssh: invalid entry in known_hosts data")
 
133
                }
 
134
 
 
135
                // keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
 
136
                // list of hosts
 
137
                marker := ""
 
138
                if keyFields[0][0] == '@' {
 
139
                        marker = string(keyFields[0][1:])
 
140
                        keyFields = keyFields[1:]
 
141
                }
 
142
 
 
143
                hosts := string(keyFields[0])
 
144
                // keyFields[1] contains the key type (e.g. “ssh-rsa”).
 
145
                // However, that information is duplicated inside the
 
146
                // base64-encoded key and so is ignored here.
 
147
 
 
148
                key := bytes.Join(keyFields[2:], []byte(" "))
 
149
                if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
 
150
                        return "", nil, nil, "", nil, err
 
151
                }
 
152
 
 
153
                return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
 
154
        }
 
155
 
 
156
        return "", nil, nil, "", nil, io.EOF
 
157
}
 
158
 
80
159
// ParseAuthorizedKeys parses a public key from an authorized_keys
81
160
// file used in OpenSSH according to the sshd(8) manual page.
82
161
func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) {
245
324
 
246
325
func (r *rsaPublicKey) Marshal() []byte {
247
326
        e := new(big.Int).SetInt64(int64(r.E))
 
327
        // RSA publickey struct layout should match the struct used by
 
328
        // parseRSACert in the x/crypto/ssh/agent package.
248
329
        wirekey := struct {
249
330
                Name string
250
331
                E    *big.Int
267
348
        return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob)
268
349
}
269
350
 
270
 
type rsaPrivateKey struct {
271
 
        *rsa.PrivateKey
272
 
}
273
 
 
274
 
func (r *rsaPrivateKey) PublicKey() PublicKey {
275
 
        return (*rsaPublicKey)(&r.PrivateKey.PublicKey)
276
 
}
277
 
 
278
 
func (r *rsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
279
 
        h := crypto.SHA1.New()
280
 
        h.Write(data)
281
 
        digest := h.Sum(nil)
282
 
        blob, err := rsa.SignPKCS1v15(rand, r.PrivateKey, crypto.SHA1, digest)
283
 
        if err != nil {
284
 
                return nil, err
285
 
        }
286
 
        return &Signature{
287
 
                Format: r.PublicKey().Type(),
288
 
                Blob:   blob,
289
 
        }, nil
290
 
}
291
 
 
292
351
type dsaPublicKey dsa.PublicKey
293
352
 
294
353
func (r *dsaPublicKey) Type() string {
317
376
}
318
377
 
319
378
func (k *dsaPublicKey) Marshal() []byte {
 
379
        // DSA publickey struct layout should match the struct used by
 
380
        // parseDSACert in the x/crypto/ssh/agent package.
320
381
        w := struct {
321
382
                Name       string
322
383
                P, Q, G, Y *big.Int
403
464
        panic("ssh: unsupported ecdsa key size")
404
465
}
405
466
 
 
467
type ed25519PublicKey ed25519.PublicKey
 
468
 
 
469
func (key ed25519PublicKey) Type() string {
 
470
        return KeyAlgoED25519
 
471
}
 
472
 
 
473
func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
 
474
        var w struct {
 
475
                KeyBytes []byte
 
476
                Rest     []byte `ssh:"rest"`
 
477
        }
 
478
 
 
479
        if err := Unmarshal(in, &w); err != nil {
 
480
                return nil, nil, err
 
481
        }
 
482
 
 
483
        key := ed25519.PublicKey(w.KeyBytes)
 
484
 
 
485
        return (ed25519PublicKey)(key), w.Rest, nil
 
486
}
 
487
 
 
488
func (key ed25519PublicKey) Marshal() []byte {
 
489
        w := struct {
 
490
                Name     string
 
491
                KeyBytes []byte
 
492
        }{
 
493
                KeyAlgoED25519,
 
494
                []byte(key),
 
495
        }
 
496
        return Marshal(&w)
 
497
}
 
498
 
 
499
func (key ed25519PublicKey) Verify(b []byte, sig *Signature) error {
 
500
        if sig.Format != key.Type() {
 
501
                return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type())
 
502
        }
 
503
 
 
504
        edKey := (ed25519.PublicKey)(key)
 
505
        if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
 
506
                return errors.New("ssh: signature did not verify")
 
507
        }
 
508
 
 
509
        return nil
 
510
}
 
511
 
406
512
func supportedEllipticCurve(curve elliptic.Curve) bool {
407
513
        return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
408
514
}
455
561
func (key *ecdsaPublicKey) Marshal() []byte {
456
562
        // See RFC 5656, section 3.1.
457
563
        keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y)
 
564
        // ECDSA publickey struct layout should match the struct used by
 
565
        // parseECDSACert in the x/crypto/ssh/agent package.
458
566
        w := struct {
459
567
                Name string
460
568
                ID   string
496
604
        return errors.New("ssh: signature did not verify")
497
605
}
498
606
 
499
 
type ecdsaPrivateKey struct {
500
 
        *ecdsa.PrivateKey
501
 
}
502
 
 
503
 
func (k *ecdsaPrivateKey) PublicKey() PublicKey {
504
 
        return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey)
505
 
}
506
 
 
507
 
func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
508
 
        h := ecHash(k.PrivateKey.PublicKey.Curve).New()
509
 
        h.Write(data)
510
 
        digest := h.Sum(nil)
511
 
        r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest)
512
 
        if err != nil {
513
 
                return nil, err
514
 
        }
515
 
 
516
 
        sig := make([]byte, intLength(r)+intLength(s))
517
 
        rest := marshalInt(sig, r)
518
 
        marshalInt(rest, s)
519
 
        return &Signature{
520
 
                Format: k.PublicKey().Type(),
521
 
                Blob:   sig,
522
 
        }, nil
523
 
}
524
 
 
525
 
// NewSignerFromKey takes a pointer to rsa, dsa or ecdsa PrivateKey
526
 
// returns a corresponding Signer instance. EC keys should use P256,
527
 
// P384 or P521.
528
 
func NewSignerFromKey(k interface{}) (Signer, error) {
529
 
        var sshKey Signer
530
 
        switch t := k.(type) {
531
 
        case *rsa.PrivateKey:
532
 
                sshKey = &rsaPrivateKey{t}
 
607
// NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey,
 
608
// *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding
 
609
// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
 
610
func NewSignerFromKey(key interface{}) (Signer, error) {
 
611
        switch key := key.(type) {
 
612
        case crypto.Signer:
 
613
                return NewSignerFromSigner(key)
533
614
        case *dsa.PrivateKey:
534
 
                sshKey = &dsaPrivateKey{t}
535
 
        case *ecdsa.PrivateKey:
536
 
                if !supportedEllipticCurve(t.Curve) {
537
 
                        return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
538
 
                }
539
 
 
540
 
                sshKey = &ecdsaPrivateKey{t}
541
 
        default:
542
 
                return nil, fmt.Errorf("ssh: unsupported key type %T", k)
543
 
        }
544
 
        return sshKey, nil
545
 
}
546
 
 
547
 
// NewPublicKey takes a pointer to rsa, dsa or ecdsa PublicKey
548
 
// and returns a corresponding ssh PublicKey instance. EC keys should use P256, P384 or P521.
549
 
func NewPublicKey(k interface{}) (PublicKey, error) {
550
 
        var sshKey PublicKey
551
 
        switch t := k.(type) {
 
615
                return &dsaPrivateKey{key}, nil
 
616
        default:
 
617
                return nil, fmt.Errorf("ssh: unsupported key type %T", key)
 
618
        }
 
619
}
 
620
 
 
621
type wrappedSigner struct {
 
622
        signer crypto.Signer
 
623
        pubKey PublicKey
 
624
}
 
625
 
 
626
// NewSignerFromSigner takes any crypto.Signer implementation and
 
627
// returns a corresponding Signer interface. This can be used, for
 
628
// example, with keys kept in hardware modules.
 
629
func NewSignerFromSigner(signer crypto.Signer) (Signer, error) {
 
630
        pubKey, err := NewPublicKey(signer.Public())
 
631
        if err != nil {
 
632
                return nil, err
 
633
        }
 
634
 
 
635
        return &wrappedSigner{signer, pubKey}, nil
 
636
}
 
637
 
 
638
func (s *wrappedSigner) PublicKey() PublicKey {
 
639
        return s.pubKey
 
640
}
 
641
 
 
642
func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
 
643
        var hashFunc crypto.Hash
 
644
 
 
645
        switch key := s.pubKey.(type) {
 
646
        case *rsaPublicKey, *dsaPublicKey:
 
647
                hashFunc = crypto.SHA1
 
648
        case *ecdsaPublicKey:
 
649
                hashFunc = ecHash(key.Curve)
 
650
        case ed25519PublicKey:
 
651
        default:
 
652
                return nil, fmt.Errorf("ssh: unsupported key type %T", key)
 
653
        }
 
654
 
 
655
        var digest []byte
 
656
        if hashFunc != 0 {
 
657
                h := hashFunc.New()
 
658
                h.Write(data)
 
659
                digest = h.Sum(nil)
 
660
        } else {
 
661
                digest = data
 
662
        }
 
663
 
 
664
        signature, err := s.signer.Sign(rand, digest, hashFunc)
 
665
        if err != nil {
 
666
                return nil, err
 
667
        }
 
668
 
 
669
        // crypto.Signer.Sign is expected to return an ASN.1-encoded signature
 
670
        // for ECDSA and DSA, but that's not the encoding expected by SSH, so
 
671
        // re-encode.
 
672
        switch s.pubKey.(type) {
 
673
        case *ecdsaPublicKey, *dsaPublicKey:
 
674
                type asn1Signature struct {
 
675
                        R, S *big.Int
 
676
                }
 
677
                asn1Sig := new(asn1Signature)
 
678
                _, err := asn1.Unmarshal(signature, asn1Sig)
 
679
                if err != nil {
 
680
                        return nil, err
 
681
                }
 
682
 
 
683
                switch s.pubKey.(type) {
 
684
                case *ecdsaPublicKey:
 
685
                        signature = Marshal(asn1Sig)
 
686
 
 
687
                case *dsaPublicKey:
 
688
                        signature = make([]byte, 40)
 
689
                        r := asn1Sig.R.Bytes()
 
690
                        s := asn1Sig.S.Bytes()
 
691
                        copy(signature[20-len(r):20], r)
 
692
                        copy(signature[40-len(s):40], s)
 
693
                }
 
694
        }
 
695
 
 
696
        return &Signature{
 
697
                Format: s.pubKey.Type(),
 
698
                Blob:   signature,
 
699
        }, nil
 
700
}
 
701
 
 
702
// NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey,
 
703
// ed25519.PublicKey, or any other crypto.Signer and returns a corresponding
 
704
// Signer instance. ECDSA keys must use P-256, P-384 or P-521.
 
705
func NewPublicKey(key interface{}) (PublicKey, error) {
 
706
        switch key := key.(type) {
552
707
        case *rsa.PublicKey:
553
 
                sshKey = (*rsaPublicKey)(t)
 
708
                return (*rsaPublicKey)(key), nil
554
709
        case *ecdsa.PublicKey:
555
 
                if !supportedEllipticCurve(t.Curve) {
556
 
                        return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.")
 
710
                if !supportedEllipticCurve(key.Curve) {
 
711
                        return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.")
557
712
                }
558
 
                sshKey = (*ecdsaPublicKey)(t)
 
713
                return (*ecdsaPublicKey)(key), nil
559
714
        case *dsa.PublicKey:
560
 
                sshKey = (*dsaPublicKey)(t)
 
715
                return (*dsaPublicKey)(key), nil
 
716
        case ed25519.PublicKey:
 
717
                return (ed25519PublicKey)(key), nil
561
718
        default:
562
 
                return nil, fmt.Errorf("ssh: unsupported key type %T", k)
 
719
                return nil, fmt.Errorf("ssh: unsupported key type %T", key)
563
720
        }
564
 
        return sshKey, nil
565
721
}
566
722
 
567
723
// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
590
746
                return x509.ParseECPrivateKey(block.Bytes)
591
747
        case "DSA PRIVATE KEY":
592
748
                return ParseDSAPrivateKey(block.Bytes)
 
749
        case "OPENSSH PRIVATE KEY":
 
750
                return parseOpenSSHPrivateKey(block.Bytes)
593
751
        default:
594
752
                return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type)
595
753
        }
626
784
                X: k.Pub,
627
785
        }, nil
628
786
}
 
787
 
 
788
// Implemented based on the documentation at
 
789
// https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key
 
790
func parseOpenSSHPrivateKey(key []byte) (*ed25519.PrivateKey, error) {
 
791
        magic := append([]byte("openssh-key-v1"), 0)
 
792
        if !bytes.Equal(magic, key[0:len(magic)]) {
 
793
                return nil, errors.New("ssh: invalid openssh private key format")
 
794
        }
 
795
        remaining := key[len(magic):]
 
796
 
 
797
        var w struct {
 
798
                CipherName   string
 
799
                KdfName      string
 
800
                KdfOpts      string
 
801
                NumKeys      uint32
 
802
                PubKey       []byte
 
803
                PrivKeyBlock []byte
 
804
        }
 
805
 
 
806
        if err := Unmarshal(remaining, &w); err != nil {
 
807
                return nil, err
 
808
        }
 
809
 
 
810
        pk1 := struct {
 
811
                Check1  uint32
 
812
                Check2  uint32
 
813
                Keytype string
 
814
                Pub     []byte
 
815
                Priv    []byte
 
816
                Comment string
 
817
                Pad     []byte `ssh:"rest"`
 
818
        }{}
 
819
 
 
820
        if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
 
821
                return nil, err
 
822
        }
 
823
 
 
824
        if pk1.Check1 != pk1.Check2 {
 
825
                return nil, errors.New("ssh: checkint mismatch")
 
826
        }
 
827
 
 
828
        // we only handle ed25519 keys currently
 
829
        if pk1.Keytype != KeyAlgoED25519 {
 
830
                return nil, errors.New("ssh: unhandled key type")
 
831
        }
 
832
 
 
833
        for i, b := range pk1.Pad {
 
834
                if int(b) != i+1 {
 
835
                        return nil, errors.New("ssh: padding not as expected")
 
836
                }
 
837
        }
 
838
 
 
839
        if len(pk1.Priv) != ed25519.PrivateKeySize {
 
840
                return nil, errors.New("ssh: private key unexpected length")
 
841
        }
 
842
 
 
843
        pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))
 
844
        copy(pk, pk1.Priv)
 
845
        return &pk, nil
 
846
}