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