| LEFT | RIGHT |
| (no file at all) |
| 1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
| 3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 package ssh | 5 package ssh |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "crypto" | 9 "crypto" |
| 10 "crypto/dsa" | 10 "crypto/dsa" |
| 11 "crypto/ecdsa" | 11 "crypto/ecdsa" |
| 12 "crypto/elliptic" | 12 "crypto/elliptic" |
| 13 "crypto/rsa" | 13 "crypto/rsa" |
| 14 "crypto/x509" | 14 "crypto/x509" |
| 15 "encoding/asn1" | 15 "encoding/asn1" |
| 16 "encoding/base64" | 16 "encoding/base64" |
| 17 "encoding/pem" | 17 "encoding/pem" |
| 18 "errors" | 18 "errors" |
| 19 "fmt" | 19 "fmt" |
| 20 "io" | 20 "io" |
| 21 "math/big" | 21 "math/big" |
| 22 "sync" |
| 22 ) | 23 ) |
| 23 | 24 |
| 24 // These constants represent the algorithm names for key types supported by this | 25 // These constants represent the algorithm names for key types supported by this |
| 25 // package. | 26 // package. |
| 26 const ( | 27 const ( |
| 27 KeyAlgoRSA = "ssh-rsa" | 28 KeyAlgoRSA = "ssh-rsa" |
| 28 KeyAlgoDSA = "ssh-dss" | 29 KeyAlgoDSA = "ssh-dss" |
| 29 KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" | 30 KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" |
| 30 KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" | 31 KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" |
| 31 KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" | 32 KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" |
| 32 ) | 33 ) |
| 33 | 34 |
| 35 func init() { |
| 36 registerPubKeyType(KeyAlgoRSA, parseRSA) |
| 37 registerPubKeyType(KeyAlgoDSA, parseDSA) |
| 38 registerPubKeyType(KeyAlgoECDSA256, parseECDSA) |
| 39 registerPubKeyType(KeyAlgoECDSA384, parseECDSA) |
| 40 registerPubKeyType(KeyAlgoECDSA521, parseECDSA) |
| 41 registerPubKeyType(CertAlgoRSAv01, parseCert) |
| 42 registerPubKeyType(CertAlgoDSAv01, parseCert) |
| 43 registerPubKeyType(CertAlgoECDSA256v01, parseCert) |
| 44 registerPubKeyType(CertAlgoECDSA384v01, parseCert) |
| 45 registerPubKeyType(CertAlgoECDSA521v01, parseCert) |
| 46 } |
| 47 |
| 34 // parsePubKey parses a public key of the given algorithm. | 48 // parsePubKey parses a public key of the given algorithm. |
| 35 // Use ParsePublicKey for keys with prepended algorithm. | 49 // Use ParsePublicKey for keys with prepended algorithm. |
| 36 func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
or) { | 50 func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err err
or) { |
| 37 » switch algo { | 51 » regKeyMu.RLock() |
| 38 » case KeyAlgoRSA: | 52 » parser := supportedKeys[algo] |
| 39 » » return parseRSA(in) | 53 » regKeyMu.RUnlock() |
| 40 » case KeyAlgoDSA: | 54 » if parser == nil { |
| 41 » » return parseDSA(in) | 55 » » return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %q", al
go) |
| 42 » case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: | 56 » } |
| 43 » » return parseECDSA(in) | 57 » return parser(algo, in) |
| 44 » case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA3
84v01, CertAlgoECDSA521v01: |
| 45 » » cert, err := parseCert(in, certToPrivAlgo(algo)) |
| 46 » » if err != nil { |
| 47 » » » return nil, nil, err |
| 48 » » } |
| 49 » » return cert, nil, nil |
| 50 » } |
| 51 » return nil, nil, fmt.Errorf("ssh: unknown key algorithm: %v", err) |
| 52 } | 58 } |
| 53 | 59 |
| 54 // parseAuthorizedKey parses a public key in OpenSSH authorized_keys format | 60 // parseAuthorizedKey parses a public key in OpenSSH authorized_keys format |
| 55 // (see sshd(8) manual page) once the options and key type fields have been | 61 // (see sshd(8) manual page) once the options and key type fields have been |
| 56 // removed. | 62 // removed. |
| 57 func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { | 63 func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { |
| 58 in = bytes.TrimSpace(in) | 64 in = bytes.TrimSpace(in) |
| 59 | 65 |
| 60 i := bytes.IndexAny(in, " \t") | 66 i := bytes.IndexAny(in, " \t") |
| 61 if i == -1 { | 67 if i == -1 { |
| (...skipping 150 matching lines...) | | Loading... |
| 212 Sign(rand io.Reader, data []byte) (*Signature, error) | 218 Sign(rand io.Reader, data []byte) (*Signature, error) |
| 213 } | 219 } |
| 214 | 220 |
| 215 type rsaPublicKey rsa.PublicKey | 221 type rsaPublicKey rsa.PublicKey |
| 216 | 222 |
| 217 func (r *rsaPublicKey) Type() string { | 223 func (r *rsaPublicKey) Type() string { |
| 218 return "ssh-rsa" | 224 return "ssh-rsa" |
| 219 } | 225 } |
| 220 | 226 |
| 221 // parseRSA parses an RSA key according to RFC 4253, section 6.6. | 227 // parseRSA parses an RSA key according to RFC 4253, section 6.6. |
| 222 func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { | 228 func parseRSA(algo string, in []byte) (out PublicKey, rest []byte, err error) { |
| 223 var w struct { | 229 var w struct { |
| 224 E *big.Int | 230 E *big.Int |
| 225 N *big.Int | 231 N *big.Int |
| 226 Rest []byte `ssh:"rest"` | 232 Rest []byte `ssh:"rest"` |
| 227 } | 233 } |
| 228 if err := Unmarshal(in, &w); err != nil { | 234 if err := Unmarshal(in, &w); err != nil { |
| 229 return nil, nil, err | 235 return nil, nil, err |
| 230 } | 236 } |
| 231 | 237 |
| 232 if w.E.BitLen() > 24 { | 238 if w.E.BitLen() > 24 { |
| (...skipping 56 matching lines...) | | Loading... |
| 289 }, nil | 295 }, nil |
| 290 } | 296 } |
| 291 | 297 |
| 292 type dsaPublicKey dsa.PublicKey | 298 type dsaPublicKey dsa.PublicKey |
| 293 | 299 |
| 294 func (r *dsaPublicKey) Type() string { | 300 func (r *dsaPublicKey) Type() string { |
| 295 return "ssh-dss" | 301 return "ssh-dss" |
| 296 } | 302 } |
| 297 | 303 |
| 298 // parseDSA parses an DSA key according to RFC 4253, section 6.6. | 304 // parseDSA parses an DSA key according to RFC 4253, section 6.6. |
| 299 func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { | 305 func parseDSA(algo string, in []byte) (out PublicKey, rest []byte, err error) { |
| 300 var w struct { | 306 var w struct { |
| 301 P, Q, G, Y *big.Int | 307 P, Q, G, Y *big.Int |
| 302 Rest []byte `ssh:"rest"` | 308 Rest []byte `ssh:"rest"` |
| 303 } | 309 } |
| 304 if err := Unmarshal(in, &w); err != nil { | 310 if err := Unmarshal(in, &w); err != nil { |
| 305 return nil, nil, err | 311 return nil, nil, err |
| 306 } | 312 } |
| 307 | 313 |
| 308 key := &dsaPublicKey{ | 314 key := &dsaPublicKey{ |
| 309 Parameters: dsa.Parameters{ | 315 Parameters: dsa.Parameters{ |
| (...skipping 104 matching lines...) | | Loading... |
| 414 switch { | 420 switch { |
| 415 case bitSize <= 256: | 421 case bitSize <= 256: |
| 416 return crypto.SHA256 | 422 return crypto.SHA256 |
| 417 case bitSize <= 384: | 423 case bitSize <= 384: |
| 418 return crypto.SHA384 | 424 return crypto.SHA384 |
| 419 } | 425 } |
| 420 return crypto.SHA512 | 426 return crypto.SHA512 |
| 421 } | 427 } |
| 422 | 428 |
| 423 // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. | 429 // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. |
| 424 func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { | 430 func parseECDSA(algo string, in []byte) (out PublicKey, rest []byte, err error)
{ |
| 425 identifier, in, ok := parseString(in) | 431 identifier, in, ok := parseString(in) |
| 426 if !ok { | 432 if !ok { |
| 427 return nil, nil, errShortRead | 433 return nil, nil, errShortRead |
| 428 } | 434 } |
| 429 | 435 |
| 430 key := new(ecdsa.PublicKey) | 436 key := new(ecdsa.PublicKey) |
| 431 | 437 |
| 432 switch string(identifier) { | 438 switch string(identifier) { |
| 433 case "nistp256": | 439 case "nistp256": |
| 434 key.Curve = elliptic.P256() | 440 key.Curve = elliptic.P256() |
| (...skipping 184 matching lines...) | | Loading... |
| 619 Parameters: dsa.Parameters{ | 625 Parameters: dsa.Parameters{ |
| 620 P: k.P, | 626 P: k.P, |
| 621 Q: k.Q, | 627 Q: k.Q, |
| 622 G: k.G, | 628 G: k.G, |
| 623 }, | 629 }, |
| 624 Y: k.Priv, | 630 Y: k.Priv, |
| 625 }, | 631 }, |
| 626 X: k.Pub, | 632 X: k.Pub, |
| 627 }, nil | 633 }, nil |
| 628 } | 634 } |
| 635 |
| 636 // TODO(jmpittman): This is a step toward improving pluggability into the ssh |
| 637 // package. Later on, remember to export what is necessary when that |
| 638 // pluggability becomes reality and we can move a lot of functionality for |
| 639 // specific kinds of keys to outside of this package. |
| 640 var regKeyMu sync.RWMutex |
| 641 |
| 642 var supportedKeys = map[string]pubKeyParser{} |
| 643 |
| 644 type pubKeyParser func(algo string, in []byte) (pubKey PublicKey, rest []byte, e
rr error) |
| 645 |
| 646 func registerPubKeyType(algo string, parser pubKeyParser) { |
| 647 regKeyMu.Lock() |
| 648 supportedKeys[algo] = parser |
| 649 regKeyMu.Unlock() |
| 650 } |
| LEFT | RIGHT |