77
83
return out, comment, nil
86
// ParseKnownHosts parses an entry in the format of the known_hosts file.
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.
96
// The unparsed remainder of the input will be returned in rest. This function
97
// can be called repeatedly to parse multiple entries.
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) {
103
end := bytes.IndexByte(in, '\n')
111
end = bytes.IndexByte(in, '\r')
116
in = bytes.TrimSpace(in)
117
if len(in) == 0 || in[0] == '#' {
122
i := bytes.IndexAny(in, " \t")
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")
135
// keyFields[0] is either "@cert-authority", "@revoked" or a comma separated
138
if keyFields[0][0] == '@' {
139
marker = string(keyFields[0][1:])
140
keyFields = keyFields[1:]
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.
148
key := bytes.Join(keyFields[2:], []byte(" "))
149
if pubKey, comment, err = parseAuthorizedKey(key); err != nil {
150
return "", nil, nil, "", nil, err
153
return marker, strings.Split(hosts, ","), pubKey, comment, rest, nil
156
return "", nil, nil, "", nil, io.EOF
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) {
403
464
panic("ssh: unsupported ecdsa key size")
467
type ed25519PublicKey ed25519.PublicKey
469
func (key ed25519PublicKey) Type() string {
470
return KeyAlgoED25519
473
func parseED25519(in []byte) (out PublicKey, rest []byte, err error) {
476
Rest []byte `ssh:"rest"`
479
if err := Unmarshal(in, &w); err != nil {
483
key := ed25519.PublicKey(w.KeyBytes)
485
return (ed25519PublicKey)(key), w.Rest, nil
488
func (key ed25519PublicKey) Marshal() []byte {
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())
504
edKey := (ed25519.PublicKey)(key)
505
if ok := ed25519.Verify(edKey, b, sig.Blob); !ok {
506
return errors.New("ssh: signature did not verify")
406
512
func supportedEllipticCurve(curve elliptic.Curve) bool {
407
513
return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521()
496
604
return errors.New("ssh: signature did not verify")
499
type ecdsaPrivateKey struct {
503
func (k *ecdsaPrivateKey) PublicKey() PublicKey {
504
return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey)
507
func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) {
508
h := ecHash(k.PrivateKey.PublicKey.Curve).New()
511
r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest)
516
sig := make([]byte, intLength(r)+intLength(s))
517
rest := marshalInt(sig, r)
520
Format: k.PublicKey().Type(),
525
// NewSignerFromKey takes a pointer to rsa, dsa or ecdsa PrivateKey
526
// returns a corresponding Signer instance. EC keys should use P256,
528
func NewSignerFromKey(k interface{}) (Signer, error) {
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) {
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.")
540
sshKey = &ecdsaPrivateKey{t}
542
return nil, fmt.Errorf("ssh: unsupported key type %T", k)
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) {
551
switch t := k.(type) {
615
return &dsaPrivateKey{key}, nil
617
return nil, fmt.Errorf("ssh: unsupported key type %T", key)
621
type wrappedSigner struct {
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())
635
return &wrappedSigner{signer, pubKey}, nil
638
func (s *wrappedSigner) PublicKey() PublicKey {
642
func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) {
643
var hashFunc crypto.Hash
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:
652
return nil, fmt.Errorf("ssh: unsupported key type %T", key)
664
signature, err := s.signer.Sign(rand, digest, hashFunc)
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
672
switch s.pubKey.(type) {
673
case *ecdsaPublicKey, *dsaPublicKey:
674
type asn1Signature struct {
677
asn1Sig := new(asn1Signature)
678
_, err := asn1.Unmarshal(signature, asn1Sig)
683
switch s.pubKey.(type) {
684
case *ecdsaPublicKey:
685
signature = Marshal(asn1Sig)
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)
697
Format: s.pubKey.Type(),
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.")
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
562
return nil, fmt.Errorf("ssh: unsupported key type %T", k)
719
return nil, fmt.Errorf("ssh: unsupported key type %T", key)
567
723
// ParsePrivateKey returns a Signer from a PEM encoded private key. It supports
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")
795
remaining := key[len(magic):]
806
if err := Unmarshal(remaining, &w); err != nil {
817
Pad []byte `ssh:"rest"`
820
if err := Unmarshal(w.PrivKeyBlock, &pk1); err != nil {
824
if pk1.Check1 != pk1.Check2 {
825
return nil, errors.New("ssh: checkint mismatch")
828
// we only handle ed25519 keys currently
829
if pk1.Keytype != KeyAlgoED25519 {
830
return nil, errors.New("ssh: unhandled key type")
833
for i, b := range pk1.Pad {
835
return nil, errors.New("ssh: padding not as expected")
839
if len(pk1.Priv) != ed25519.PrivateKeySize {
840
return nil, errors.New("ssh: private key unexpected length")
843
pk := ed25519.PrivateKey(make([]byte, ed25519.PrivateKeySize))