1// Copyright 2015 Keybase, Inc. All rights reserved. Use of 2// this source code is governed by the included BSD license. 3 4package libkb 5 6import ( 7 "bufio" 8 "bytes" 9 "crypto/sha256" 10 "encoding/hex" 11 "errors" 12 "fmt" 13 "io" 14 "regexp" 15 "strings" 16 17 "github.com/keybase/client/go/kbcrypto" 18 keybase1 "github.com/keybase/client/go/protocol/keybase1" 19 "github.com/keybase/go-crypto/openpgp" 20 "github.com/keybase/go-crypto/openpgp/armor" 21 "github.com/keybase/go-crypto/openpgp/packet" 22 jsonw "github.com/keybase/go-jsonw" 23 _ "golang.org/x/crypto/ripemd160" // imported so that keybase/go-crypto/openpgp supports ripemd160 24) 25 26var _ GenericKey = (*PGPKeyBundle)(nil) 27 28type PGPKeyBundle struct { 29 *openpgp.Entity 30 31 // GPGFallbackKey to be used as a fallback if given dummy a PrivateKey. 32 GPGFallbackKey GenericKey 33 34 // We make the (fairly dangerous) assumption that the key will never be 35 // modified. This avoids the issue that encoding an openpgp.Entity is 36 // nondeterministic due to Go's randomized iteration order (so different 37 // exports of the same key may hash differently). 38 // 39 // If you're *sure* that you're creating a PGPKeyBundle from an armored 40 // *public* key, you can prefill this field and Export() will use it. 41 ArmoredPublicKey string 42 43 // True if this key was generated by this program 44 Generated bool 45} 46 47func NewPGPKeyBundle(entity *openpgp.Entity) *PGPKeyBundle { 48 return &PGPKeyBundle{Entity: entity} 49} 50 51func NewGeneratedPGPKeyBundle(entity *openpgp.Entity) *PGPKeyBundle { 52 return &PGPKeyBundle{Entity: entity, Generated: true} 53} 54 55const ( 56 PGPFingerprintLen = 20 57) 58 59type PGPFingerprint [PGPFingerprintLen]byte 60 61func ImportPGPFingerprint(f keybase1.PGPFingerprint) PGPFingerprint { 62 var ret PGPFingerprint 63 copy(ret[:], f[:]) 64 return ret 65} 66 67func PGPFingerprintFromHex(s string) (*PGPFingerprint, error) { 68 var fp PGPFingerprint 69 err := DecodeHexFixed(fp[:], []byte(s)) 70 switch err.(type) { 71 case nil: 72 return &fp, nil 73 case HexWrongLengthError: 74 return nil, fmt.Errorf("Bad fingerprint; wrong length: %d", len(s)) 75 default: 76 return nil, err 77 } 78} 79 80func PGPFingerprintFromSlice(b []byte) (*PGPFingerprint, error) { 81 if len(b) != PGPFingerprintLen { 82 return nil, fmt.Errorf("Bad fingerprint; wrong length: %d", PGPFingerprintLen) 83 } 84 var fp PGPFingerprint 85 copy(fp[:], b) 86 return &fp, nil 87} 88 89func PGPFingerprintFromHexNoError(s string) *PGPFingerprint { 90 if len(s) == 0 { 91 return nil 92 } else if f, e := PGPFingerprintFromHex(s); e == nil { 93 return f 94 } else { 95 return nil 96 } 97} 98 99func (p PGPFingerprint) String() string { 100 return hex.EncodeToString(p[:]) 101} 102 103func (p PGPFingerprint) ToQuads() string { 104 x := []byte(strings.ToUpper(p.String())) 105 totlen := len(x)*5/4 - 1 106 ret := make([]byte, totlen) 107 j := 0 108 for i, b := range x { 109 ret[j] = b 110 j++ 111 if (i%4) == 3 && j < totlen { 112 ret[j] = ' ' 113 j++ 114 } 115 } 116 return string(ret) 117} 118 119func (p PGPFingerprint) ToKeyID() string { 120 return strings.ToUpper(hex.EncodeToString(p[12:20])) 121} 122 123func (p PGPFingerprint) ToDisplayString(verbose bool) string { 124 if verbose { 125 return p.String() 126 } 127 return p.ToKeyID() 128} 129 130func (p *PGPFingerprint) Match(q string, exact bool) bool { 131 if p == nil { 132 return false 133 } 134 if exact { 135 return strings.EqualFold(p.String(), q) 136 } 137 return strings.HasSuffix(strings.ToLower(p.String()), strings.ToLower(q)) 138} 139 140func (k *PGPKeyBundle) InitGPGKey() { 141 k.GPGFallbackKey = &GPGKey{ 142 fp: k.GetFingerprintP(), 143 kid: k.GetKID(), 144 } 145} 146 147func (k *PGPKeyBundle) FullHash() (string, error) { 148 keyBlob, err := k.Encode() 149 if err != nil { 150 return "", err 151 } 152 153 keySum := sha256.Sum256([]byte(strings.TrimSpace(keyBlob))) 154 return hex.EncodeToString(keySum[:]), nil 155} 156 157// StripRevocations returns a copy of the key with revocations removed 158func (k *PGPKeyBundle) StripRevocations() (strippedKey *PGPKeyBundle) { 159 strippedKey = nil 160 if k.ArmoredPublicKey != "" { 161 // Re-read the key because we want to return a copy, that does 162 // not reference PGPKeyBundle `k` anywhere. 163 strippedKey, _, _ = ReadOneKeyFromString(k.ArmoredPublicKey) 164 } 165 166 if strippedKey == nil { 167 // Either Armored key was not saved or ReadOneKeyFromString 168 // failed. Do old behavior here - we won't have a proper copy 169 // of the key (there is a lot of pointers in the key structs), 170 // but at least we won't have to bail out completely. 171 entityCopy := *k.Entity 172 strippedKey = &PGPKeyBundle{Entity: &entityCopy} 173 } 174 175 strippedKey.Revocations = nil 176 177 oldSubkeys := strippedKey.Subkeys 178 strippedKey.Subkeys = nil 179 for _, subkey := range oldSubkeys { 180 // Skip revoked subkeys 181 if subkey.Sig.SigType == packet.SigTypeSubkeyBinding && subkey.Revocation == nil { 182 strippedKey.Subkeys = append(strippedKey.Subkeys, subkey) 183 } 184 } 185 return 186} 187 188func (k *PGPKeyBundle) StoreToLocalDb(g *GlobalContext) error { 189 s, err := k.Encode() 190 if err != nil { 191 return err 192 } 193 val := jsonw.NewString(s) 194 g.Log.Debug("| Storing Key (kid=%s) to Local DB", k.GetKID()) 195 return g.LocalDb.Put(DbKey{Typ: DBPGPKey, Key: k.GetKID().String()}, []DbKey{}, val) 196} 197 198func (p PGPFingerprint) Eq(p2 PGPFingerprint) bool { 199 return FastByteArrayEq(p[:], p2[:]) 200} 201 202func GetPGPFingerprint(w *jsonw.Wrapper) (*PGPFingerprint, error) { 203 s, err := w.GetString() 204 if err != nil { 205 return nil, err 206 } 207 return PGPFingerprintFromHex(s) 208} 209 210func GetPGPFingerprintVoid(w *jsonw.Wrapper, p *PGPFingerprint, e *error) { 211 ret, err := GetPGPFingerprint(w) 212 if err != nil { 213 *e = err 214 } else { 215 *p = *ret 216 } 217} 218 219func (p *PGPFingerprint) UnmarshalJSON(b []byte) error { 220 tmp, err := PGPFingerprintFromHex(keybase1.Unquote(b)) 221 if err != nil { 222 return err 223 } 224 *p = *tmp 225 return nil 226} 227 228func (p *PGPFingerprint) MarshalJSON() ([]byte, error) { 229 return keybase1.Quote(p.String()), nil 230} 231 232func (k PGPKeyBundle) toList() openpgp.EntityList { 233 list := make(openpgp.EntityList, 1) 234 list[0] = k.Entity 235 return list 236} 237 238func (k PGPKeyBundle) GetFingerprint() PGPFingerprint { 239 return PGPFingerprint(k.PrimaryKey.Fingerprint) 240} 241 242func (k PGPKeyBundle) GetFingerprintP() *PGPFingerprint { 243 fp := k.GetFingerprint() 244 return &fp 245} 246 247func GetPGPFingerprintFromGenericKey(k GenericKey) *PGPFingerprint { 248 switch pgp := k.(type) { 249 case *PGPKeyBundle: 250 return pgp.GetFingerprintP() 251 default: 252 return nil 253 } 254} 255 256func (k PGPKeyBundle) KeysById(id uint64, fp []byte) []openpgp.Key { 257 return k.toList().KeysById(id, fp) 258} 259 260func (k PGPKeyBundle) KeysByIdUsage(id uint64, fp []byte, usage byte) []openpgp.Key { 261 return k.toList().KeysByIdUsage(id, fp, usage) 262} 263 264func (k PGPKeyBundle) DecryptionKeys() []openpgp.Key { 265 return k.toList().DecryptionKeys() 266} 267 268func (k PGPKeyBundle) MatchesKey(key *openpgp.Key) bool { 269 return FastByteArrayEq(k.PrimaryKey.Fingerprint[:], 270 key.Entity.PrimaryKey.Fingerprint[:]) 271} 272 273func (k PGPKeyBundle) SamePrimaryAs(k2 PGPKeyBundle) bool { 274 return FastByteArrayEq(k.PrimaryKey.Fingerprint[:], k2.PrimaryKey.Fingerprint[:]) 275} 276 277func (k *PGPKeyBundle) Encode() (ret string, err error) { 278 if k.ArmoredPublicKey != "" { 279 return k.ArmoredPublicKey, nil 280 } 281 buf := bytes.Buffer{} 282 err = k.EncodeToStream(NopWriteCloser{&buf}, false) 283 if err == nil { 284 ret = buf.String() 285 k.ArmoredPublicKey = ret 286 } 287 return 288} 289 290func PGPKeyRawToArmored(raw []byte, priv bool) (ret string, err error) { 291 292 var writer io.WriteCloser 293 var out bytes.Buffer 294 var which string 295 296 if priv { 297 which = "PRIVATE" 298 } else { 299 which = "PUBLIC" 300 } 301 hdr := fmt.Sprintf("PGP %s KEY BLOCK", which) 302 303 writer, err = armor.Encode(&out, hdr, PGPArmorHeaders) 304 305 if err != nil { 306 return 307 } 308 if _, err = writer.Write(raw); err != nil { 309 return 310 } 311 writer.Close() 312 ret = out.String() 313 return 314} 315 316func (k *PGPKeyBundle) SerializePrivate(w io.Writer) error { 317 return k.Entity.SerializePrivate(w, &packet.Config{ReuseSignaturesOnSerialize: !k.Generated}) 318} 319 320func (k *PGPKeyBundle) EncodeToStream(wc io.WriteCloser, private bool) error { 321 // See Issue #32 322 which := "PUBLIC" 323 if private { 324 which = "PRIVATE" 325 } 326 writer, err := armor.Encode(wc, fmt.Sprintf("PGP %s KEY BLOCK", which), PGPArmorHeaders) 327 if err != nil { 328 return err 329 } 330 331 if private { 332 err = k.SerializePrivate(writer) 333 } else { 334 err = k.Entity.Serialize(writer) 335 } 336 if err != nil { 337 return err 338 } 339 340 return writer.Close() 341} 342 343var cleanPGPInputRxx = regexp.MustCompile(`[ \t\r]*\n[ \t\r]*`) 344var bug8612PrepassRxx = regexp.MustCompile(`^(?P<header>-{5}BEGIN PGP (.*?)-{5})(\s*(?P<junk>.+?))$`) 345 346func cleanPGPInput(s string) string { 347 s = strings.TrimSpace(s) 348 v := cleanPGPInputRxx.Split(s, -1) 349 ret := strings.Join(v, "\n") 350 return ret 351} 352 353// note: openpgp.ReadArmoredKeyRing only returns the first block. 354// It will never return multiple entities. 355func ReadOneKeyFromString(originalArmor string) (*PGPKeyBundle, *Warnings, error) { 356 return readOneKeyFromString(originalArmor, false /* liberal */) 357} 358 359// bug8612Prepass cleans off any garbage trailing the "-----" in the first line of a PGP 360// key. For years, the server allowed this junk through, so some keys on the server side 361// (and hashed into chains) have junk here. It's pretty safe to strip it out when replaying 362// sigchains, so do it. 363func bug8612Prepass(a string) string { 364 idx := strings.Index(a, "\n") 365 if idx < 0 { 366 return a 367 } 368 line0 := a[0:idx] 369 rest := a[idx:] 370 match := bug8612PrepassRxx.FindStringSubmatch(line0) 371 if len(match) == 0 { 372 return a 373 } 374 result := make(map[string]string) 375 for i, name := range bug8612PrepassRxx.SubexpNames() { 376 if i != 0 { 377 result[name] = match[i] 378 } 379 } 380 return result["header"] + rest 381} 382 383// note: openpgp.ReadArmoredKeyRing only returns the first block. 384// It will never return multiple entities. 385func ReadOneKeyFromStringLiberal(originalArmor string) (*PGPKeyBundle, *Warnings, error) { 386 return readOneKeyFromString(originalArmor, true /* liberal */) 387} 388 389func readOneKeyFromString(originalArmor string, liberal bool) (*PGPKeyBundle, *Warnings, error) { 390 cleanArmor := cleanPGPInput(originalArmor) 391 if liberal { 392 cleanArmor = bug8612Prepass(cleanArmor) 393 } 394 reader := strings.NewReader(cleanArmor) 395 el, err := openpgp.ReadArmoredKeyRing(reader) 396 return finishReadOne(el, originalArmor, err) 397} 398 399// firstPrivateKey scans s for a private key block. 400func firstPrivateKey(s string) (string, error) { 401 scanner := bufio.NewScanner(strings.NewReader(s)) 402 var lines []string 403 looking := true 404 complete := false 405 for scanner.Scan() { 406 line := scanner.Text() 407 if looking && strings.HasPrefix(line, "-----BEGIN PGP PRIVATE KEY BLOCK-----") { 408 looking = false 409 410 } 411 if looking { 412 continue 413 } 414 lines = append(lines, line) 415 if strings.HasPrefix(line, "-----END PGP PRIVATE KEY BLOCK-----") { 416 complete = true 417 break 418 } 419 } 420 if err := scanner.Err(); err != nil { 421 return "", err 422 } 423 if looking { 424 // never found a private key block 425 return "", NoSecretKeyError{} 426 } 427 if !complete { 428 // string ended without the end tag 429 return "", errors.New("never found end block line") 430 } 431 return strings.Join(lines, "\n"), nil 432} 433 434// ReadPrivateKeyFromString finds the first private key block in s 435// and decodes it into a PGPKeyBundle. It is useful in the case 436// where s contains multiple key blocks and you want the private 437// key block. For example, the result of gpg export. 438func ReadPrivateKeyFromString(s string) (*PGPKeyBundle, *Warnings, error) { 439 priv, err := firstPrivateKey(s) 440 if err != nil { 441 return nil, &Warnings{}, err 442 } 443 return ReadOneKeyFromString(priv) 444} 445 446func mergeKeysIfPossible(out *PGPKeyBundle, lst []*openpgp.Entity) error { 447 for _, e := range lst { 448 tmp := PGPKeyBundle{Entity: e} 449 if out.SamePrimaryAs(tmp) { 450 out.MergeKey(&tmp) 451 } else { 452 return TooManyKeysError{len(lst) + 1} 453 } 454 } 455 return nil 456} 457 458func finishReadOne(lst []*openpgp.Entity, armored string, err error) (*PGPKeyBundle, *Warnings, error) { 459 w := &Warnings{} 460 if err != nil { 461 return nil, w, err 462 } 463 if len(lst) == 0 { 464 return nil, w, NoKeyError{"No keys found in primary bundle"} 465 } 466 first := &PGPKeyBundle{Entity: lst[0]} 467 468 if len(lst) > 1 { 469 470 // Some keys like Sheldon Hern's (https://github.com/keybase/client/issues/2130) 471 // have the same primary key twice in their list of keys. In this case, we should just 472 // perform a merge if possible, since the server-side accepts and merges such key exports. 473 err = mergeKeysIfPossible(first, lst[1:]) 474 if err != nil { 475 return nil, w, err 476 } 477 } 478 479 for _, bs := range first.Entity.BadSubkeys { 480 w.Push(Warningf("Bad subkey: %s", bs.Err)) 481 } 482 483 if first.Entity.PrivateKey == nil { 484 first.ArmoredPublicKey = armored 485 } 486 return first, w, nil 487} 488 489func ReadOneKeyFromBytes(b []byte) (*PGPKeyBundle, *Warnings, error) { 490 reader := bytes.NewBuffer(b) 491 el, err := openpgp.ReadKeyRing(reader) 492 return finishReadOne(el, "", err) 493} 494 495func GetOneKey(jw *jsonw.Wrapper) (*PGPKeyBundle, *Warnings, error) { 496 s, err := jw.GetString() 497 if err != nil { 498 return nil, &Warnings{}, err 499 } 500 return ReadOneKeyFromString(s) 501} 502 503// XXX for now this is OK but probably we need a PGP uid parser 504// as in pgp-utils 505func (k *PGPKeyBundle) FindKeybaseUsername(un string) bool { 506 507 rxx := regexp.MustCompile("(?i)< " + un + "@keybase.io>$") 508 509 for _, id := range k.Identities { 510 if rxx.MatchString(id.Name) { 511 return true 512 } 513 } 514 return false 515} 516 517func (k PGPKeyBundle) VerboseDescription() string { 518 lines := k.UsersDescription() 519 lines = append(lines, k.KeyDescription()) 520 return strings.Join(lines, "\n") 521} 522 523func (k PGPKeyBundle) HumanDescription() string { 524 user := k.GetPrimaryUID() 525 keyID := k.GetFingerprint().ToKeyID() 526 return fmt.Sprintf("PGP key %s %s", user, keyID) 527} 528 529func (k PGPKeyBundle) UsersDescription() []string { 530 id := k.GetPrimaryUID() 531 if len(id) == 0 { 532 return nil 533 } 534 return []string{"user: " + id} 535} 536 537// GetPrimaryUID gets the primary UID in the given key bundle, returned 538// in the 'Max K (foo) <bar@baz.com>' convention. 539func (k PGPKeyBundle) GetPrimaryUID() string { 540 541 var pri *openpgp.Identity 542 var s string 543 if len(k.Identities) == 0 { 544 return "" 545 } 546 var first *openpgp.Identity 547 for _, id := range k.Identities { 548 if first == nil { 549 first = id 550 } 551 if id.SelfSignature != nil && id.SelfSignature.IsPrimaryId != nil && *id.SelfSignature.IsPrimaryId { 552 pri = id 553 break 554 } 555 } 556 if pri == nil { 557 pri = first 558 } 559 if pri.UserId != nil { 560 s = pri.UserId.Id 561 } else { 562 s = pri.Name 563 } 564 return s 565} 566 567// HasSecretKey checks if the PGPKeyBundle contains secret key. This 568// function returning true does not indicate that the key is 569// functional - it may also be a key stub. 570func (k *PGPKeyBundle) HasSecretKey() bool { 571 return k.PrivateKey != nil 572} 573 574// FindPGPPrivateKey checks if supposed secret key PGPKeyBundle 575// contains any valid PrivateKey entities. Sometimes primary private 576// key is stoopped out but there are subkeys with secret keys. 577func FindPGPPrivateKey(k *PGPKeyBundle) bool { 578 if k.PrivateKey.PrivateKey != nil { 579 return true 580 } 581 582 for _, subKey := range k.Subkeys { 583 if subKey.PrivateKey != nil && subKey.PrivateKey.PrivateKey != nil { 584 return true 585 } 586 } 587 588 return false 589} 590 591func (k *PGPKeyBundle) CheckSecretKey() (err error) { 592 if k.PrivateKey == nil { 593 err = NoSecretKeyError{} 594 } else if k.PrivateKey.Encrypted { 595 err = kbcrypto.BadKeyError{Msg: "PGP key material should be unencrypted"} 596 } else if !FindPGPPrivateKey(k) && k.GPGFallbackKey == nil { 597 err = kbcrypto.BadKeyError{Msg: "no private key material or GPGKey"} 598 } 599 return 600} 601 602func (k *PGPKeyBundle) CanSign() bool { 603 return (k.PrivateKey != nil && !k.PrivateKey.Encrypted) || k.GPGFallbackKey != nil 604} 605 606func (k *PGPKeyBundle) GetBinaryKID() keybase1.BinaryKID { 607 608 prefix := []byte{ 609 byte(kbcrypto.KeybaseKIDV1), 610 byte(k.PrimaryKey.PubKeyAlgo), 611 } 612 613 // XXX Hack; Because PublicKey.serializeWithoutHeaders is off-limits 614 // to us, we need to do a full serialize and then strip off the header. 615 // The further annoyance is that the size of the header varies with the 616 // bitlen of the key. Small keys (<191 bytes total) yield 8 bytes of header 617 // material --- for instance, 1024-bit test keys. For longer keys, we 618 // have 9 bytes of header material, to encode a 2-byte frame, rather than 619 // a 1-byte frame. 620 buf := bytes.Buffer{} 621 _ = k.PrimaryKey.Serialize(&buf) 622 byts := buf.Bytes() 623 hdrBytes := 8 624 if len(byts) >= 193 { 625 hdrBytes++ 626 } 627 sum := sha256.Sum256(buf.Bytes()[hdrBytes:]) 628 629 out := append(prefix, sum[:]...) 630 out = append(out, byte(kbcrypto.IDSuffixKID)) 631 632 return keybase1.BinaryKID(out) 633} 634 635func (k *PGPKeyBundle) GetKID() keybase1.KID { 636 return k.GetBinaryKID().ToKID() 637} 638 639func (k PGPKeyBundle) GetAlgoType() kbcrypto.AlgoType { 640 return kbcrypto.AlgoType(k.PrimaryKey.PubKeyAlgo) 641} 642 643func (k PGPKeyBundle) KeyDescription() string { 644 algo, kid, creation := k.KeyInfo() 645 return fmt.Sprintf("%s, ID %s, created %s", algo, kid, creation) 646} 647 648func (k PGPKeyBundle) KeyInfo() (algorithm, kid, creation string) { 649 pubkey := k.PrimaryKey 650 651 var typ string 652 switch pubkey.PubKeyAlgo { 653 case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoRSASignOnly: 654 typ = "RSA" 655 case packet.PubKeyAlgoDSA: 656 typ = "DSA" 657 case packet.PubKeyAlgoECDSA: 658 typ = "ECDSA" 659 case packet.PubKeyAlgoEdDSA: 660 typ = "EdDSA" 661 default: 662 typ = "<UNKNOWN TYPE>" 663 } 664 665 bl, err := pubkey.BitLength() 666 if err != nil { 667 bl = 0 668 } 669 670 algorithm = fmt.Sprintf("%d-bit %s key", bl, typ) 671 kid = pubkey.KeyIdString() 672 creation = pubkey.CreationTime.Format("2006-01-02") 673 674 return 675} 676 677// Generates hash security warnings given a CKF 678func (k PGPKeyBundle) SecurityWarnings(kind HashSecurityWarningType) (warnings HashSecurityWarnings) { 679 fingerprint := k.GetFingerprint() 680 for _, identity := range k.Entity.Identities { 681 if identity.SelfSignature == nil || 682 IsHashSecure(identity.SelfSignature.Hash) { 683 continue 684 } 685 686 warnings = append( 687 warnings, 688 NewHashSecurityWarning( 689 kind, 690 identity.SelfSignature.Hash, 691 &fingerprint, 692 ), 693 ) 694 return 695 } 696 return 697} 698 699func unlockPrivateKey(k *packet.PrivateKey, pw string) error { 700 if !k.Encrypted { 701 return nil 702 } 703 err := k.Decrypt([]byte(pw)) 704 if err != nil && strings.HasSuffix(err.Error(), "private key checksum failure") { 705 // XXX this is gross, the openpgp library should return a better 706 // error if the PW was incorrectly specified 707 err = PassphraseError{} 708 } 709 return err 710} 711 712func (k *PGPKeyBundle) isAnyKeyEncrypted() bool { 713 if k.PrivateKey.Encrypted { 714 return true 715 } 716 717 for _, subkey := range k.Subkeys { 718 if subkey.PrivateKey.Encrypted { 719 return true 720 } 721 } 722 723 return false 724} 725 726func (k *PGPKeyBundle) unlockAllPrivateKeys(pw string) error { 727 if err := unlockPrivateKey(k.PrivateKey, pw); err != nil { 728 return err 729 } 730 for _, subkey := range k.Subkeys { 731 if err := unlockPrivateKey(subkey.PrivateKey, pw); err != nil { 732 return err 733 } 734 } 735 return nil 736} 737 738func (k *PGPKeyBundle) Unlock(m MetaContext, reason string, secretUI SecretUI) error { 739 if !k.isAnyKeyEncrypted() { 740 m.Debug("Key is not encrypted, skipping Unlock.") 741 return nil 742 } 743 744 unlocker := func(pw string, _ bool) (ret GenericKey, err error) { 745 if err = k.unlockAllPrivateKeys(pw); err != nil { 746 return nil, err 747 } 748 return k, nil 749 } 750 751 _, err := NewKeyUnlocker(5, reason, k.VerboseDescription(), PassphraseTypePGP, false, secretUI, unlocker).Run(m) 752 return err 753} 754 755func (k *PGPKeyBundle) CheckFingerprint(fp *PGPFingerprint) error { 756 if k == nil { 757 return UnexpectedKeyError{} 758 } 759 if fp == nil { 760 return UnexpectedKeyError{} 761 } 762 fp2 := k.GetFingerprint() 763 if !fp2.Eq(*fp) { 764 return BadFingerprintError{fp2, *fp} 765 } 766 return nil 767} 768 769func (k *PGPKeyBundle) SignToString(msg []byte) (sig string, id keybase1.SigIDBase, err error) { 770 if sig, id, err = SimpleSign(msg, *k); err != nil && k.GPGFallbackKey != nil { 771 return k.GPGFallbackKey.SignToString(msg) 772 } 773 return 774} 775 776func (k PGPKeyBundle) VerifyStringAndExtract(ctx VerifyContext, sig string) (msg []byte, id keybase1.SigIDBase, err error) { 777 var ps *ParsedSig 778 if ps, err = PGPOpenSig(sig); err != nil { 779 return 780 } else if err = ps.Verify(k); err != nil { 781 ctx.Debug("Failing key----------\n%s", k.ArmoredPublicKey) 782 ctx.Debug("Failing sig----------\n%s", sig) 783 return 784 } 785 msg = ps.LiteralData 786 id = ps.ID() 787 return 788} 789 790func (k PGPKeyBundle) VerifyString(ctx VerifyContext, sig string, msg []byte) (id keybase1.SigIDBase, err error) { 791 extractedMsg, resID, err := k.VerifyStringAndExtract(ctx, sig) 792 if err != nil { 793 return 794 } 795 if !FastByteArrayEq(extractedMsg, msg) { 796 err = BadSigError{"wrong payload"} 797 return 798 } 799 id = resID 800 return 801} 802 803func IsPGPAlgo(algo kbcrypto.AlgoType) bool { 804 switch algo { 805 case kbcrypto.KIDPGPRsa, kbcrypto.KIDPGPElgamal, kbcrypto.KIDPGPDsa, kbcrypto.KIDPGPEcdh, kbcrypto.KIDPGPEcdsa, kbcrypto.KIDPGPBase, kbcrypto.KIDPGPEddsa: 806 return true 807 } 808 return false 809} 810 811func (k *PGPKeyBundle) FindEmail(em string) bool { 812 for _, ident := range k.Identities { 813 if i, e := ParseIdentity(ident.Name); e == nil && i.Email == em { 814 return true 815 } 816 } 817 return false 818} 819 820func (k *PGPKeyBundle) IdentityNames() []string { 821 var names []string 822 for _, ident := range k.Identities { 823 names = append(names, ident.Name) 824 } 825 return names 826} 827 828func (k *PGPKeyBundle) GetPGPIdentities() []keybase1.PGPIdentity { 829 ret := make([]keybase1.PGPIdentity, len(k.Identities)) 830 for _, pgpIdentity := range k.Identities { 831 ret = append(ret, ExportPGPIdentity(pgpIdentity)) 832 } 833 return ret 834} 835 836// CheckIdentity finds the foo_user@keybase.io PGP identity and figures out when it 837// was created and when it's slated to expire. We plan to start phasing out use of 838// PGP-specified Expiration times as far as sigchain walking is concerned. But for now, 839// there are a few places where it's still used (see ComputedKeyInfos#InsertServerEldestKey). 840func (k *PGPKeyBundle) CheckIdentity(kbid Identity) (match bool, ctime int64, etime int64) { 841 ctime, etime = -1, -1 842 for _, pgpIdentity := range k.Identities { 843 if Cicmp(pgpIdentity.UserId.Email, kbid.Email) { 844 match = true 845 ctime = pgpIdentity.SelfSignature.CreationTime.Unix() 846 // This is a special case in OpenPGP, so we used KeyLifetimeSecs 847 lifeSeconds := pgpIdentity.SelfSignature.KeyLifetimeSecs 848 if lifeSeconds == nil { 849 // No expiration time is OK, it just means it never expires. 850 etime = 0 851 } else { 852 etime = ctime + int64(*lifeSeconds) 853 } 854 break 855 } 856 } 857 return 858} 859 860// EncryptToString fails for this type of key, since we haven't implemented it yet 861func (k *PGPKeyBundle) EncryptToString(plaintext []byte, sender GenericKey) (ciphertext string, err error) { 862 err = KeyCannotEncryptError{} 863 return 864} 865 866// DecryptFromString fails for this type of key, since we haven't implemented it yet 867func (k *PGPKeyBundle) DecryptFromString(ciphertext string) (msg []byte, sender keybase1.KID, err error) { 868 err = KeyCannotDecryptError{} 869 return 870} 871 872// CanEncrypt returns false for now, since we haven't implemented PGP encryption of packets 873// for metadata operations 874func (k *PGPKeyBundle) CanEncrypt() bool { return false } 875 876// CanDecrypt returns false for now, since we haven't implemented PGP encryption of packets 877// for metadata operations 878func (k *PGPKeyBundle) CanDecrypt() bool { return false } 879 880func (k *PGPKeyBundle) ExportPublicAndPrivate() (public RawPublicKey, private RawPrivateKey, err error) { 881 var publicKey, privateKey bytes.Buffer 882 883 serializePublic := func() error { return k.Entity.Serialize(&publicKey) } 884 serializePrivate := func() error { return k.SerializePrivate(&privateKey) } 885 886 // NOTE(maxtaco): For imported keys, it is crucial to serialize the public key 887 // **before** the private key, since the latter operation destructively 888 // removes signature subpackets from the key serialization. 889 // This was the cause of keybase/keybase-issues#1906. 890 // 891 // Urg, there's still more. For generated keys, it's the opposite. 892 // We have to sign the key components first (via SerializePrivate) 893 // so we can export them publicly. 894 895 if k.Generated { 896 err = serializePrivate() 897 if err == nil { 898 err = serializePublic() 899 } 900 } else { 901 err = serializePublic() 902 903 if err == nil { 904 err = serializePrivate() 905 } 906 } 907 908 if err != nil { 909 return nil, nil, err 910 } 911 912 return RawPublicKey(publicKey.Bytes()), RawPrivateKey(privateKey.Bytes()), nil 913} 914 915func (k *PGPKeyBundle) SecretSymmetricKey(reason EncryptionReason) (NaclSecretBoxKey, error) { 916 return NaclSecretBoxKey{}, KeyCannotEncryptError{} 917} 918 919//=================================================== 920 921// Fulfill the TrackIdComponent interface 922 923func (p PGPFingerprint) ToIDString() string { 924 return p.String() 925} 926 927func (p PGPFingerprint) ToKeyValuePair() (string, string) { 928 return PGPAssertionKey, p.ToIDString() 929} 930 931func (p PGPFingerprint) GetProofState() keybase1.ProofState { 932 return keybase1.ProofState_OK 933} 934 935func (p PGPFingerprint) LastWriterWins() bool { 936 return false 937} 938 939func (p PGPFingerprint) GetProofType() keybase1.ProofType { 940 return keybase1.ProofType_PGP 941} 942 943//=================================================== 944 945func EncryptPGPKey(bundle *openpgp.Entity, passphrase string) error { 946 passBytes := []byte(passphrase) 947 948 if bundle.PrivateKey != nil && bundle.PrivateKey.PrivateKey != nil { 949 // Primary private key exists and is not stubbed. 950 if err := bundle.PrivateKey.Encrypt(passBytes, nil); err != nil { 951 return err 952 } 953 } 954 955 for _, subkey := range bundle.Subkeys { 956 if subkey.PrivateKey == nil || subkey.PrivateKey.PrivateKey == nil { 957 // There has to be a private key and not stubbed. 958 continue 959 } 960 961 if err := subkey.PrivateKey.Encrypt(passBytes, nil); err != nil { 962 return err 963 } 964 } 965 966 return nil 967} 968