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