Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

906 linhas
22 KiB

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