Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ssh | 5 package ssh |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "crypto" | 9 "crypto" |
10 "crypto/dsa" | 10 "crypto/dsa" |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
207 PublicKeyAlgo() string | 207 PublicKeyAlgo() string |
208 | 208 |
209 // Marshal returns the serialized key data in SSH wire format, | 209 // Marshal returns the serialized key data in SSH wire format, |
210 // without the name prefix. Callers should typically use | 210 // without the name prefix. Callers should typically use |
211 // MarshalPublicKey(). | 211 // MarshalPublicKey(). |
212 Marshal() []byte | 212 Marshal() []byte |
213 | 213 |
214 // Verify that sig is a signature on the given data using this | 214 // Verify that sig is a signature on the given data using this |
215 // key. This function will hash the data appropriately first. | 215 // key. This function will hash the data appropriately first. |
216 Verify(data []byte, sigBlob []byte) bool | 216 Verify(data []byte, sigBlob []byte) bool |
217 | 217 } |
218 » // RawKey returns the underlying object, eg. *rsa.PublicKey. | 218 |
219 » RawKey() interface{} | 219 // A Signer is can create signatures that verify against a public key. |
220 } | 220 type Signer interface { |
221 | |
222 // PrivateKey is an abstraction of different types of private keys. | |
223 type PrivateKey interface { | |
224 // PublicKey returns an associated PublicKey instance. | 221 // PublicKey returns an associated PublicKey instance. |
225 PublicKey() PublicKey | 222 PublicKey() PublicKey |
226 | 223 |
227 » // RawKey returns the underlying object, eg. *rsa.PrivateKey. | 224 » // Sign returns raw signature for the given data. This method |
228 » RawKey() interface{} | 225 » // will apply the hash specified for the keytype to the data. |
229 | |
230 » // Sign returns raw signature data for the given data. | |
231 Sign(rand io.Reader, data []byte) ([]byte, error) | 226 Sign(rand io.Reader, data []byte) ([]byte, error) |
jmp
2013/09/18 04:07:51
I like the new interface.
I have had this thought
| |
232 } | 227 } |
228 | |
229 type rsaPublicKey rsa.PublicKey | |
233 | 230 |
234 func (r *rsaPublicKey) PrivateKeyAlgo() string { | 231 func (r *rsaPublicKey) PrivateKeyAlgo() string { |
235 return "ssh-rsa" | 232 return "ssh-rsa" |
236 } | 233 } |
237 | 234 |
238 func (r *rsaPublicKey) PublicKeyAlgo() string { | 235 func (r *rsaPublicKey) PublicKeyAlgo() string { |
239 » return "ssh-rsa" | 236 » return r.PrivateKeyAlgo() |
240 } | |
241 | |
242 func (r *rsaPublicKey) RawKey() interface{} { | |
243 » return (*rsa.PublicKey)(r) | |
244 } | 237 } |
245 | 238 |
246 // parseRSA parses an RSA key according to RFC 4253, section 6.6. | 239 // parseRSA parses an RSA key according to RFC 4253, section 6.6. |
247 func parseRSA(in []byte) (out PublicKey, rest []byte, ok bool) { | 240 func parseRSA(in []byte) (out PublicKey, rest []byte, ok bool) { |
248 key := new(rsa.PublicKey) | 241 key := new(rsa.PublicKey) |
249 | 242 |
250 bigE, in, ok := parseInt(in) | 243 bigE, in, ok := parseInt(in) |
251 if !ok || bigE.BitLen() > 24 { | 244 if !ok || bigE.BitLen() > 24 { |
252 return | 245 return |
253 } | 246 } |
254 e := bigE.Int64() | 247 e := bigE.Int64() |
255 if e < 3 || e&1 == 0 { | 248 if e < 3 || e&1 == 0 { |
256 ok = false | 249 ok = false |
257 return | 250 return |
258 } | 251 } |
259 key.E = int(e) | 252 key.E = int(e) |
260 | 253 |
261 if key.N, in, ok = parseInt(in); !ok { | 254 if key.N, in, ok = parseInt(in); !ok { |
262 return | 255 return |
263 } | 256 } |
264 | 257 |
265 ok = true | 258 ok = true |
266 » return NewRSAPublicKey(key), in, ok | 259 » return (*rsaPublicKey)(key), in, ok |
267 } | 260 } |
268 | 261 |
269 func (r *rsaPublicKey) Marshal() []byte { | 262 func (r *rsaPublicKey) Marshal() []byte { |
270 // See RFC 4253, section 6.6. | 263 // See RFC 4253, section 6.6. |
271 e := new(big.Int).SetInt64(int64(r.E)) | 264 e := new(big.Int).SetInt64(int64(r.E)) |
272 length := intLength(e) | 265 length := intLength(e) |
273 length += intLength(r.N) | 266 length += intLength(r.N) |
274 | 267 |
275 ret := make([]byte, length) | 268 ret := make([]byte, length) |
276 rest := marshalInt(ret, e) | 269 rest := marshalInt(ret, e) |
277 marshalInt(rest, r.N) | 270 marshalInt(rest, r.N) |
278 | 271 |
279 return ret | 272 return ret |
280 } | 273 } |
281 | 274 |
282 func (r *rsaPublicKey) Verify(data []byte, sig []byte) bool { | 275 func (r *rsaPublicKey) Verify(data []byte, sig []byte) bool { |
283 h := crypto.SHA1.New() | 276 h := crypto.SHA1.New() |
284 h.Write(data) | 277 h.Write(data) |
285 digest := h.Sum(nil) | 278 digest := h.Sum(nil) |
286 return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig) == nil | 279 return rsa.VerifyPKCS1v15((*rsa.PublicKey)(r), crypto.SHA1, digest, sig) == nil |
287 } | 280 } |
288 | 281 |
289 func NewRSAPublicKey(k *rsa.PublicKey) PublicKey { | |
290 return (*rsaPublicKey)(k) | |
291 } | |
292 | |
293 type rsaPublicKey rsa.PublicKey | |
294 | |
295 type rsaPrivateKey struct { | 282 type rsaPrivateKey struct { |
296 *rsa.PrivateKey | 283 *rsa.PrivateKey |
297 } | 284 } |
298 | 285 |
299 func (r *rsaPrivateKey) PublicKey() PublicKey { | 286 func (r *rsaPrivateKey) PublicKey() PublicKey { |
300 return (*rsaPublicKey)(&r.PrivateKey.PublicKey) | 287 return (*rsaPublicKey)(&r.PrivateKey.PublicKey) |
301 } | |
302 | |
303 func (r *rsaPrivateKey) RawKey() interface{} { | |
304 return r.PrivateKey | |
305 } | 288 } |
306 | 289 |
307 func (r *rsaPrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error) { | 290 func (r *rsaPrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error) { |
308 h := crypto.SHA1.New() | 291 h := crypto.SHA1.New() |
309 h.Write(data) | 292 h.Write(data) |
310 digest := h.Sum(nil) | 293 digest := h.Sum(nil) |
311 return rsa.SignPKCS1v15(rand, r.PrivateKey, crypto.SHA1, digest) | 294 return rsa.SignPKCS1v15(rand, r.PrivateKey, crypto.SHA1, digest) |
312 } | 295 } |
313 | 296 |
314 type dsaPublicKey dsa.PublicKey | 297 type dsaPublicKey dsa.PublicKey |
315 | 298 |
316 func (r *dsaPublicKey) PrivateKeyAlgo() string { | 299 func (r *dsaPublicKey) PrivateKeyAlgo() string { |
317 return "ssh-dss" | 300 return "ssh-dss" |
318 } | 301 } |
302 | |
319 func (r *dsaPublicKey) PublicKeyAlgo() string { | 303 func (r *dsaPublicKey) PublicKeyAlgo() string { |
320 » return "ssh-dss" | 304 » return r.PrivateKeyAlgo() |
321 } | |
322 func (r *dsaPublicKey) RawKey() interface{} { | |
323 » return (*dsa.PublicKey)(r) | |
324 } | 305 } |
325 | 306 |
326 // parseDSA parses an DSA key according to RFC 4253, section 6.6. | 307 // parseDSA parses an DSA key according to RFC 4253, section 6.6. |
327 func parseDSA(in []byte) (out PublicKey, rest []byte, ok bool) { | 308 func parseDSA(in []byte) (out PublicKey, rest []byte, ok bool) { |
328 key := new(dsa.PublicKey) | 309 key := new(dsa.PublicKey) |
329 | 310 |
330 if key.P, in, ok = parseInt(in); !ok { | 311 if key.P, in, ok = parseInt(in); !ok { |
331 return | 312 return |
332 } | 313 } |
333 | 314 |
334 if key.Q, in, ok = parseInt(in); !ok { | 315 if key.Q, in, ok = parseInt(in); !ok { |
335 return | 316 return |
336 } | 317 } |
337 | 318 |
338 if key.G, in, ok = parseInt(in); !ok { | 319 if key.G, in, ok = parseInt(in); !ok { |
339 return | 320 return |
340 } | 321 } |
341 | 322 |
342 if key.Y, in, ok = parseInt(in); !ok { | 323 if key.Y, in, ok = parseInt(in); !ok { |
343 return | 324 return |
344 } | 325 } |
345 | 326 |
346 ok = true | 327 ok = true |
347 » return NewDSAPublicKey(key), in, ok | 328 » return (*dsaPublicKey)(key), in, ok |
348 } | 329 } |
349 | 330 |
350 func (r *dsaPublicKey) Marshal() []byte { | 331 func (r *dsaPublicKey) Marshal() []byte { |
351 // See RFC 4253, section 6.6. | 332 // See RFC 4253, section 6.6. |
352 length := intLength(r.P) | 333 length := intLength(r.P) |
353 length += intLength(r.Q) | 334 length += intLength(r.Q) |
354 length += intLength(r.G) | 335 length += intLength(r.G) |
355 length += intLength(r.Y) | 336 length += intLength(r.Y) |
356 | 337 |
357 ret := make([]byte, length) | 338 ret := make([]byte, length) |
(...skipping 16 matching lines...) Expand all Loading... | |
374 // padding, unsigned, and in network byte order). | 355 // padding, unsigned, and in network byte order). |
375 // For DSS purposes, sig.Blob should be exactly 40 bytes in length. | 356 // For DSS purposes, sig.Blob should be exactly 40 bytes in length. |
376 if len(sigBlob) != 40 { | 357 if len(sigBlob) != 40 { |
377 return false | 358 return false |
378 } | 359 } |
379 r := new(big.Int).SetBytes(sigBlob[:20]) | 360 r := new(big.Int).SetBytes(sigBlob[:20]) |
380 s := new(big.Int).SetBytes(sigBlob[20:]) | 361 s := new(big.Int).SetBytes(sigBlob[20:]) |
381 return dsa.Verify((*dsa.PublicKey)(k), digest, r, s) | 362 return dsa.Verify((*dsa.PublicKey)(k), digest, r, s) |
382 } | 363 } |
383 | 364 |
384 func NewDSAPublicKey(k *dsa.PublicKey) PublicKey { | |
385 return (*dsaPublicKey)(k) | |
386 } | |
387 | |
388 type dsaPrivateKey struct { | 365 type dsaPrivateKey struct { |
389 *dsa.PrivateKey | 366 *dsa.PrivateKey |
390 } | 367 } |
391 | 368 |
392 func (k *dsaPrivateKey) PublicKey() PublicKey { | 369 func (k *dsaPrivateKey) PublicKey() PublicKey { |
393 return (*dsaPublicKey)(&k.PrivateKey.PublicKey) | 370 return (*dsaPublicKey)(&k.PrivateKey.PublicKey) |
394 } | |
395 | |
396 func (k *dsaPrivateKey) RawKey() interface{} { | |
397 return k.PrivateKey | |
398 } | 371 } |
399 | 372 |
400 func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error) { | 373 func (k *dsaPrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error) { |
401 h := crypto.SHA1.New() | 374 h := crypto.SHA1.New() |
402 h.Write(data) | 375 h.Write(data) |
403 digest := h.Sum(nil) | 376 digest := h.Sum(nil) |
404 r, s, err := dsa.Sign(rand, k.PrivateKey, digest) | 377 r, s, err := dsa.Sign(rand, k.PrivateKey, digest) |
405 if err != nil { | 378 if err != nil { |
406 return nil, err | 379 return nil, err |
407 } | 380 } |
408 | 381 |
409 sig := make([]byte, 40) | 382 sig := make([]byte, 40) |
410 copy(sig[:20], r.Bytes()) | 383 copy(sig[:20], r.Bytes()) |
411 copy(sig[20:], s.Bytes()) | 384 copy(sig[20:], s.Bytes()) |
412 return sig, nil | 385 return sig, nil |
413 } | 386 } |
414 | 387 |
415 type ecdsaPublicKey ecdsa.PublicKey | 388 type ecdsaPublicKey ecdsa.PublicKey |
416 | |
417 func NewECDSAPublicKey(k *ecdsa.PublicKey) PublicKey { | |
418 return (*ecdsaPublicKey)(k) | |
419 } | |
420 func (r *ecdsaPublicKey) RawKey() interface{} { | |
421 return (*ecdsa.PublicKey)(r) | |
422 } | |
423 | 389 |
424 func (key *ecdsaPublicKey) PrivateKeyAlgo() string { | 390 func (key *ecdsaPublicKey) PrivateKeyAlgo() string { |
425 return "ecdsa-sha2-" + key.nistID() | 391 return "ecdsa-sha2-" + key.nistID() |
426 } | 392 } |
427 | 393 |
428 func (key *ecdsaPublicKey) nistID() string { | 394 func (key *ecdsaPublicKey) nistID() string { |
429 switch key.Params().BitSize { | 395 switch key.Params().BitSize { |
430 case 256: | 396 case 256: |
431 return "nistp256" | 397 return "nistp256" |
432 case 384: | 398 case 384: |
433 return "nistp384" | 399 return "nistp384" |
434 case 521: | 400 case 521: |
435 return "nistp521" | 401 return "nistp521" |
436 } | 402 } |
437 panic("ssh: unsupported ecdsa key size") | 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()) | |
438 } | 408 } |
439 | 409 |
440 // ecHash returns the hash to match the given elliptic curve, see RFC | 410 // ecHash returns the hash to match the given elliptic curve, see RFC |
441 // 5656, section 6.2.1 | 411 // 5656, section 6.2.1 |
442 func ecHash(curve elliptic.Curve) crypto.Hash { | 412 func ecHash(curve elliptic.Curve) crypto.Hash { |
443 bitSize := curve.Params().BitSize | 413 bitSize := curve.Params().BitSize |
444 switch { | 414 switch { |
445 case bitSize <= 256: | 415 case bitSize <= 256: |
446 return crypto.SHA256 | 416 return crypto.SHA256 |
447 case bitSize <= 384: | 417 case bitSize <= 384: |
448 return crypto.SHA384 | 418 return crypto.SHA384 |
449 } | 419 } |
450 return crypto.SHA512 | 420 return crypto.SHA512 |
451 } | 421 } |
452 | 422 |
453 func (key *ecdsaPublicKey) PublicKeyAlgo() string { | 423 func (key *ecdsaPublicKey) PublicKeyAlgo() string { |
454 » switch key.Params().BitSize { | 424 » return key.PrivateKeyAlgo() |
455 » case 256: | |
456 » » return KeyAlgoECDSA256 | |
457 » case 384: | |
458 » » return KeyAlgoECDSA384 | |
459 » case 521: | |
460 » » return KeyAlgoECDSA521 | |
461 » } | |
462 » panic("ssh: unsupported ecdsa key size") | |
463 } | 425 } |
464 | 426 |
465 // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. | 427 // parseECDSA parses an ECDSA key according to RFC 5656, section 3.1. |
466 func parseECDSA(in []byte) (out PublicKey, rest []byte, ok bool) { | 428 func parseECDSA(in []byte) (out PublicKey, rest []byte, ok bool) { |
467 var identifier []byte | 429 var identifier []byte |
468 if identifier, in, ok = parseString(in); !ok { | 430 if identifier, in, ok = parseString(in); !ok { |
469 return | 431 return |
470 } | 432 } |
471 | 433 |
472 key := new(ecdsa.PublicKey) | 434 key := new(ecdsa.PublicKey) |
(...skipping 13 matching lines...) Expand all Loading... | |
486 var keyBytes []byte | 448 var keyBytes []byte |
487 if keyBytes, in, ok = parseString(in); !ok { | 449 if keyBytes, in, ok = parseString(in); !ok { |
488 return | 450 return |
489 } | 451 } |
490 | 452 |
491 key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes) | 453 key.X, key.Y = elliptic.Unmarshal(key.Curve, keyBytes) |
492 if key.X == nil || key.Y == nil { | 454 if key.X == nil || key.Y == nil { |
493 ok = false | 455 ok = false |
494 return | 456 return |
495 } | 457 } |
496 » return NewECDSAPublicKey(key), in, ok | 458 » return (*ecdsaPublicKey)(key), in, ok |
497 } | 459 } |
498 | 460 |
499 func (key *ecdsaPublicKey) Marshal() []byte { | 461 func (key *ecdsaPublicKey) Marshal() []byte { |
500 // See RFC 5656, section 3.1. | 462 // See RFC 5656, section 3.1. |
501 keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) | 463 keyBytes := elliptic.Marshal(key.Curve, key.X, key.Y) |
502 | 464 |
503 ID := key.nistID() | 465 ID := key.nistID() |
504 length := stringLength(len(ID)) | 466 length := stringLength(len(ID)) |
505 length += stringLength(len(keyBytes)) | 467 length += stringLength(len(keyBytes)) |
506 | 468 |
(...skipping 24 matching lines...) Expand all Loading... | |
531 } | 493 } |
532 | 494 |
533 type ecdsaPrivateKey struct { | 495 type ecdsaPrivateKey struct { |
534 *ecdsa.PrivateKey | 496 *ecdsa.PrivateKey |
535 } | 497 } |
536 | 498 |
537 func (k *ecdsaPrivateKey) PublicKey() PublicKey { | 499 func (k *ecdsaPrivateKey) PublicKey() PublicKey { |
538 return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey) | 500 return (*ecdsaPublicKey)(&k.PrivateKey.PublicKey) |
539 } | 501 } |
540 | 502 |
541 func (k *ecdsaPrivateKey) RawKey() interface{} { | |
542 return k.PrivateKey | |
543 } | |
544 | |
545 func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error) { | 503 func (k *ecdsaPrivateKey) Sign(rand io.Reader, data []byte) ([]byte, error) { |
546 h := ecHash(k.PrivateKey.PublicKey.Curve).New() | 504 h := ecHash(k.PrivateKey.PublicKey.Curve).New() |
547 h.Write(data) | 505 h.Write(data) |
548 digest := h.Sum(nil) | 506 digest := h.Sum(nil) |
549 r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest) | 507 r, s, err := ecdsa.Sign(rand, k.PrivateKey, digest) |
550 if err != nil { | 508 if err != nil { |
551 return nil, err | 509 return nil, err |
552 } | 510 } |
553 | 511 |
554 sig := make([]byte, intLength(r)+intLength(s)) | 512 sig := make([]byte, intLength(r)+intLength(s)) |
555 rest := marshalInt(sig, r) | 513 rest := marshalInt(sig, r) |
556 marshalInt(rest, s) | 514 marshalInt(rest, s) |
557 return sig, nil | 515 return sig, nil |
558 } | 516 } |
559 | 517 |
560 // NewPrivateKey takes a pointer to rsa, dsa or ecdsa PrivateKey | 518 // NewPrivateKey takes a pointer to rsa, dsa or ecdsa PrivateKey |
561 // returns a corresponding ssh PrivateKey instance. | 519 // returns a corresponding Signer instance. EC keys should use P256, |
562 func NewPrivateKey(k interface{}) (PrivateKey, error) { | 520 // P384 or P521. |
521 func NewSignerFromKey(k interface{}) (Signer, error) { | |
522 » var sshKey Signer | |
563 switch t := k.(type) { | 523 switch t := k.(type) { |
564 case *rsa.PrivateKey: | 524 case *rsa.PrivateKey: |
565 » » return &rsaPrivateKey{t}, nil | 525 » » sshKey = &rsaPrivateKey{t} |
566 case *dsa.PrivateKey: | 526 case *dsa.PrivateKey: |
567 » » return &dsaPrivateKey{t}, nil | 527 » » sshKey = &dsaPrivateKey{t} |
568 case *ecdsa.PrivateKey: | 528 case *ecdsa.PrivateKey: |
569 » » return &ecdsaPrivateKey{t}, nil | 529 » » if !supportedEllipticCurve(t.Curve) { |
570 » } | 530 » » » return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.") |
571 » return nil, fmt.Errorf("unsupport key type %T", k) | 531 » » } |
532 | |
533 » » sshKey = &ecdsaPrivateKey{t} | |
534 » default: | |
535 » » return nil, fmt.Errorf("ssh: unsupported key type %T", k) | |
536 » } | |
537 » return sshKey, nil | |
538 } | |
539 | |
540 // NewPublicKey takes a pointer to rsa, dsa or ecdsa PublicKey | |
541 // and returns a corresponding ssh PublicKey instance. EC keys should use P256, P384 or P521. | |
542 func NewPublicKey(k interface{}) (PublicKey, error) { | |
543 » var sshKey PublicKey | |
544 » switch t := k.(type) { | |
545 » case *rsa.PublicKey: | |
546 » » sshKey = (*rsaPublicKey)(t) | |
547 » case *ecdsa.PublicKey: | |
548 » » if !supportedEllipticCurve(t.Curve) { | |
549 » » » return nil, errors.New("ssh: only P256, P384 and P521 EC keys are supported.") | |
550 » » } | |
551 » » sshKey = (*ecdsaPublicKey)(t) | |
552 » case *dsa.PublicKey: | |
553 » » sshKey = (*dsaPublicKey)(t) | |
554 » default: | |
555 » » return nil, fmt.Errorf("ssh: unsupported key type %T", k) | |
556 » } | |
557 » return sshKey, nil | |
572 } | 558 } |
573 | 559 |
574 // ParsePublicKey parses a PEM encoded private key. Currently, only | 560 // ParsePublicKey parses a PEM encoded private key. Currently, only |
575 // PKCS#1, RSA private keys are supported. | 561 // PKCS#1, RSA and ECDSA private keys are supported. |
576 func ParsePrivateKey(pemBytes []byte) (PrivateKey, error) { | 562 func ParsePrivateKey(pemBytes []byte) (Signer, error) { |
577 block, _ := pem.Decode(pemBytes) | 563 block, _ := pem.Decode(pemBytes) |
578 if block == nil { | 564 if block == nil { |
579 return nil, errors.New("ssh: no key found") | 565 return nil, errors.New("ssh: no key found") |
580 } | 566 } |
581 | 567 |
582 var rawkey interface{} | 568 var rawkey interface{} |
583 switch block.Type { | 569 switch block.Type { |
584 case "RSA PRIVATE KEY": | 570 case "RSA PRIVATE KEY": |
585 rsa, err := x509.ParsePKCS1PrivateKey(block.Bytes) | 571 rsa, err := x509.ParsePKCS1PrivateKey(block.Bytes) |
586 if err != nil { | 572 if err != nil { |
587 return nil, err | 573 return nil, err |
588 } | 574 } |
589 rawkey = rsa | 575 rawkey = rsa |
590 » // TODO(hanwen): find doc for format and implement PEM parsing | 576 » case "EC PRIVATE KEY": |
jmp
2013/09/18 04:07:51
For ECDSA, this will already do what you want http
| |
591 » // for (EC)DSA keys. | 577 » » ec, err := x509.ParseECPrivateKey(block.Bytes) |
578 » » if err != nil { | |
579 » » » return nil, err | |
580 » » } | |
581 » » rawkey = ec | |
582 | |
583 » » // TODO(hanwen): find doc for format and implement PEM parsing | |
584 » » // for DSA keys. | |
592 default: | 585 default: |
593 » » return nil, fmt.Errorf("ssh: ParsePrivateKey does not support ke y type %q", | 586 » » return nil, fmt.Errorf("ssh: unsupported key type %q", block.Typ e) |
594 » » » block.Type) | 587 » } |
595 » } | 588 |
596 | 589 » return NewSignerFromKey(rawkey) |
597 » return NewPrivateKey(rawkey) | 590 } |
598 } | |
LEFT | RIGHT |