github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/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 ) 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 dsaPublicKey dsa.PublicKey 271 272 func (r *dsaPublicKey) Type() string { 273 return "ssh-dss" 274 } 275 276 // parseDSA parses an DSA key according to RFC 4253, section 6.6. 277 func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { 278 var w struct { 279 P, Q, G, Y *big.Int 280 Rest []byte `ssh:"rest"` 281 } 282 if err := Unmarshal(in, &w); err != nil { 283 return nil, nil, err 284 } 285 286 key := &dsaPublicKey{ 287 Parameters: dsa.Parameters{ 288 P: w.P, 289 Q: w.Q, 290 G: w.G, 291 }, 292 Y: w.Y, 293 } 294 return key, w.Rest, nil 295 } 296 297 func (k *dsaPublicKey) Marshal() []byte { 298 w := struct { 299 Name string 300 P, Q, G, Y *big.Int 301 }{ 302 k.Type(), 303 k.P, 304 k.Q, 305 k.G, 306 k.Y, 307 } 308 309 return Marshal(&w) 310 } 311 312 func (k *dsaPublicKey) Verify(data []byte, sig *Signature) error { 313 if sig.Format != k.Type() { 314 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, k.Type()) 315 } 316 h := crypto.SHA1.New() 317 h.Write(data) 318 digest := h.Sum(nil) 319 320 // Per RFC 4253, section 6.6, 321 // The value for 'dss_signature_blob' is encoded as a string containing 322 // r, followed by s (which are 160-bit integers, without lengths or 323 // padding, unsigned, and in network byte order). 324 // For DSS purposes, sig.Blob should be exactly 40 bytes in length. 325 if len(sig.Blob) != 40 { 326 return errors.New("ssh: DSA signature parse error") 327 } 328 r := new(big.Int).SetBytes(sig.Blob[:20]) 329 s := new(big.Int).SetBytes(sig.Blob[20:]) 330 if dsa.Verify((*dsa.PublicKey)(k), digest, r, s) { 331 return nil 332 } 333 return errors.New("ssh: signature did not verify") 334 } 335 336 type dsaPrivateKey struct { 337 *dsa.PrivateKey 338 } 339 340 func (k *dsaPrivateKey) PublicKey() PublicKey { 341 return (*dsaPublicKey)(&k.PrivateKey.PublicKey) 342 } 343 344 func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) (*Signature, error) { 345 h := crypto.SHA1.New() 346 h.Write(data) 347 digest := h.Sum(nil) 348 r, s, err := dsa.Sign(rand, k.PrivateKey, digest) 349 if err != nil { 350 return nil, err 351 } 352 353 sig := make([]byte, 40) 354 rb := r.Bytes() 355 sb := s.Bytes() 356 357 copy(sig[20-len(rb):20], rb) 358 copy(sig[40-len(sb):], sb) 359 360 return &Signature{ 361 Format: k.PublicKey().Type(), 362 Blob: sig, 363 }, nil 364 } 365 366 type ecdsaPublicKey ecdsa.PublicKey 367 368 func (key *ecdsaPublicKey) Type() string { 369 return "ecdsa-sha2-" + key.nistID() 370 } 371 372 func (key *ecdsaPublicKey) nistID() string { 373 switch key.Params().BitSize { 374 case 256: 375 return "nistp256" 376 case 384: 377 return "nistp384" 378 case 521: 379 return "nistp521" 380 } 381 panic("ssh: unsupported ecdsa key size") 382 } 383 384 func supportedEllipticCurve(curve elliptic.Curve) bool { 385 return curve == elliptic.P256() || curve == elliptic.P384() || curve == elliptic.P521() 386 } 387 388 // ecHash returns the hash to match the given elliptic curve, see RFC 389 // 5656, section 6.2.1 390 func ecHash(curve elliptic.Curve) crypto.Hash { 391 bitSize := curve.Params().BitSize 392 switch { 393 case bitSize <= 256: 394 return crypto.SHA256 395 case bitSize <= 384: 396 return crypto.SHA384 397 } 398 return crypto.SHA512 399 } 400 401 // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. 402 func parseECDSA(in []byte) (out PublicKey, rest []byte, err error) { 403 var w struct { 404 Curve string 405 KeyBytes []byte 406 Rest []byte `ssh:"rest"` 407 } 408 409 if err := Unmarshal(in, &w); err != nil { 410 return nil, nil, err 411 } 412 413 key := new(ecdsa.PublicKey) 414 415 switch w.Curve { 416 case "nistp256": 417 key.Curve = elliptic.P256() 418 case "nistp384": 419 key.Curve = elliptic.P384() 420 case "nistp521": 421 key.Curve = elliptic.P521() 422 default: 423 return nil, nil, errors.New("ssh: unsupported curve") 424 } 425 426 key.X, key.Y = elliptic.Unmarshal(key.Curve, w.KeyBytes) 427 if key.X == nil || key.Y == nil { 428 return nil, nil, errors.New("ssh: invalid curve point") 429 } 430 return (*ecdsaPublicKey)(key), w.Rest, nil 431 } 432 433 func (key *ecdsaPublicKey) Marshal() []byte { 434 // See RFC 5656, section 3.1. 435 keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) 436 w := struct { 437 Name string 438 ID string 439 Key []byte 440 }{ 441 key.Type(), 442 key.nistID(), 443 keyBytes, 444 } 445 446 return Marshal(&w) 447 } 448 449 func (key *ecdsaPublicKey) Verify(data []byte, sig *Signature) error { 450 if sig.Format != key.Type() { 451 return fmt.Errorf("ssh: signature type %s for key type %s", sig.Format, key.Type()) 452 } 453 454 h := ecHash(key.Curve).New() 455 h.Write(data) 456 digest := h.Sum(nil) 457 458 // Per RFC 5656, section 3.1.2, 459 // The ecdsa_signature_blob value has the following specific encoding: 460 // mpint r 461 // mpint s 462 var ecSig struct { 463 R *big.Int 464 S *big.Int 465 } 466 467 if err := Unmarshal(sig.Blob, &ecSig); err != nil { 468 return err 469 } 470 471 if ecdsa.Verify((*ecdsa.PublicKey)(key), digest, ecSig.R, ecSig.S) { 472 return nil 473 } 474 return errors.New("ssh: signature did not verify") 475 } 476 477 // NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, 478 // *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding 479 // Signer instance. ECDSA keys must use P-256, P-384 or P-521. 480 func NewSignerFromKey(key interface{}) (Signer, error) { 481 switch key := key.(type) { 482 case crypto.Signer: 483 return NewSignerFromSigner(key) 484 case *dsa.PrivateKey: 485 return &dsaPrivateKey{key}, nil 486 default: 487 return nil, fmt.Errorf("ssh: unsupported key type %T", key) 488 } 489 } 490 491 type wrappedSigner struct { 492 signer crypto.Signer 493 pubKey PublicKey 494 } 495 496 // NewSignerFromSigner takes any crypto.Signer implementation and 497 // returns a corresponding Signer interface. This can be used, for 498 // example, with keys kept in hardware modules. 499 func NewSignerFromSigner(signer crypto.Signer) (Signer, error) { 500 pubKey, err := NewPublicKey(signer.Public()) 501 if err != nil { 502 return nil, err 503 } 504 505 return &wrappedSigner{signer, pubKey}, nil 506 } 507 508 func (s *wrappedSigner) PublicKey() PublicKey { 509 return s.pubKey 510 } 511 512 func (s *wrappedSigner) Sign(rand io.Reader, data []byte) (*Signature, error) { 513 var hashFunc crypto.Hash 514 515 switch key := s.pubKey.(type) { 516 case *rsaPublicKey, *dsaPublicKey: 517 hashFunc = crypto.SHA1 518 case *ecdsaPublicKey: 519 hashFunc = ecHash(key.Curve) 520 default: 521 return nil, fmt.Errorf("ssh: unsupported key type %T", key) 522 } 523 524 h := hashFunc.New() 525 h.Write(data) 526 digest := h.Sum(nil) 527 528 signature, err := s.signer.Sign(rand, digest, hashFunc) 529 if err != nil { 530 return nil, err 531 } 532 533 // crypto.Signer.Sign is expected to return an ASN.1-encoded signature 534 // for ECDSA and DSA, but that's not the encoding expected by SSH, so 535 // re-encode. 536 switch s.pubKey.(type) { 537 case *ecdsaPublicKey, *dsaPublicKey: 538 type asn1Signature struct { 539 R, S *big.Int 540 } 541 asn1Sig := new(asn1Signature) 542 _, err := asn1.Unmarshal(signature, asn1Sig) 543 if err != nil { 544 return nil, err 545 } 546 547 switch s.pubKey.(type) { 548 case *ecdsaPublicKey: 549 signature = Marshal(asn1Sig) 550 551 case *dsaPublicKey: 552 signature = make([]byte, 40) 553 r := asn1Sig.R.Bytes() 554 s := asn1Sig.S.Bytes() 555 copy(signature[20-len(r):20], r) 556 copy(signature[40-len(s):40], s) 557 } 558 } 559 560 return &Signature{ 561 Format: s.pubKey.Type(), 562 Blob: signature, 563 }, nil 564 } 565 566 // NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or 567 // any other crypto.Signer and returns a corresponding Signer instance. ECDSA 568 // keys must use P-256, P-384 or P-521. 569 func NewPublicKey(key interface{}) (PublicKey, error) { 570 switch key := key.(type) { 571 case *rsa.PublicKey: 572 return (*rsaPublicKey)(key), nil 573 case *ecdsa.PublicKey: 574 if !supportedEllipticCurve(key.Curve) { 575 return nil, errors.New("ssh: only P-256, P-384 and P-521 EC keys are supported.") 576 } 577 return (*ecdsaPublicKey)(key), nil 578 case *dsa.PublicKey: 579 return (*dsaPublicKey)(key), nil 580 default: 581 return nil, fmt.Errorf("ssh: unsupported key type %T", key) 582 } 583 } 584 585 // ParsePrivateKey returns a Signer from a PEM encoded private key. It supports 586 // the same keys as ParseRawPrivateKey. 587 func ParsePrivateKey(pemBytes []byte) (Signer, error) { 588 key, err := ParseRawPrivateKey(pemBytes) 589 if err != nil { 590 return nil, err 591 } 592 593 return NewSignerFromKey(key) 594 } 595 596 // ParseRawPrivateKey returns a private key from a PEM encoded private key. It 597 // supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys. 598 func ParseRawPrivateKey(pemBytes []byte) (interface{}, error) { 599 block, _ := pem.Decode(pemBytes) 600 if block == nil { 601 return nil, errors.New("ssh: no key found") 602 } 603 604 switch block.Type { 605 case "RSA PRIVATE KEY": 606 return x509.ParsePKCS1PrivateKey(block.Bytes) 607 case "EC PRIVATE KEY": 608 return x509.ParseECPrivateKey(block.Bytes) 609 case "DSA PRIVATE KEY": 610 return ParseDSAPrivateKey(block.Bytes) 611 default: 612 return nil, fmt.Errorf("ssh: unsupported key type %q", block.Type) 613 } 614 } 615 616 // ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as 617 // specified by the OpenSSL DSA man page. 618 func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error) { 619 var k struct { 620 Version int 621 P *big.Int 622 Q *big.Int 623 G *big.Int 624 Priv *big.Int 625 Pub *big.Int 626 } 627 rest, err := asn1.Unmarshal(der, &k) 628 if err != nil { 629 return nil, errors.New("ssh: failed to parse DSA key: " + err.Error()) 630 } 631 if len(rest) > 0 { 632 return nil, errors.New("ssh: garbage after DSA key") 633 } 634 635 return &dsa.PrivateKey{ 636 PublicKey: dsa.PublicKey{ 637 Parameters: dsa.Parameters{ 638 P: k.P, 639 Q: k.Q, 640 G: k.G, 641 }, 642 Y: k.Priv, 643 }, 644 X: k.Pub, 645 }, nil 646 }