github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/kbsig.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 // Code used in populating JSON objects to generating Keybase-style 5 // signatures. 6 package libkb 7 8 import ( 9 "encoding/base64" 10 "encoding/hex" 11 "errors" 12 "fmt" 13 14 keybase1 "github.com/keybase/client/go/protocol/keybase1" 15 stellar1 "github.com/keybase/client/go/protocol/stellar1" 16 jsonw "github.com/keybase/go-jsonw" 17 ) 18 19 func clientInfo(m MetaContext) *jsonw.Wrapper { 20 ret := jsonw.NewDictionary() 21 _ = ret.SetKey("version", jsonw.NewString(Version)) 22 _ = ret.SetKey("name", jsonw.NewString(GoClientID)) 23 return ret 24 } 25 26 type KeySection struct { 27 Key GenericKey 28 EldestKID keybase1.KID 29 ParentKID keybase1.KID 30 HasRevSig bool 31 RevSig string 32 SigningUser UserBasic 33 IncludePGPHash bool 34 PerUserKeyGeneration keybase1.PerUserKeyGeneration 35 } 36 37 func LinkEntropy() (string, error) { 38 entropyBytes, err := RandBytes(18) 39 if err != nil { 40 return "", fmt.Errorf("failed to generate entropy bytes: %v", err) 41 } 42 return base64.StdEncoding.EncodeToString(entropyBytes), nil 43 } 44 45 func (arg KeySection) ToJSON() (*jsonw.Wrapper, error) { 46 ret := jsonw.NewDictionary() 47 48 err := ret.SetKey("kid", jsonw.NewString(arg.Key.GetKID().String())) 49 if err != nil { 50 return nil, err 51 } 52 53 if arg.EldestKID != "" { 54 err := ret.SetKey("eldest_kid", jsonw.NewString(arg.EldestKID.String())) 55 if err != nil { 56 return nil, err 57 } 58 } 59 60 if arg.ParentKID != "" { 61 err := ret.SetKey("parent_kid", jsonw.NewString(arg.ParentKID.String())) 62 if err != nil { 63 return nil, err 64 } 65 } 66 67 if arg.HasRevSig { 68 var revSig *jsonw.Wrapper 69 if arg.RevSig != "" { 70 revSig = jsonw.NewString(arg.RevSig) 71 } else { 72 revSig = jsonw.NewNil() 73 } 74 err := ret.SetKey("reverse_sig", revSig) 75 if err != nil { 76 return nil, err 77 } 78 } 79 80 if arg.SigningUser != nil { 81 err := ret.SetKey("host", jsonw.NewString(CanonicalHost)) 82 if err != nil { 83 return nil, err 84 } 85 err = ret.SetKey("uid", UIDWrapper(arg.SigningUser.GetUID())) 86 if err != nil { 87 return nil, err 88 } 89 err = ret.SetKey("username", jsonw.NewString(arg.SigningUser.GetName())) 90 if err != nil { 91 return nil, err 92 } 93 } 94 95 if arg.PerUserKeyGeneration != 0 { 96 err := ret.SetKey("generation", jsonw.NewInt(int(arg.PerUserKeyGeneration))) 97 if err != nil { 98 return nil, err 99 } 100 } 101 102 if pgp, ok := arg.Key.(*PGPKeyBundle); ok { 103 fingerprint := pgp.GetFingerprint() 104 err := ret.SetKey("fingerprint", jsonw.NewString(fingerprint.String())) 105 if err != nil { 106 return nil, err 107 } 108 err = ret.SetKey("key_id", jsonw.NewString(fingerprint.ToKeyID())) 109 if err != nil { 110 return nil, err 111 } 112 if arg.IncludePGPHash { 113 hash, err := pgp.FullHash() 114 if err != nil { 115 return nil, err 116 } 117 118 err = ret.SetKey("full_hash", jsonw.NewString(hash)) 119 if err != nil { 120 return nil, err 121 } 122 } 123 } 124 125 return ret, nil 126 } 127 128 func (u *User) ToTrackingStatementKey(errp *error) *jsonw.Wrapper { 129 ret := jsonw.NewDictionary() 130 131 if !u.HasActiveKey() { 132 *errp = fmt.Errorf("User %s doesn't have an active key", u.GetName()) 133 } else { 134 kid := u.GetEldestKID() 135 _ = ret.SetKey("kid", jsonw.NewString(kid.String())) 136 ckf := u.GetComputedKeyFamily() 137 if fingerprint, exists := ckf.kf.kid2pgp[kid]; exists { 138 _ = ret.SetKey("key_fingerprint", jsonw.NewString(fingerprint.String())) 139 } 140 } 141 return ret 142 } 143 144 func (u *User) ToTrackingStatementPGPKeys(errp *error) *jsonw.Wrapper { 145 keys := u.GetActivePGPKeys(true) 146 if len(keys) == 0 { 147 return nil 148 } 149 150 ret := jsonw.NewArray(len(keys)) 151 for i, k := range keys { 152 kd := jsonw.NewDictionary() 153 kid := k.GetKID() 154 fp := k.GetFingerprintP() 155 _ = kd.SetKey("kid", jsonw.NewString(kid.String())) 156 if fp != nil { 157 _ = kd.SetKey("key_fingerprint", jsonw.NewString(fp.String())) 158 } 159 _ = ret.SetIndex(i, kd) 160 } 161 return ret 162 } 163 164 func (u *User) ToTrackingStatementBasics(errp *error) *jsonw.Wrapper { 165 ret := jsonw.NewDictionary() 166 _ = ret.SetKey("username", jsonw.NewString(u.name)) 167 if lastIDChange, err := u.basics.AtKey("last_id_change").GetInt(); err == nil { 168 _ = ret.SetKey("last_id_change", jsonw.NewInt(lastIDChange)) 169 } 170 if idVersion, err := u.basics.AtKey("id_version").GetInt(); err == nil { 171 _ = ret.SetKey("id_version", jsonw.NewInt(idVersion)) 172 } 173 return ret 174 } 175 176 func (u *User) ToTrackingStatementSeqTail() *jsonw.Wrapper { 177 mul := u.GetPublicChainTail() 178 if mul == nil { 179 return jsonw.NewNil() 180 } 181 ret := jsonw.NewDictionary() 182 _ = ret.SetKey("sig_id", jsonw.NewString(mul.SigID.ToSigIDLegacy().String())) 183 _ = ret.SetKey("seqno", jsonw.NewInt(int(mul.Seqno))) 184 _ = ret.SetKey("payload_hash", jsonw.NewString(mul.LinkID.String())) 185 return ret 186 } 187 188 func (u *User) ToTrackingStatement(w *jsonw.Wrapper, outcome *IdentifyOutcome) (err error) { 189 190 track := jsonw.NewDictionary() 191 if u.HasActiveKey() { 192 key := u.ToTrackingStatementKey(&err) 193 if key != nil { 194 _ = track.SetKey("key", key) 195 } 196 } 197 if pgpkeys := u.ToTrackingStatementPGPKeys(&err); pgpkeys != nil { 198 err := track.SetKey("pgp_keys", pgpkeys) 199 if err != nil { 200 return err 201 } 202 } 203 err = track.SetKey("seq_tail", u.ToTrackingStatementSeqTail()) 204 if err != nil { 205 return err 206 } 207 err = track.SetKey("basics", u.ToTrackingStatementBasics(&err)) 208 if err != nil { 209 return err 210 } 211 err = track.SetKey("id", UIDWrapper(u.id)) 212 if err != nil { 213 return err 214 } 215 err = track.SetKey("remote_proofs", outcome.TrackingStatement()) 216 if err != nil { 217 return err 218 } 219 220 entropy, err := LinkEntropy() 221 if err != nil { 222 return err 223 } 224 err = track.SetKey("entropy", jsonw.NewString(entropy)) 225 if err != nil { 226 return err 227 } 228 229 return w.SetKey("track", track) 230 } 231 232 func (u *User) ToWotStatement() *jsonw.Wrapper { 233 user := jsonw.NewDictionary() 234 _ = user.SetKey("username", jsonw.NewString(u.GetNormalizedName().String())) 235 _ = user.SetKey("uid", UIDWrapper(u.GetUID())) 236 _ = user.SetKey("seq_tail", u.ToTrackingStatementSeqTail()) 237 eldest := jsonw.NewDictionary() 238 _ = eldest.SetKey("kid", jsonw.NewString(u.GetEldestKID().String())) 239 _ = eldest.SetKey("seqno", jsonw.NewInt64(int64(u.GetCurrentEldestSeqno()))) 240 _ = user.SetKey("eldest", eldest) 241 242 return user 243 } 244 245 func (u *User) ToUntrackingStatementBasics() *jsonw.Wrapper { 246 ret := jsonw.NewDictionary() 247 _ = ret.SetKey("username", jsonw.NewString(u.name)) 248 return ret 249 } 250 251 func (u *User) ToUntrackingStatement(w *jsonw.Wrapper) (err error) { 252 untrack := jsonw.NewDictionary() 253 err = untrack.SetKey("basics", u.ToUntrackingStatementBasics()) 254 if err != nil { 255 return err 256 } 257 err = untrack.SetKey("id", UIDWrapper(u.GetUID())) 258 if err != nil { 259 return err 260 } 261 262 entropy, err := LinkEntropy() 263 if err != nil { 264 return err 265 } 266 err = untrack.SetKey("entropy", jsonw.NewString(entropy)) 267 if err != nil { 268 return err 269 } 270 271 return w.SetKey("untrack", untrack) 272 } 273 274 func (g *GenericChainLink) BaseToTrackingStatement(state keybase1.ProofState) *jsonw.Wrapper { 275 ret := jsonw.NewDictionary() 276 _ = ret.SetKey("curr", jsonw.NewString(g.id.String())) 277 _ = ret.SetKey("sig_id", jsonw.NewString(g.GetSigID().String())) 278 279 rkp := jsonw.NewDictionary() 280 _ = ret.SetKey("remote_key_proof", rkp) 281 _ = rkp.SetKey("state", jsonw.NewInt(int(state))) 282 283 prev := g.GetPrev() 284 var prevVal *jsonw.Wrapper 285 if prev == nil { 286 prevVal = jsonw.NewNil() 287 } else { 288 prevVal = jsonw.NewString(prev.String()) 289 } 290 291 _ = ret.SetKey("prev", prevVal) 292 _ = ret.SetKey("ctime", jsonw.NewInt64(g.unpacked.ctime)) 293 _ = ret.SetKey("etime", jsonw.NewInt64(g.unpacked.etime)) 294 return ret 295 } 296 297 func remoteProofToTrackingStatement(s RemoteProofChainLink, base *jsonw.Wrapper) { 298 proofType := s.GetProofType() 299 _ = base.AtKey("remote_key_proof").SetKey("proof_type", jsonw.NewInt(int(proofType))) 300 _ = base.AtKey("remote_key_proof").SetKey("check_data_json", s.CheckDataJSON()) 301 _ = base.SetKey("sig_type", jsonw.NewInt(SigTypeRemoteProof)) 302 } 303 304 type HighSkip struct { 305 Seqno keybase1.Seqno 306 Hash LinkID 307 } 308 309 func NewHighSkip(highSkipSeqno keybase1.Seqno, highSkipHash LinkID) HighSkip { 310 return HighSkip{ 311 Seqno: highSkipSeqno, 312 Hash: highSkipHash, 313 } 314 } 315 316 func NewInitialHighSkip() HighSkip { 317 return NewHighSkip(keybase1.Seqno(0), nil) 318 } 319 320 func (h HighSkip) AssertEqualsExpected(expected HighSkip) error { 321 if expected.Seqno != h.Seqno { 322 return fmt.Errorf("Expected highSkip.Seqno %d, got %d.", expected.Seqno, h.Seqno) 323 } 324 if !expected.Hash.Eq(h.Hash) { 325 return fmt.Errorf("Expected highSkip.Hash %s, got %s.", expected.Hash.String(), h.Hash.String()) 326 } 327 return nil 328 } 329 330 type ProofMetadata struct { 331 Me *User 332 SigningUser UserBasic 333 Seqno keybase1.Seqno 334 PrevLinkID LinkID 335 LinkType LinkType 336 SigningKey GenericKey 337 Eldest keybase1.KID 338 CreationTime int64 339 ExpireIn int 340 IncludePGPHash bool 341 SigVersion SigVersion 342 SeqType keybase1.SeqType 343 MerkleRoot *MerkleRoot 344 IgnoreIfUnsupported SigIgnoreIfUnsupported 345 // HighSkipFallback is used for teams to provide for a KEX-provisisonee to 346 // provide the provisioner's information as the latest high link. 347 HighSkipFallback *HighSkip 348 } 349 350 type ProofMetadataRes struct { 351 J *jsonw.Wrapper 352 Seqno keybase1.Seqno 353 } 354 355 func (arg ProofMetadata) merkleRootInfo(m MetaContext) (ret *jsonw.Wrapper) { 356 if mr := arg.MerkleRoot; mr != nil { 357 return mr.ToSigJSON() 358 } 359 if mc := m.G().MerkleClient; mc != nil { 360 ret, _ = mc.LastRootToSigJSON(m) 361 } 362 return ret 363 } 364 365 func (arg ProofMetadata) ToJSON(m MetaContext) (*jsonw.Wrapper, error) { 366 res, err := arg.ToJSON2(m) 367 if err != nil { 368 return nil, err 369 } 370 return res.J, nil 371 } 372 373 func (arg ProofMetadata) ToJSON2(m MetaContext) (ret *ProofMetadataRes, err error) { 374 // if only Me exists, then that is the signing user too 375 if arg.SigningUser == nil && arg.Me != nil { 376 arg.SigningUser = arg.Me 377 } 378 379 var seqno keybase1.Seqno 380 var prev *jsonw.Wrapper 381 382 // sanity check the seqno and prev relationship 383 if arg.Seqno > 1 && len(arg.PrevLinkID) == 0 { 384 return nil, fmt.Errorf("can't have a seqno > 1 without a prev value") 385 } 386 387 if arg.Seqno > 0 { 388 seqno = arg.Seqno 389 if arg.Seqno == 1 { 390 prev = jsonw.NewNil() 391 } else { 392 prev = jsonw.NewString(arg.PrevLinkID.String()) 393 } 394 } else { 395 if arg.Me == nil { 396 return nil, fmt.Errorf("missing self user object while signing") 397 } 398 lastSeqno := arg.Me.sigChain().GetLastKnownSeqno() 399 lastLink := arg.Me.sigChain().GetLastKnownID() 400 if lastLink == nil { 401 seqno = 1 402 prev = jsonw.NewNil() 403 } else { 404 seqno = lastSeqno + 1 405 prev = jsonw.NewString(lastLink.String()) 406 } 407 } 408 409 ctime := arg.CreationTime 410 if ctime == 0 { 411 ctime = m.G().Clock().Now().Unix() 412 } 413 414 ei := arg.ExpireIn 415 if ei == 0 { 416 ei = SigExpireIn 417 } 418 419 j := jsonw.NewDictionary() 420 err = j.SetKey("tag", jsonw.NewString("signature")) 421 if err != nil { 422 return nil, err 423 } 424 err = j.SetKey("ctime", jsonw.NewInt64(ctime)) 425 if err != nil { 426 return nil, err 427 } 428 err = j.SetKey("expire_in", jsonw.NewInt(ei)) 429 if err != nil { 430 return nil, err 431 } 432 err = j.SetKey("seqno", jsonw.NewInt64(int64(seqno))) 433 if err != nil { 434 return nil, err 435 } 436 err = j.SetKey("prev", prev) 437 if err != nil { 438 return nil, err 439 } 440 441 var highSkip *HighSkip 442 allowHighSkips := m.G().Env.GetFeatureFlags().HasFeature(EnvironmentFeatureAllowHighSkips) 443 if allowHighSkips { 444 if (arg.Me != nil) && (arg.HighSkipFallback != nil) { 445 return nil, fmt.Errorf("arg.Me and arg.HighSkipFallback can't both be non-nil.") 446 } else if arg.Me != nil { 447 highSkipPre, err := arg.Me.GetExpectedNextHighSkip(m) 448 if err != nil { 449 return nil, err 450 } 451 highSkip = &highSkipPre 452 } else if arg.HighSkipFallback != nil { 453 highSkip = arg.HighSkipFallback 454 } 455 456 if highSkip != nil { 457 highSkipObj := jsonw.NewDictionary() 458 err := highSkipObj.SetKey("seqno", jsonw.NewInt64(int64(highSkip.Seqno))) 459 if err != nil { 460 return nil, err 461 } 462 if hash := highSkip.Hash; hash != nil { 463 err := highSkipObj.SetKey("hash", jsonw.NewString(hash.String())) 464 if err != nil { 465 return nil, err 466 } 467 } else { 468 err := highSkipObj.SetKey("hash", jsonw.NewNil()) 469 if err != nil { 470 return nil, err 471 } 472 } 473 err = j.SetKey("high_skip", highSkipObj) 474 if err != nil { 475 return nil, err 476 } 477 } 478 } 479 480 if arg.IgnoreIfUnsupported { 481 err := j.SetKey("ignore_if_unsupported", jsonw.NewBool(true)) 482 if err != nil { 483 return nil, err 484 } 485 } 486 eldest := arg.Eldest 487 if eldest == "" { 488 if arg.Me == nil { 489 return nil, fmt.Errorf("missing self user object while signing") 490 } 491 eldest = arg.Me.GetEldestKID() 492 } 493 494 body := jsonw.NewDictionary() 495 496 if arg.SigVersion != 0 { 497 err := body.SetKey("version", jsonw.NewInt(int(arg.SigVersion))) 498 if err != nil { 499 return nil, err 500 } 501 } else { 502 err := body.SetKey("version", jsonw.NewInt(int(KeybaseSignatureV1))) 503 if err != nil { 504 return nil, err 505 } 506 } 507 508 err = body.SetKey("type", jsonw.NewString(string(arg.LinkType))) 509 if err != nil { 510 return nil, err 511 } 512 513 key, err := KeySection{ 514 Key: arg.SigningKey, 515 EldestKID: eldest, 516 SigningUser: arg.SigningUser, 517 IncludePGPHash: arg.IncludePGPHash, 518 }.ToJSON() 519 if err != nil { 520 return nil, err 521 } 522 err = body.SetKey("key", key) 523 if err != nil { 524 return nil, err 525 } 526 // Capture the most recent Merkle Root, inside of "body" 527 // field. 528 if mr := arg.merkleRootInfo(m); mr != nil { 529 err := body.SetKey("merkle_root", mr) 530 if err != nil { 531 return nil, err 532 } 533 } 534 535 err = j.SetKey("body", body) 536 if err != nil { 537 return nil, err 538 } 539 540 // Save what kind of client we're running. 541 err = j.SetKey("client", clientInfo(m)) 542 if err != nil { 543 return nil, err 544 } 545 546 if arg.SeqType != 0 { 547 err := j.SetKey("seq_type", jsonw.NewInt(int(arg.SeqType))) 548 if err != nil { 549 return nil, err 550 } 551 } 552 553 return &ProofMetadataRes{ 554 J: j, 555 Seqno: seqno, 556 }, nil 557 } 558 559 func (u *User) TrackingProofFor(m MetaContext, signingKey GenericKey, sigVersion SigVersion, u2 *User, outcome *IdentifyOutcome) (*ProofMetadataRes, error) { 560 ret, err := ProofMetadata{ 561 Me: u, 562 LinkType: LinkTypeTrack, 563 SigningKey: signingKey, 564 SigVersion: sigVersion, 565 }.ToJSON2(m) 566 if err == nil { 567 err = u2.ToTrackingStatement(ret.J.AtKey("body"), outcome) 568 } 569 return ret, err 570 } 571 572 func (u *User) UntrackingProofFor(m MetaContext, signingKey GenericKey, sigVersion SigVersion, u2 *User) (*ProofMetadataRes, error) { 573 ret, err := ProofMetadata{ 574 Me: u, 575 LinkType: LinkTypeUntrack, 576 SigningKey: signingKey, 577 SigVersion: sigVersion, 578 }.ToJSON2(m) 579 if err == nil { 580 err = u2.ToUntrackingStatement(ret.J.AtKey("body")) 581 } 582 return ret, err 583 } 584 585 // arg.Me user is used to get the last known seqno in ProofMetadata. 586 // If arg.Me == nil, set arg.Seqno. 587 func KeyProof(m MetaContext, arg Delegator) (*jsonw.Wrapper, error) { 588 res, err := KeyProof2(m, arg) 589 if err != nil { 590 return nil, err 591 } 592 return res.J, nil 593 } 594 595 // arg.Me user is used to get the last known seqno in ProofMetadata. 596 // If arg.Me == nil, set arg.Seqno. 597 func KeyProof2(m MetaContext, arg Delegator) (ret *ProofMetadataRes, err error) { 598 var kp *jsonw.Wrapper 599 includePGPHash := false 600 601 if arg.DelegationType == DelegationTypeEldest { 602 includePGPHash = true 603 } else if arg.NewKey != nil { 604 keySection := KeySection{ 605 Key: arg.NewKey, 606 } 607 switch arg.DelegationType { 608 case DelegationTypePGPUpdate: 609 keySection.IncludePGPHash = true 610 case DelegationTypeSibkey: 611 keySection.HasRevSig = true 612 keySection.RevSig = arg.RevSig 613 keySection.IncludePGPHash = true 614 default: 615 keySection.ParentKID = arg.ExistingKey.GetKID() 616 } 617 618 if kp, err = keySection.ToJSON(); err != nil { 619 return nil, err 620 } 621 } 622 623 // Only set the fallback for subkeys during KEX where arg.Me == nil; it is 624 // otherwise updated using me.SigChainBump(). 625 var highSkipFallback *HighSkip 626 if arg.Me == nil && arg.DelegationType == DelegationTypeSubkey { 627 highSkip := NewHighSkip(arg.Seqno-1, arg.PrevLinkID) 628 highSkipFallback = &highSkip 629 } 630 631 ret, err = ProofMetadata{ 632 Me: arg.Me, 633 SigningUser: arg.SigningUser, 634 LinkType: LinkType(arg.DelegationType), 635 ExpireIn: arg.Expire, 636 SigningKey: arg.GetSigningKey(), 637 Eldest: arg.EldestKID, 638 CreationTime: arg.Ctime, 639 IncludePGPHash: includePGPHash, 640 Seqno: arg.Seqno, 641 HighSkipFallback: highSkipFallback, 642 PrevLinkID: arg.PrevLinkID, 643 MerkleRoot: arg.MerkleRoot, 644 }.ToJSON2(m) 645 if err != nil { 646 return nil, err 647 } 648 649 body := ret.J.AtKey("body") 650 651 if arg.Device != nil { 652 device := *arg.Device 653 device.Kid = arg.NewKey.GetKID() 654 var dw *jsonw.Wrapper 655 dw, err = device.Export(LinkType(arg.DelegationType)) 656 if err != nil { 657 return nil, err 658 } 659 err = body.SetKey("device", dw) 660 if err != nil { 661 return nil, err 662 } 663 } 664 if kp != nil { 665 err := body.SetKey(string(arg.DelegationType), kp) 666 if err != nil { 667 return nil, err 668 } 669 } 670 return ret, nil 671 } 672 673 func (u *User) ServiceProof(m MetaContext, signingKey GenericKey, typ ServiceType, remotename string, sigVersion SigVersion) (*ProofMetadataRes, error) { 674 ret, err := ProofMetadata{ 675 Me: u, 676 LinkType: LinkTypeWebServiceBinding, 677 SigningKey: signingKey, 678 SigVersion: sigVersion, 679 }.ToJSON2(m) 680 if err != nil { 681 return nil, err 682 } 683 service := typ.ToServiceJSON(remotename) 684 entropy, err := LinkEntropy() 685 if err != nil { 686 return nil, err 687 } 688 err = service.SetKey("entropy", jsonw.NewString(entropy)) 689 if err != nil { 690 return nil, err 691 } 692 err = ret.J.AtKey("body").SetKey("service", service) 693 if err != nil { 694 return nil, err 695 } 696 return ret, nil 697 } 698 699 func (u *User) WotVouchProof(m MetaContext, signingKey GenericKey, sigVersion SigVersion, mac []byte, merkleRoot *MerkleRoot, sigIDToRevoke *keybase1.SigID) (*ProofMetadataRes, error) { 700 md := ProofMetadata{ 701 Me: u, 702 LinkType: LinkTypeWotVouch, 703 MerkleRoot: merkleRoot, 704 SigningKey: signingKey, 705 SigVersion: sigVersion, 706 IgnoreIfUnsupported: true, 707 } 708 ret, err := md.ToJSON2(m) 709 if err != nil { 710 return nil, err 711 } 712 713 body := ret.J.AtKey("body") 714 if err := body.SetKey("wot_vouch", jsonw.NewString(hex.EncodeToString(mac))); err != nil { 715 return nil, err 716 } 717 718 if sigIDToRevoke != nil { 719 revokeSection := jsonw.NewDictionary() 720 err := revokeSection.SetKey("sig_id", jsonw.NewString(sigIDToRevoke.String())) 721 if err != nil { 722 return nil, err 723 } 724 err = body.SetKey("revoke", revokeSection) 725 if err != nil { 726 return nil, err 727 } 728 } 729 730 return ret, nil 731 } 732 733 func (u *User) WotReactProof(m MetaContext, signingKey GenericKey, sigVersion SigVersion, mac []byte) (*ProofMetadataRes, error) { 734 md := ProofMetadata{ 735 Me: u, 736 LinkType: LinkTypeWotReact, 737 SigningKey: signingKey, 738 SigVersion: sigVersion, 739 IgnoreIfUnsupported: true, 740 } 741 ret, err := md.ToJSON2(m) 742 if err != nil { 743 return nil, err 744 } 745 746 body := ret.J.AtKey("body") 747 if err := body.SetKey("wot_react", jsonw.NewString(hex.EncodeToString(mac))); err != nil { 748 return nil, err 749 } 750 751 return ret, nil 752 } 753 754 // SimpleSignJson marshals the given Json structure and then signs it. 755 func SignJSON(jw *jsonw.Wrapper, key GenericKey) (out string, id keybase1.SigIDBase, lid LinkID, err error) { 756 var tmp []byte 757 if tmp, err = jw.Marshal(); err != nil { 758 return 759 } 760 out, id, err = key.SignToString(tmp) 761 lid = ComputeLinkID(tmp) 762 return 763 } 764 765 func GetDefaultSigVersion(g *GlobalContext) SigVersion { 766 return KeybaseSignatureV2 767 } 768 769 func MakeSig( 770 m MetaContext, 771 signingKey GenericKey, 772 v1LinkType LinkType, 773 innerLinkJSON []byte, 774 hasRevokes SigHasRevokes, 775 seqType keybase1.SeqType, 776 ignoreIfUnsupported SigIgnoreIfUnsupported, 777 me *User, 778 sigVersion SigVersion) (sig string, sigID keybase1.SigID, linkID LinkID, err error) { 779 780 switch sigVersion { 781 case KeybaseSignatureV1: 782 var sigIDBase keybase1.SigIDBase 783 sig, sigIDBase, err = signingKey.SignToString(innerLinkJSON) 784 linkID = ComputeLinkID(innerLinkJSON) 785 params := keybase1.SigIDSuffixParametersFromTypeAndVersion(string(v1LinkType), keybase1.SigVersion(sigVersion)) 786 sigID = sigIDBase.ToSigID(params) 787 case KeybaseSignatureV2: 788 prevSeqno := me.GetSigChainLastKnownSeqno() 789 prevLinkID := me.GetSigChainLastKnownID() 790 highSkip, highSkipErr := me.GetExpectedNextHighSkip(m) 791 if highSkipErr != nil { 792 return sig, sigID, linkID, highSkipErr 793 } 794 sig, sigID, linkID, err = MakeSigchainV2OuterSig( 795 m, 796 signingKey, 797 v1LinkType, 798 prevSeqno+1, 799 innerLinkJSON, 800 prevLinkID, 801 hasRevokes, 802 seqType, 803 ignoreIfUnsupported, 804 &highSkip, 805 ) 806 default: 807 err = errors.New("Invalid Signature Version") 808 } 809 return sig, sigID, linkID, err 810 } 811 812 func (u *User) RevokeKeysProof(m MetaContext, key GenericKey, kidsToRevoke []keybase1.KID, 813 deviceToDisable keybase1.DeviceID, merkleRoot *MerkleRoot) (*ProofMetadataRes, error) { 814 ret, err := ProofMetadata{ 815 Me: u, 816 LinkType: LinkTypeRevoke, 817 SigningKey: key, 818 MerkleRoot: merkleRoot, 819 }.ToJSON2(m) 820 if err != nil { 821 return nil, err 822 } 823 body := ret.J.AtKey("body") 824 revokeSection := jsonw.NewDictionary() 825 err = revokeSection.SetKey("kids", jsonw.NewWrapper(kidsToRevoke)) 826 if err != nil { 827 return nil, err 828 } 829 err = body.SetKey("revoke", revokeSection) 830 if err != nil { 831 return nil, err 832 } 833 if deviceToDisable.Exists() { 834 device, err := u.GetDevice(deviceToDisable) 835 if err != nil { 836 return nil, err 837 } 838 deviceSection := jsonw.NewDictionary() 839 err = deviceSection.SetKey("id", jsonw.NewString(deviceToDisable.String())) 840 if err != nil { 841 return nil, err 842 } 843 err = deviceSection.SetKey("type", jsonw.NewString(device.Type.String())) 844 if err != nil { 845 return nil, err 846 } 847 err = deviceSection.SetKey("status", jsonw.NewInt(DeviceStatusDefunct)) 848 if err != nil { 849 return nil, err 850 } 851 err = body.SetKey("device", deviceSection) 852 if err != nil { 853 return nil, err 854 } 855 } 856 return ret, nil 857 } 858 859 func (u *User) RevokeSigsProof(m MetaContext, key GenericKey, sigIDsToRevoke []keybase1.SigID, merkleRoot *MerkleRoot) (*ProofMetadataRes, error) { 860 ret, err := ProofMetadata{ 861 Me: u, 862 LinkType: LinkTypeRevoke, 863 SigningKey: key, 864 MerkleRoot: merkleRoot, 865 }.ToJSON2(m) 866 if err != nil { 867 return nil, err 868 } 869 body := ret.J.AtKey("body") 870 revokeSection := jsonw.NewDictionary() 871 idsArray := jsonw.NewArray(len(sigIDsToRevoke)) 872 for i, id := range sigIDsToRevoke { 873 err := idsArray.SetIndex(i, jsonw.NewString(id.String())) 874 if err != nil { 875 return nil, err 876 } 877 } 878 err = revokeSection.SetKey("sig_ids", idsArray) 879 if err != nil { 880 return nil, err 881 } 882 err = body.SetKey("revoke", revokeSection) 883 if err != nil { 884 return nil, err 885 } 886 return ret, nil 887 } 888 889 func (u *User) CryptocurrencySig(m MetaContext, key GenericKey, address string, typ CryptocurrencyType, sigToRevoke keybase1.SigID, merkleRoot *MerkleRoot, sigVersion SigVersion) (*ProofMetadataRes, error) { 890 ret, err := ProofMetadata{ 891 Me: u, 892 LinkType: LinkTypeCryptocurrency, 893 SigningKey: key, 894 MerkleRoot: merkleRoot, 895 SigVersion: sigVersion, 896 }.ToJSON2(m) 897 if err != nil { 898 return nil, err 899 } 900 body := ret.J.AtKey("body") 901 currencySection := jsonw.NewDictionary() 902 err = currencySection.SetKey("address", jsonw.NewString(address)) 903 if err != nil { 904 return nil, err 905 } 906 err = currencySection.SetKey("type", jsonw.NewString(typ.String())) 907 if err != nil { 908 return nil, err 909 } 910 entropy, err := LinkEntropy() 911 if err != nil { 912 return nil, err 913 } 914 err = currencySection.SetKey("entropy", jsonw.NewString(entropy)) 915 if err != nil { 916 return nil, err 917 } 918 err = body.SetKey("cryptocurrency", currencySection) 919 if err != nil { 920 return nil, err 921 } 922 if len(sigToRevoke) > 0 { 923 revokeSection := jsonw.NewDictionary() 924 err := revokeSection.SetKey("sig_id", jsonw.NewString(sigToRevoke.String())) 925 if err != nil { 926 return nil, err 927 } 928 err = body.SetKey("revoke", revokeSection) 929 if err != nil { 930 return nil, err 931 } 932 } 933 return ret, nil 934 } 935 936 func (u *User) UpdatePassphraseProof(m MetaContext, key GenericKey, pwh string, ppGen PassphraseGeneration, pdpka5kid string) (*jsonw.Wrapper, error) { 937 ret, err := ProofMetadata{ 938 Me: u, 939 LinkType: LinkTypeUpdatePassphrase, 940 SigningKey: key, 941 }.ToJSON(m) 942 if err != nil { 943 return nil, err 944 } 945 body := ret.AtKey("body") 946 pp := jsonw.NewDictionary() 947 err = pp.SetKey("hash", jsonw.NewString(pwh)) 948 if err != nil { 949 return nil, err 950 } 951 err = pp.SetKey("pdpka5_kid", jsonw.NewString(pdpka5kid)) 952 if err != nil { 953 return nil, err 954 } 955 err = pp.SetKey("version", jsonw.NewInt(int(ClientTriplesecVersion))) 956 if err != nil { 957 return nil, err 958 } 959 err = pp.SetKey("passphrase_generation", jsonw.NewInt(int(ppGen))) 960 if err != nil { 961 return nil, err 962 } 963 err = body.SetKey("update_passphrase_hash", pp) 964 if err != nil { 965 return nil, err 966 } 967 return ret, nil 968 } 969 970 func (u *User) UpdateEmailProof(m MetaContext, key GenericKey, newEmail string) (*jsonw.Wrapper, error) { 971 ret, err := ProofMetadata{ 972 Me: u, 973 LinkType: LinkTypeUpdateSettings, 974 SigningKey: key, 975 }.ToJSON(m) 976 if err != nil { 977 return nil, err 978 } 979 body := ret.AtKey("body") 980 settings := jsonw.NewDictionary() 981 err = settings.SetKey("email", jsonw.NewString(newEmail)) 982 if err != nil { 983 return nil, err 984 } 985 err = body.SetKey("update_settings", settings) 986 if err != nil { 987 return nil, err 988 } 989 return ret, nil 990 } 991 992 type SigMultiItem struct { 993 Sig3 *Sig3 `json:"sig3,omitempty"` 994 Sig string `json:"sig,omitempty"` 995 SigningKID keybase1.KID `json:"signing_kid"` 996 Type string `json:"type"` 997 SeqType keybase1.SeqType `json:"seq_type"` 998 SigInner string `json:"sig_inner"` 999 TeamID keybase1.TeamID `json:"team_id,omitempty"` 1000 PublicKeys *SigMultiItemPublicKeys `json:"public_keys,omitempty"` 1001 Version SigVersion `json:"version"` 1002 Expansions *jsonw.Wrapper `json:"expansions,omitempty"` 1003 } 1004 1005 type SigMultiItemPublicKeys struct { 1006 Encryption keybase1.KID `json:"encryption"` 1007 Signing keybase1.KID `json:"signing"` 1008 } 1009 1010 type Sig3 struct { 1011 Inner string `json:"i,omitempty"` 1012 Outer string `json:"o,omitempty"` 1013 Sig string `json:"s,omitempty"` 1014 } 1015 1016 // PerUserKeyProof creates a proof introducing a new per-user-key generation. 1017 // `signingKey` is the key signing in this new key. Not to be confused with the derived per-user-key signing key. 1018 func PerUserKeyProof(m MetaContext, 1019 me *User, 1020 pukSigKID keybase1.KID, 1021 pukEncKID keybase1.KID, 1022 generation keybase1.PerUserKeyGeneration, 1023 signingKey GenericKey) (*ProofMetadataRes, error) { 1024 1025 if me == nil { 1026 return nil, fmt.Errorf("missing user object for proof") 1027 } 1028 1029 ret, err := ProofMetadata{ 1030 Me: me, 1031 LinkType: LinkTypePerUserKey, 1032 SigningKey: signingKey, 1033 }.ToJSON2(m) 1034 if err != nil { 1035 return nil, err 1036 } 1037 1038 pukSection := jsonw.NewDictionary() 1039 err = pukSection.SetKey("signing_kid", jsonw.NewString(pukSigKID.String())) 1040 if err != nil { 1041 return nil, err 1042 } 1043 err = pukSection.SetKey("encryption_kid", jsonw.NewString(pukEncKID.String())) 1044 if err != nil { 1045 return nil, err 1046 } 1047 err = pukSection.SetKey("generation", jsonw.NewInt(int(generation))) 1048 if err != nil { 1049 return nil, err 1050 } 1051 // The caller is responsible for overwriting reverse_sig after signing. 1052 err = pukSection.SetKey("reverse_sig", jsonw.NewNil()) 1053 if err != nil { 1054 return nil, err 1055 } 1056 1057 body := ret.J.AtKey("body") 1058 err = body.SetKey("per_user_key", pukSection) 1059 if err != nil { 1060 return nil, err 1061 } 1062 return ret, nil 1063 } 1064 1065 type UserLinkSignature struct { 1066 Payload JSONPayload 1067 Seqno keybase1.Seqno 1068 LinkID LinkID 1069 } 1070 1071 // Make a per-user key proof with a reverse sig. 1072 // Modifies the User `me` with a sigchain bump and key delegation. 1073 // Returns a JSONPayload ready for use in "sigs" in sig/multi. 1074 func PerUserKeyProofReverseSigned(m MetaContext, me *User, perUserKeySeed PerUserKeySeed, generation keybase1.PerUserKeyGeneration, 1075 signer GenericKey) (*UserLinkSignature, error) { 1076 1077 pukSigKey, err := perUserKeySeed.DeriveSigningKey() 1078 if err != nil { 1079 return nil, err 1080 } 1081 1082 pukEncKey, err := perUserKeySeed.DeriveDHKey() 1083 if err != nil { 1084 return nil, err 1085 } 1086 1087 // Make reverse sig 1088 forward, err := PerUserKeyProof(m, me, pukSigKey.GetKID(), pukEncKey.GetKID(), generation, signer) 1089 if err != nil { 1090 return nil, err 1091 } 1092 reverseSig, _, _, err := SignJSON(forward.J, pukSigKey) 1093 if err != nil { 1094 return nil, err 1095 } 1096 1097 // Make sig 1098 jw := forward.J 1099 err = jw.SetValueAtPath("body.per_user_key.reverse_sig", jsonw.NewString(reverseSig)) 1100 if err != nil { 1101 return nil, err 1102 } 1103 sig, sigID, linkID, err := SignJSON(jw, signer) 1104 if err != nil { 1105 return nil, err 1106 } 1107 1108 // Update the user locally 1109 me.SigChainBump(linkID, sigID.ToSigIDLegacy(), false) 1110 err = me.localDelegatePerUserKey(keybase1.PerUserKey{ 1111 Gen: int(generation), 1112 Seqno: me.GetSigChainLastKnownSeqno(), 1113 SigKID: pukSigKey.GetKID(), 1114 EncKID: pukEncKey.GetKID(), 1115 SignedByKID: signer.GetKID(), 1116 }) 1117 if err != nil { 1118 return nil, err 1119 } 1120 1121 publicKeysEntry := make(JSONPayload) 1122 publicKeysEntry["signing"] = pukSigKey.GetKID().String() 1123 publicKeysEntry["encryption"] = pukEncKey.GetKID().String() 1124 1125 payload := make(JSONPayload) 1126 payload["sig"] = sig 1127 payload["signing_kid"] = signer.GetKID().String() 1128 payload["type"] = LinkTypePerUserKey 1129 payload["public_keys"] = publicKeysEntry 1130 return &UserLinkSignature{ 1131 Payload: payload, 1132 Seqno: forward.Seqno, 1133 LinkID: linkID, 1134 }, nil 1135 } 1136 1137 // StellarProof creates a proof of a stellar wallet. 1138 func StellarProof(m MetaContext, me *User, walletAddress stellar1.AccountID, 1139 signingKey GenericKey) (*ProofMetadataRes, error) { 1140 if me == nil { 1141 return nil, fmt.Errorf("missing user object for proof") 1142 } 1143 walletPubKey, err := MakeNaclSigningKeyPairFromStellarAccountID(walletAddress) 1144 if err != nil { 1145 return nil, err 1146 } 1147 walletKID := walletPubKey.GetKID() 1148 1149 ret, err := ProofMetadata{ 1150 Me: me, 1151 LinkType: LinkTypeWalletStellar, 1152 SigningKey: signingKey, 1153 SigVersion: KeybaseSignatureV2, 1154 IgnoreIfUnsupported: SigIgnoreIfUnsupported(true), 1155 }.ToJSON2(m) 1156 if err != nil { 1157 return nil, err 1158 } 1159 1160 walletSection := jsonw.NewDictionary() 1161 err = walletSection.SetKey("address", jsonw.NewString(walletAddress.String())) 1162 if err != nil { 1163 return nil, err 1164 } 1165 err = walletSection.SetKey("network", jsonw.NewString(string(WalletNetworkStellar))) 1166 if err != nil { 1167 return nil, err 1168 } 1169 1170 // Inner links can be hidden. To prevent an attacker from figuring out the 1171 // contents from the hash of the inner link, add 18 random bytes. 1172 entropy, err := LinkEntropy() 1173 if err != nil { 1174 return nil, err 1175 } 1176 err = walletSection.SetKey("entropy", jsonw.NewString(entropy)) 1177 if err != nil { 1178 return nil, err 1179 } 1180 1181 walletKeySection := jsonw.NewDictionary() 1182 err = walletKeySection.SetKey("kid", jsonw.NewString(walletKID.String())) 1183 if err != nil { 1184 return nil, err 1185 } 1186 // The caller is responsible for overwriting reverse_sig after signing. 1187 err = walletKeySection.SetKey("reverse_sig", jsonw.NewNil()) 1188 if err != nil { 1189 return nil, err 1190 } 1191 1192 body := ret.J.AtKey("body") 1193 err = body.SetKey("wallet", walletSection) 1194 if err != nil { 1195 return nil, err 1196 } 1197 err = body.SetKey("wallet_key", walletKeySection) 1198 if err != nil { 1199 return nil, err 1200 } 1201 return ret, nil 1202 } 1203 1204 // Make a stellar proof with a reverse sig. 1205 // Modifies the User `me` with a sigchain bump and key delegation. 1206 // Returns a JSONPayload ready for use in "sigs" in sig/multi. 1207 func StellarProofReverseSigned(m MetaContext, me *User, walletAddress stellar1.AccountID, 1208 stellarSigner stellar1.SecretKey, deviceSigner GenericKey) (*UserLinkSignature, error) { 1209 // Make reverse sig 1210 forward, err := StellarProof(m, me, walletAddress, deviceSigner) 1211 if err != nil { 1212 return nil, err 1213 } 1214 stellarSignerKey, err := MakeNaclSigningKeyPairFromStellarSecretKey(stellarSigner) 1215 if err != nil { 1216 return nil, err 1217 } 1218 reverseSig, _, _, err := SignJSON(forward.J, stellarSignerKey) 1219 if err != nil { 1220 return nil, err 1221 } 1222 1223 // Make sig 1224 jw := forward.J 1225 err = jw.SetValueAtPath("body.wallet_key.reverse_sig", jsonw.NewString(reverseSig)) 1226 if err != nil { 1227 return nil, err 1228 } 1229 innerJSON, err := jw.Marshal() 1230 if err != nil { 1231 return nil, err 1232 } 1233 sig, sigID, linkID, err := MakeSig( 1234 m, 1235 deviceSigner, 1236 LinkTypeWalletStellar, 1237 innerJSON, 1238 SigHasRevokes(false), 1239 keybase1.SeqType_PUBLIC, 1240 SigIgnoreIfUnsupported(true), 1241 me, 1242 KeybaseSignatureV2, 1243 ) 1244 if err != nil { 1245 return nil, err 1246 } 1247 1248 // Update the user locally 1249 me.SigChainBump(linkID, sigID, false) 1250 // TODO: do we need to locally do something like me.localDelegatePerUserKey? 1251 1252 payload := make(JSONPayload) 1253 payload["sig"] = sig 1254 payload["sig_inner"] = string(innerJSON) 1255 payload["signing_kid"] = deviceSigner.GetKID().String() 1256 payload["public_key"] = stellarSignerKey.GetKID().String() 1257 payload["type"] = LinkTypeWalletStellar 1258 return &UserLinkSignature{ 1259 Payload: payload, 1260 Seqno: forward.Seqno, 1261 LinkID: linkID, 1262 }, nil 1263 }