github.com/inflatablewoman/deis@v1.0.1-0.20141111034523-a4511c46a6ce/deisctl/Godeps/_workspace/src/code.google.com/p/go.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 ) 23 24 // These constants represent the algorithm names for key types supported by this 25 // package. 26 const ( 27 KeyAlgoRSA = "ssh-rsa" 28 KeyAlgoDSA = "ssh-dss" 29 KeyAlgoECDSA256 = "ecdsa-sha2-nistp256" 30 KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" 31 KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" 32 ) 33 34 // parsePubKey parses a public key of the given algorithm. 35 // Use ParsePublicKey for keys with prepended algorithm. 36 func parsePubKey(in []byte, algo string) (pubKey PublicKey, rest []byte, err error) { 37 switch algo { 38 case KeyAlgoRSA: 39 return parseRSA(in) 40 case KeyAlgoDSA: 41 return parseDSA(in) 42 case KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521: 43 return parseECDSA(in) 44 case CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, 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 } 53 54 // 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 56 // removed. 57 func parseAuthorizedKey(in []byte) (out PublicKey, comment string, err error) { 58 in = bytes.TrimSpace(in) 59 60 i := bytes.IndexAny(in, " \t") 61 if i == -1 { 62 i = len(in) 63 } 64 base64Key := in[:i] 65 66 key := make([]byte, base64.StdEncoding.DecodedLen(len(base64Key))) 67 n, err := base64.StdEncoding.Decode(key, base64Key) 68 if err != nil { 69 return nil, "", err 70 } 71 key = key[:n] 72 out, err = ParsePublicKey(key) 73 if err != nil { 74 return nil, "", err 75 } 76 comment = string(bytes.TrimSpace(in[i:])) 77 return out, comment, nil 78 } 79 80 // ParseAuthorizedKeys parses a public key from an authorized_keys 81 // file used in OpenSSH according to the sshd(8) manual page. 82 func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error) { 83 for len(in) > 0 { 84 end := bytes.IndexByte(in, '\n') 85 if end != -1 { 86 rest = in[end+1:] 87 in = in[:end] 88 } else { 89 rest = nil 90 } 91 92 end = bytes.IndexByte(in, '\r') 93 if end != -1 { 94 in = in[:end] 95 } 96 97 in = bytes.TrimSpace(in) 98 if len(in) == 0 || in[0] == '#' { 99 in = rest 100 continue 101 } 102 103 i := bytes.IndexAny(in, " \t") 104 if i == -1 { 105 in = rest 106 continue 107 } 108 109 if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { 110 return out, comment, options, rest, nil 111 } 112 113 // No key type recognised. Maybe there's an options field at 114 // the beginning. 115 var b byte 116 inQuote := false 117 var candidateOptions []string 118 optionStart := 0 119 for i, b = range in { 120 isEnd := !inQuote && (b == ' ' || b == '\t') 121 if (b == ',' && !inQuote) || isEnd { 122 if i-optionStart > 0 { 123 candidateOptions = append(candidateOptions, string(in[optionStart:i])) 124 } 125 optionStart = i + 1 126 } 127 if isEnd { 128 break 129 } 130 if b == '"' && (i == 0 || (i > 0 && in[i-1] != '\\')) { 131 inQuote = !inQuote 132 } 133 } 134 for i < len(in) && (in[i] == ' ' || in[i] == '\t') { 135 i++ 136 } 137 if i == len(in) { 138 // Invalid line: unmatched quote 139 in = rest 140 continue 141 } 142 143 in = in[i:] 144 i = bytes.IndexAny(in, " \t") 145 if i == -1 { 146 in = rest 147 continue 148 } 149 150 if out, comment, err = parseAuthorizedKey(in[i:]); err == nil { 151 options = candidateOptions 152 return out, comment, options, rest, nil 153 } 154 155 in = rest 156 continue 157 } 158 159 return nil, "", nil, nil, errors.New("ssh: no key found") 160 } 161 162 // ParsePublicKey parses an SSH public key formatted for use in 163 // the SSH wire protocol according to RFC 4253, section 6.6. 164 func ParsePublicKey(in []byte) (out PublicKey, err error) { 165 algo, in, ok := parseString(in) 166 if !ok { 167 return nil, errShortRead 168 } 169 var rest []byte 170 out, rest, err = parsePubKey(in, string(algo)) 171 if len(rest) > 0 { 172 return nil, errors.New("ssh: trailing junk in public key") 173 } 174 175 return out, err 176 } 177 178 // MarshalAuthorizedKey serializes key for inclusion in an OpenSSH 179 // authorized_keys file. The return value ends with newline. 180 func MarshalAuthorizedKey(key PublicKey) []byte { 181 b := &bytes.Buffer{} 182 b.WriteString(key.Type()) 183 b.WriteByte(' ') 184 e := base64.NewEncoder(base64.StdEncoding, b) 185 e.Write(key.Marshal()) 186 e.Close() 187 b.WriteByte('\n') 188 return b.Bytes() 189 } 190 191 // PublicKey is an abstraction of different types of public keys. 192 type PublicKey interface { 193 // Type returns the key's type, e.g. "ssh-rsa". 194 Type() string 195 196 // Marshal returns the serialized key data in SSH wire format, 197 // with the name prefix. 198 Marshal() []byte 199 200 // Verify that sig is a signature on the given data using this 201 // key. This function will hash the data appropriately first. 202 Verify(data []byte, sig *Signature) error 203 } 204 205 // A Signer can create signatures that verify against a public key. 206 type Signer interface { 207 // PublicKey returns an associated PublicKey instance. 208 PublicKey() PublicKey 209 210 // Sign returns raw signature for the given data. This method 211 // will apply the hash specified for the keytype to the data. 212 Sign(rand io.Reader, data []byte) (*Signature, error) 213 } 214 215 type rsaPublicKey rsa.PublicKey 216 217 func (r *rsaPublicKey) Type() string { 218 return "ssh-rsa" 219 } 220 221 // parseRSA parses an RSA key according to RFC 4253, section 6.6. 222 func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { 223 var w struct { 224 E *big.Int 225 N *big.Int 226 Rest []byte `ssh:"rest"` 227 } 228 if err := Unmarshal(in, &w); err != nil { 229 return nil, nil, err 230 } 231 232 if w.E.BitLen() > 24 { 233 return nil, nil, errors.New("ssh: exponent too large") 234 } 235 e := w.E.Int64() 236 if e < 3 || e&1 == 0 { 237 return nil, nil, errors.New("ssh: incorrect exponent") 238 } 239 240 var key rsa.PublicKey 241 key.E = int(e) 242 key.N = w.N 243 return (*rsaPublicKey)(&key), w.Rest, nil 244 } 245 246 func (r *rsaPublicKey) Marshal() []byte { 247 e := new(big.Int).SetInt64(int64(r.E)) 248 wirekey := struct { 249 Name string 250 E *big.Int 251 N *big.Int 252 }{ 253 KeyAlgoRSA, 254 e, 255 r.N, 256 } 257 return Marshal(&wirekey) 258 } 259 260 func (r *rsaPublicKey) Verify(data []byte, sig *Signature) error { 261 if sig.Format != r.Type() { 262 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, r.Type()) 263 } 264 h := crypto.SHA1.New() 265 h.Write(data) 266 digest := h.Sum(nil) 267 return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig.Blob) 268 } 269 270 type rsaPrivateKey struct { 271 *rsa.PrivateKey 272 } 273 274 func (r *rsaPrivateKey) PublicKey() PublicKey { 275 return (*rsaPublicKey)(&r.PrivateKey.PublicKey) 276 } 277 278 func (r *rsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { 279 h := crypto.SHA1.New() 280 h.Write(data) 281 digest := h.Sum(nil) 282 blob, err := rsa.SignPKCS1v15(rand, r.PrivateKey, crypto.SHA1, digest) 283 if err != nil { 284 return nil, err 285 } 286 return &Signature{ 287 Format: r.PublicKey().Type(), 288 Blob: blob, 289 }, nil 290 } 291 292 type dsaPublicKey dsa.PublicKey 293 294 func (r *dsaPublicKey) Type() string { 295 return "ssh-dss" 296 } 297 298 // parseDSA parses an DSA key according to RFC 4253, section 6.6. 299 func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { 300 var w struct { 301 P, Q, G, Y *big.Int 302 Rest []byte `ssh:"rest"` 303 } 304 if err := Unmarshal(in, &w); err != nil { 305 return nil, nil, err 306 } 307 308 key := &dsaPublicKey{ 309 Parameters: dsa.Parameters{ 310 P: w.P, 311 Q: w.Q, 312 G: w.G, 313 }, 314 Y: w.Y, 315 } 316 return key, w.Rest, nil 317 } 318 319 func (k *dsaPublicKey) Marshal() []byte { 320 w := struct { 321 Name string 322 P, Q, G, Y *big.Int 323 }{ 324 k.Type(), 325 k.P, 326 k.Q, 327 k.G, 328 k.Y, 329 } 330 331 return Marshal(&w) 332 } 333 334 func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { 335 if sig.Format != k.Type() { 336 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) 337 } 338 h := crypto.SHA1.New() 339 h.Write(data) 340 digest := h.Sum(nil) 341 342 // Per RFC 4253, section 6.6, 343 // The value for 'dss_signature_blob' is encoded as a string containing 344 // r, followed by s (which are 160-bit integers, without lengths or 345 // padding, unsigned, and in network byte order). 346 // For DSS purposes, sig.Blob should be exactly 40 bytes in length. 347 if len(sig.Blob) != 40 { 348 return errors.New("ssh: DSA signature parse error") 349 } 350 r := new(big.Int).SetBytes(sig.Blob[:20]) 351 s := new(big.Int).SetBytes(sig.Blob[20:]) 352 if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { 353 return nil 354 } 355 return errors.New("ssh: signature did not verify") 356 } 357 358 type dsaPrivateKey struct { 359 *dsa.PrivateKey 360 } 361 362 func (k *dsaPrivateKey) PublicKey() PublicKey { 363 return (*dsaPublicKey)(&k.PrivateKey.PublicKey) 364 } 365 366 func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { 367 h := crypto.SHA1.New() 368 h.Write(data) 369 digest := h.Sum(nil) 370 r, s, err := dsa.Sign(rand, k.PrivateKey, digest) 371 if err != nil { 372 return nil, err 373 } 374 375 sig := make([]byte, 40) 376 rb := r.Bytes() 377 sb := s.Bytes() 378 379 copy(sig[20-len(rb):20], rb) 380 copy(sig[40-len(sb):], sb) 381 382 return &Signature{ 383 Format: k.PublicKey().Type(), 384 Blob: sig, 385 }, nil 386 } 387 388 type ecdsaPublicKey ecdsa.PublicKey 389 390 func (key *ecdsaPublicKey) Type() string { 391 return "ecdsa-sha2-" + key.nistID() 392 } 393 394 func (key *ecdsaPublicKey) nistID() string { 395 switch key.Params().BitSize { 396 case 256: 397 return "nistp256" 398 case 384: 399 return "nistp384" 400 case 521: 401 return "nistp521" 402 } 403 panic("ssh: unsupported ecdsa key size") 404 } 405 406 func supportedEllipticCurve(curve elliptic.Curve) bool { 407 return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() 408 } 409 410 // ecHash returns the hash to match the given elliptic curve, see RFC 411 // 5656, section 6.2.1 412 func ecHash(curve elliptic.Curve) crypto.Hash { 413 bitSize := curve.Params().BitSize 414 switch { 415 case bitSize <= 256: 416 return crypto.SHA256 417 case bitSize <= 384: 418 return crypto.SHA384 419 } 420 return crypto.SHA512 421 } 422 423 // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. 424 func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { 425 identifier, in, ok := parseString(in) 426 if !ok { 427 return nil, nil, errShortRead 428 } 429 430 key := new(ecdsa.PublicKey) 431 432 switch string(identifier) { 433 case "nistp256": 434 key.Curve = elliptic.P256() 435 case "nistp384": 436 key.Curve = elliptic.P384() 437 case "nistp521": 438 key.Curve = elliptic.P521() 439 default: 440 return nil, nil, errors.New("ssh: unsupported curve") 441 } 442 443 var keyBytes []byte 444 if keyBytes, in, ok = parseString(in); !ok { 445 return nil, nil, errShortRead 446 } 447 448 key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes) 449 if key.X == nil || key.Y == nil { 450 return nil, nil, errors.New("ssh: invalid curve point") 451 } 452 return (*ecdsaPublicKey)(key), in, nil 453 } 454 455 func (key *ecdsaPublicKey) Marshal() []byte { 456 // See RFC 5656, section 3.1. 457 keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) 458 w := struct { 459 Name string 460 ID string 461 Key []byte 462 }{ 463 key.Type(), 464 key.nistID(), 465 keyBytes, 466 } 467 468 return Marshal(&w) 469 } 470 471 func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { 472 if sig.Format != key.Type() { 473 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type()) 474 } 475 476 h := ecHash(key.Curve).New() 477 h.Write(data) 478 digest := h.Sum(nil) 479 480 // Per RFC 5656, section 3.1.2, 481 // The ecdsa_signature_blob value has the following specific encoding: 482 // mpint r 483 // mpint s 484 var ecSig struct { 485 R *big.Int 486 S *big.Int 487 } 488 489 if err := Unmarshal(sig.Blob, &ecSig); err != nil { 490 return err 491 } 492 493 if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) { 494 return nil 495 } 496 return errors.New("ssh: signature did not verify") 497 } 498 499 type ecdsaPrivateKey struct { 500 *ecdsa.PrivateKey 501 } 502 503 func (k *ecdsaPrivateKey) PublicKey() PublicKey { 504 return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey) 505 } 506 507 func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { 508 h := ecHash(k.PrivateKey.PublicKey.Curve).New() 509 h.Write(data) 510 digest := h.Sum(nil) 511 r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest) 512 if err != nil { 513 return nil, err 514 } 515 516 sig := make([]byte, intLength(r)+intLength(s)) 517 rest := marshalInt(sig, r) 518 marshalInt(rest, s) 519 return &Signature{ 520 Format: k.PublicKey().Type(), 521 Blob: sig, 522 }, nil 523 } 524 525 // NewSignerFromKey takes a pointer to rsa, dsa or ecdsa PrivateKey 526 // returns a corresponding Signer instance. EC keys should use P256, 527 // P384 or P521. 528 func NewSignerFromKey(k interface{}) (Signer, error) { 529 var sshKey Signer 530 switch t := k.(type) { 531 case *rsa.PrivateKey: 532 sshKey = &rsaPrivateKey{t} 533 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.") 538 } 539 540 sshKey = &ecdsaPrivateKey{t} 541 default: 542 return nil, fmt.Errorf("ssh: unsupported key type %T", k) 543 } 544 return sshKey, nil 545 } 546 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) { 550 var sshKey PublicKey 551 switch t := k.(type) { 552 case *rsa.PublicKey: 553 sshKey = (*rsaPublicKey)(t) 554 case *ecdsa.PublicKey: 555 if !supportedEllipticCurve(t.Curve) { 556 return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.") 557 } 558 sshKey = (*ecdsaPublicKey)(t) 559 case *dsa.PublicKey: 560 sshKey = (*dsaPublicKey)(t) 561 default: 562 return nil, fmt.Errorf("ssh: unsupported key type %T", k) 563 } 564 return sshKey, nil 565 } 566 567 // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports 568 // the same keys as ParseRawPrivateKey. 569 func ParsePrivateKey(pemBytes []byte) (Signer, error) { 570 key, err := ParseRawPrivateKey(pemBytes) 571 if err != nil { 572 return nil, err 573 } 574 575 return NewSignerFromKey(key) 576 } 577 578 // ParseRawPrivateKey returns a private key from a PEM encoded private key. It 579 // supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. 580 func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { 581 block, _ := pem.Decode(pemBytes) 582 if block == nil { 583 return nil, errors.New("ssh: no key found") 584 } 585 586 switch block.Type { 587 case "RSA PRIVATE KEY": 588 return x509.ParsePKCS1PrivateKey(block.Bytes) 589 case "EC PRIVATE KEY": 590 return x509.ParseECPrivateKey(block.Bytes) 591 case "DSA PRIVATE KEY": 592 return ParseDSAPrivateKey(block.Bytes) 593 default: 594 return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) 595 } 596 } 597 598 // ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as 599 // specified by the OpenSSL DSA man page. 600 func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { 601 var k struct { 602 Version int 603 P *big.Int 604 Q *big.Int 605 G *big.Int 606 Priv *big.Int 607 Pub *big.Int 608 } 609 rest, err := asn1.Unmarshal(der, &k) 610 if err != nil { 611 return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) 612 } 613 if len(rest) > 0 { 614 return nil, errors.New("ssh: garbage after DSA key") 615 } 616 617 return &dsa.PrivateKey{ 618 PublicKey: dsa.PublicKey{ 619 Parameters: dsa.Parameters{ 620 P: k.P, 621 Q: k.Q, 622 G: k.G, 623 }, 624 Y: k.Priv, 625 }, 626 X: k.Pub, 627 }, nil 628 }