github.com/status-im/status-go@v1.1.0/protocol/messenger_contact_verification.go (about) 1 package protocol 2 3 import ( 4 "context" 5 "strings" 6 7 "github.com/pkg/errors" 8 "go.uber.org/zap" 9 10 "github.com/ethereum/go-ethereum/common/hexutil" 11 12 "github.com/golang/protobuf/proto" 13 14 "github.com/status-im/status-go/eth-node/crypto" 15 "github.com/status-im/status-go/eth-node/types" 16 17 "github.com/status-im/status-go/protocol/common" 18 "github.com/status-im/status-go/protocol/protobuf" 19 "github.com/status-im/status-go/protocol/requests" 20 v1protocol "github.com/status-im/status-go/protocol/v1" 21 "github.com/status-im/status-go/protocol/verification" 22 ) 23 24 const minContactVerificationMessageLen = 1 25 const maxContactVerificationMessageLen = 280 26 27 func (m *Messenger) SendContactVerificationRequest(ctx context.Context, contactID string, challenge string) (*MessengerResponse, error) { 28 if len(challenge) < minContactVerificationMessageLen || len(challenge) > maxContactVerificationMessageLen { 29 return nil, errors.New("invalid verification request challenge length") 30 } 31 32 contact, ok := m.allContacts.Load(contactID) 33 if !ok || !contact.mutual() { 34 return nil, errors.New("must be a mutual contact") 35 } 36 37 verifRequest := &verification.Request{ 38 From: common.PubkeyToHex(&m.identity.PublicKey), 39 To: contact.ID, 40 Challenge: challenge, 41 RequestStatus: verification.RequestStatusPENDING, 42 RepliedAt: 0, 43 } 44 45 chat, ok := m.allChats.Load(contactID) 46 if !ok { 47 publicKey, err := contact.PublicKey() 48 if err != nil { 49 return nil, err 50 } 51 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 52 // We don't want to show the chat to the user 53 chat.Active = false 54 } 55 56 m.allChats.Store(chat.ID, chat) 57 clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) 58 59 request := &protobuf.RequestContactVerification{ 60 Clock: clock, 61 Challenge: challenge, 62 } 63 64 encodedMessage, err := proto.Marshal(request) 65 if err != nil { 66 return nil, err 67 } 68 69 rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ 70 LocalChatID: chat.ID, 71 Payload: encodedMessage, 72 MessageType: protobuf.ApplicationMetadataMessage_REQUEST_CONTACT_VERIFICATION, 73 ResendType: common.ResendTypeDataSync, 74 }) 75 76 if err != nil { 77 return nil, err 78 } 79 80 contact.VerificationStatus = VerificationStatusVERIFYING 81 contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() 82 83 err = m.persistence.SaveContact(contact, nil) 84 if err != nil { 85 return nil, err 86 } 87 88 // We sync the contact with the other devices 89 err = m.syncContact(context.Background(), contact, m.dispatchMessage) 90 if err != nil { 91 return nil, err 92 } 93 94 m.allContacts.Store(contact.ID, contact) 95 96 verifRequest.RequestedAt = clock 97 verifRequest.ID = rawMessage.ID 98 99 err = m.verificationDatabase.SaveVerificationRequest(verifRequest) 100 if err != nil { 101 return nil, err 102 } 103 104 err = m.SyncVerificationRequest(context.Background(), verifRequest, m.dispatchMessage) 105 if err != nil { 106 return nil, err 107 } 108 109 chatMessage, err := m.createLocalContactVerificationMessage(request.Challenge, chat, rawMessage.ID, common.ContactVerificationStatePending) 110 if err != nil { 111 return nil, err 112 } 113 114 err = m.persistence.SaveMessages([]*common.Message{chatMessage}) 115 if err != nil { 116 return nil, err 117 } 118 119 response := &MessengerResponse{} 120 121 response.AddVerificationRequest(verifRequest) 122 123 err = m.createOrUpdateOutgoingContactVerificationNotification(contact, response, verifRequest, chatMessage, nil) 124 if err != nil { 125 return nil, err 126 } 127 128 response.AddMessage(chatMessage) 129 130 err = m.prepareMessages(response.messages) 131 if err != nil { 132 return nil, err 133 } 134 135 return response, nil 136 } 137 138 func (m *Messenger) GetVerificationRequestSentTo(ctx context.Context, contactID string) (*verification.Request, error) { 139 _, ok := m.allContacts.Load(contactID) 140 if !ok { 141 return nil, errors.New("contact not found") 142 } 143 144 return m.verificationDatabase.GetLatestVerificationRequestSentTo(contactID) 145 } 146 147 func (m *Messenger) GetReceivedVerificationRequests(ctx context.Context) ([]*verification.Request, error) { 148 myPubKey := hexutil.Encode(crypto.FromECDSAPub(&m.identity.PublicKey)) 149 return m.verificationDatabase.GetReceivedVerificationRequests(myPubKey) 150 } 151 152 func (m *Messenger) CancelVerificationRequest(ctx context.Context, id string) (*MessengerResponse, error) { 153 verifRequest, err := m.verificationDatabase.GetVerificationRequest(id) 154 if err != nil { 155 return nil, err 156 } 157 158 if verifRequest == nil { 159 m.logger.Error("could not find verification request with id", zap.String("id", id)) 160 return nil, verification.ErrVerificationRequestNotFound 161 } 162 163 if verifRequest.From != common.PubkeyToHex(&m.identity.PublicKey) { 164 return nil, errors.New("Can cancel only outgoing contact request") 165 } 166 167 contactID := verifRequest.To 168 contact, ok := m.allContacts.Load(contactID) 169 if !ok || !contact.mutual() { 170 return nil, errors.New("Can't find contact for canceling verification request") 171 } 172 173 if verifRequest.RequestStatus != verification.RequestStatusPENDING { 174 return nil, errors.New("can cancel only pending verification request") 175 } 176 177 verifRequest.RequestStatus = verification.RequestStatusCANCELED 178 err = m.verificationDatabase.SaveVerificationRequest(verifRequest) 179 if err != nil { 180 return nil, err 181 } 182 contact.VerificationStatus = VerificationStatusUNVERIFIED 183 contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() 184 185 err = m.persistence.SaveContact(contact, nil) 186 if err != nil { 187 return nil, err 188 } 189 190 // We sync the contact with the other devices 191 err = m.syncContact(context.Background(), contact, m.dispatchMessage) 192 if err != nil { 193 return nil, err 194 } 195 196 m.allContacts.Store(contact.ID, contact) 197 198 // NOTE: does we need it? 199 chat, ok := m.allChats.Load(verifRequest.To) 200 if !ok { 201 publicKey, err := contact.PublicKey() 202 if err != nil { 203 return nil, err 204 } 205 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 206 // We don't want to show the chat to the user 207 chat.Active = false 208 } 209 210 m.allChats.Store(chat.ID, chat) 211 clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) 212 213 response := &MessengerResponse{} 214 215 response.AddVerificationRequest(verifRequest) 216 217 response.AddContact(contact) 218 219 err = m.SyncVerificationRequest(context.Background(), verifRequest, m.dispatchMessage) 220 if err != nil { 221 return nil, err 222 } 223 224 request := &protobuf.CancelContactVerification{ 225 Id: id, 226 Clock: clock, 227 } 228 229 encodedMessage, err := proto.Marshal(request) 230 if err != nil { 231 return nil, err 232 } 233 234 _, err = m.dispatchMessage(ctx, common.RawMessage{ 235 LocalChatID: chat.ID, 236 Payload: encodedMessage, 237 MessageType: protobuf.ApplicationMetadataMessage_CANCEL_CONTACT_VERIFICATION, 238 ResendType: common.ResendTypeDataSync, 239 }) 240 241 if err != nil { 242 return nil, err 243 } 244 245 notification, err := m.persistence.GetActivityCenterNotificationByID(types.FromHex(id)) 246 if err != nil { 247 return nil, err 248 } 249 250 if notification != nil { 251 notification.ContactVerificationStatus = verification.RequestStatusCANCELED 252 message := notification.Message 253 message.ContactVerificationState = common.ContactVerificationStateCanceled 254 notification.Read = true 255 notification.UpdatedAt = m.GetCurrentTimeInMillis() 256 257 err = m.addActivityCenterNotification(response, notification, m.syncActivityCenterReadByIDs) 258 if err != nil { 259 m.logger.Error("failed to save notification", zap.Error(err)) 260 return nil, err 261 } 262 } 263 264 return response, nil 265 } 266 267 func (m *Messenger) AcceptContactVerificationRequest(ctx context.Context, id string, response string) (*MessengerResponse, error) { 268 verifRequest, err := m.verificationDatabase.GetVerificationRequest(id) 269 if err != nil { 270 return nil, err 271 } 272 273 if verifRequest == nil { 274 m.logger.Error("could not find verification request with id", zap.String("id", id)) 275 return nil, verification.ErrVerificationRequestNotFound 276 } 277 278 contactID := verifRequest.From 279 280 contact, ok := m.allContacts.Load(contactID) 281 if !ok || !contact.mutual() { 282 return nil, errors.New("must be a mutual contact") 283 } 284 285 chat, ok := m.allChats.Load(contactID) 286 if !ok { 287 publicKey, err := contact.PublicKey() 288 if err != nil { 289 return nil, err 290 } 291 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 292 // We don't want to show the chat to the user 293 chat.Active = false 294 } 295 296 m.allChats.Store(chat.ID, chat) 297 clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) 298 299 err = m.verificationDatabase.AcceptContactVerificationRequest(id, response) 300 if err != nil { 301 return nil, err 302 } 303 304 verifRequest, err = m.verificationDatabase.GetVerificationRequest(id) 305 if err != nil { 306 return nil, err 307 } 308 309 err = m.SyncVerificationRequest(context.Background(), verifRequest, m.dispatchMessage) 310 if err != nil { 311 return nil, err 312 } 313 314 request := &protobuf.AcceptContactVerification{ 315 Clock: clock, 316 Id: verifRequest.ID, 317 Response: response, 318 } 319 320 encodedMessage, err := proto.Marshal(request) 321 if err != nil { 322 return nil, err 323 } 324 325 rawMessage, err := m.dispatchMessage(ctx, common.RawMessage{ 326 LocalChatID: chat.ID, 327 Payload: encodedMessage, 328 MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_VERIFICATION, 329 ResendType: common.ResendTypeDataSync, 330 }) 331 332 if err != nil { 333 return nil, err 334 } 335 336 // Pull one from the db if there 337 notification, err := m.persistence.GetActivityCenterNotificationByID(types.FromHex(id)) 338 if err != nil { 339 return nil, err 340 } 341 resp := &MessengerResponse{} 342 343 resp.AddVerificationRequest(verifRequest) 344 345 replyMessage, err := m.createLocalContactVerificationMessage(response, chat, rawMessage.ID, common.ContactVerificationStateAccepted) 346 if err != nil { 347 return nil, err 348 } 349 350 err = m.persistence.SaveMessages([]*common.Message{replyMessage}) 351 if err != nil { 352 return nil, err 353 } 354 355 resp.AddMessage(replyMessage) 356 357 if notification != nil { 358 // TODO: Should we update only the message or only the notification or both? 359 360 notification.ContactVerificationStatus = verification.RequestStatusACCEPTED 361 message := notification.Message 362 message.ContactVerificationState = common.ContactVerificationStateAccepted 363 notification.ReplyMessage = replyMessage 364 notification.Read = true 365 notification.Accepted = true 366 notification.UpdatedAt = m.GetCurrentTimeInMillis() 367 err = m.addActivityCenterNotification(resp, notification, m.syncActivityCenterAcceptedByIDs) 368 if err != nil { 369 m.logger.Error("failed to save notification", zap.Error(err)) 370 return nil, err 371 } 372 resp.AddMessage(message) // <=== wasn't typo? 373 } 374 375 return resp, nil 376 } 377 378 func (m *Messenger) VerifiedTrusted(ctx context.Context, request *requests.VerifiedTrusted) (*MessengerResponse, error) { 379 err := request.Validate() 380 if err != nil { 381 return nil, err 382 } 383 // Pull one from the db if there 384 notification, err := m.persistence.GetActivityCenterNotificationByID(request.ID) 385 if err != nil { 386 return nil, err 387 } 388 389 if notification == nil || notification.ReplyMessage == nil { 390 return nil, errors.New("could not find notification") 391 } 392 393 contactID := notification.ReplyMessage.From 394 395 contact, ok := m.allContacts.Load(contactID) 396 if !ok || !contact.mutual() { 397 return nil, errors.New("must be a mutual contact") 398 } 399 400 err = m.setTrustStatusForContact(context.Background(), contactID, verification.TrustStatusTRUSTED) 401 402 if err != nil { 403 return nil, err 404 } 405 406 contact.VerificationStatus = VerificationStatusVERIFIED 407 contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() 408 err = m.persistence.SaveContact(contact, nil) 409 if err != nil { 410 return nil, err 411 } 412 413 chat, ok := m.allChats.Load(contactID) 414 clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) 415 if !ok { 416 publicKey, err := contact.PublicKey() 417 if err != nil { 418 return nil, err 419 } 420 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 421 // We don't want to show the chat to the user 422 chat.Active = false 423 } 424 425 verifRequest, err := m.verificationDatabase.GetLatestVerificationRequestSentTo(contactID) 426 if err != nil { 427 return nil, err 428 } 429 430 if verifRequest == nil { 431 return nil, errors.New("no contact verification found") 432 } 433 434 verifRequest.RequestStatus = verification.RequestStatusTRUSTED 435 verifRequest.RepliedAt = clock 436 err = m.verificationDatabase.SaveVerificationRequest(verifRequest) 437 if err != nil { 438 return nil, err 439 } 440 441 err = m.SyncVerificationRequest(context.Background(), verifRequest, m.dispatchMessage) 442 if err != nil { 443 return nil, err 444 } 445 446 // We sync the contact with the other devices 447 err = m.syncContact(context.Background(), contact, m.dispatchMessage) 448 if err != nil { 449 return nil, err 450 } 451 452 // Dispatch profile message to save a contact to the encrypted profile part 453 err = m.DispatchProfileShowcase() 454 if err != nil { 455 return nil, err 456 } 457 458 response := &MessengerResponse{} 459 460 notification.ContactVerificationStatus = verification.RequestStatusTRUSTED 461 notification.Message.ContactVerificationState = common.ContactVerificationStateTrusted 462 notification.Read = true 463 notification.Accepted = true 464 notification.UpdatedAt = m.GetCurrentTimeInMillis() 465 466 err = m.addActivityCenterNotification(response, notification, m.syncActivityCenterAcceptedByIDs) 467 if err != nil { 468 m.logger.Error("failed to save notification", zap.Error(err)) 469 return nil, err 470 } 471 472 msg, err := m.persistence.MessageByID(notification.ReplyMessage.ID) 473 if err != nil { 474 return nil, err 475 } 476 msg.ContactVerificationState = common.ContactVerificationStateTrusted 477 478 err = m.persistence.SaveMessages([]*common.Message{msg}) 479 if err != nil { 480 return nil, err 481 } 482 response.AddMessage(msg) 483 484 response.AddContact(contact) 485 486 return response, nil 487 } 488 489 func (m *Messenger) VerifiedUntrustworthy(ctx context.Context, request *requests.VerifiedUntrustworthy) (*MessengerResponse, error) { 490 if err := request.Validate(); err != nil { 491 return nil, err 492 } 493 494 // Pull one from the db if there 495 notification, err := m.persistence.GetActivityCenterNotificationByID(request.ID) 496 if err != nil { 497 return nil, err 498 } 499 500 if notification == nil || notification.ReplyMessage == nil { 501 return nil, errors.New("could not find notification") 502 } 503 504 contactID := notification.ReplyMessage.From 505 506 err = m.setTrustStatusForContact(context.Background(), contactID, verification.TrustStatusUNTRUSTWORTHY) 507 if err != nil { 508 return nil, err 509 } 510 511 contact, err := m.setContactVerificationStatus(contactID, VerificationStatusVERIFIED) 512 if err != nil { 513 return nil, err 514 } 515 516 chat, ok := m.allChats.Load(contactID) 517 clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) 518 if !ok { 519 publicKey, err := contact.PublicKey() 520 if err != nil { 521 return nil, err 522 } 523 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 524 // We don't want to show the chat to the user 525 chat.Active = false 526 } 527 528 verifRequest, err := m.verificationDatabase.GetLatestVerificationRequestSentTo(contactID) 529 if err != nil { 530 return nil, err 531 } 532 533 if verifRequest == nil { 534 return nil, errors.New("no contact verification found") 535 } 536 537 verifRequest.RequestStatus = verification.RequestStatusUNTRUSTWORTHY 538 verifRequest.RepliedAt = clock 539 err = m.verificationDatabase.SaveVerificationRequest(verifRequest) 540 if err != nil { 541 return nil, err 542 } 543 544 err = m.SyncVerificationRequest(context.Background(), verifRequest, m.dispatchMessage) 545 if err != nil { 546 return nil, err 547 } 548 549 response := &MessengerResponse{} 550 551 notification.ContactVerificationStatus = verification.RequestStatusUNTRUSTWORTHY 552 notification.Message.ContactVerificationState = common.ContactVerificationStateUntrustworthy 553 notification.Read = true 554 notification.Accepted = true 555 notification.UpdatedAt = m.GetCurrentTimeInMillis() 556 557 err = m.addActivityCenterNotification(response, notification, m.syncActivityCenterAcceptedByIDs) 558 if err != nil { 559 m.logger.Error("failed to save notification", zap.Error(err)) 560 return nil, err 561 } 562 563 msg, err := m.persistence.MessageByID(notification.ReplyMessage.ID) 564 if err != nil { 565 return nil, err 566 } 567 msg.ContactVerificationState = common.ContactVerificationStateUntrustworthy 568 569 err = m.persistence.SaveMessages([]*common.Message{msg}) 570 if err != nil { 571 return nil, err 572 } 573 574 response.AddMessage(msg) 575 576 return response, nil 577 } 578 579 func (m *Messenger) DeclineContactVerificationRequest(ctx context.Context, id string) (*MessengerResponse, error) { 580 verifRequest, err := m.verificationDatabase.GetVerificationRequest(id) 581 if err != nil { 582 return nil, err 583 } 584 585 if verifRequest == nil { 586 m.logger.Error("could not find verification request with id", zap.String("id", id)) 587 return nil, verification.ErrVerificationRequestNotFound 588 } 589 590 contact, ok := m.allContacts.Load(verifRequest.From) 591 if !ok || !contact.mutual() { 592 return nil, errors.New("must be a mutual contact") 593 } 594 contactID := verifRequest.From 595 contact, err = m.setContactVerificationStatus(contactID, VerificationStatusVERIFIED) 596 597 if err != nil { 598 return nil, err 599 } 600 601 if verifRequest == nil { 602 return nil, errors.New("no contact verification found") 603 } 604 605 chat, ok := m.allChats.Load(verifRequest.From) 606 if !ok { 607 publicKey, err := contact.PublicKey() 608 if err != nil { 609 return nil, err 610 } 611 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 612 // We don't want to show the chat to the user 613 chat.Active = false 614 } 615 616 m.allChats.Store(chat.ID, chat) 617 clock, _ := chat.NextClockAndTimestamp(m.getTimesource()) 618 619 verifRequest.RequestStatus = verification.RequestStatusDECLINED 620 verifRequest.RepliedAt = clock 621 err = m.verificationDatabase.SaveVerificationRequest(verifRequest) 622 if err != nil { 623 return nil, err 624 } 625 626 response := &MessengerResponse{} 627 628 response.AddVerificationRequest(verifRequest) 629 630 err = m.SyncVerificationRequest(context.Background(), verifRequest, m.dispatchMessage) 631 if err != nil { 632 return nil, err 633 } 634 635 request := &protobuf.DeclineContactVerification{ 636 Id: id, 637 Clock: clock, 638 } 639 640 encodedMessage, err := proto.Marshal(request) 641 if err != nil { 642 return nil, err 643 } 644 645 _, err = m.dispatchMessage(ctx, common.RawMessage{ 646 LocalChatID: chat.ID, 647 Payload: encodedMessage, 648 MessageType: protobuf.ApplicationMetadataMessage_DECLINE_CONTACT_VERIFICATION, 649 ResendType: common.ResendTypeDataSync, 650 }) 651 652 if err != nil { 653 return nil, err 654 } 655 656 err = m.verificationDatabase.DeclineContactVerificationRequest(id) 657 if err != nil { 658 return nil, err 659 } 660 661 notification, err := m.persistence.GetActivityCenterNotificationByID(types.FromHex(id)) 662 if err != nil { 663 return nil, err 664 } 665 666 if notification != nil { 667 notification.ContactVerificationStatus = verification.RequestStatusDECLINED 668 notification.Read = true 669 notification.Dismissed = true 670 notification.UpdatedAt = m.GetCurrentTimeInMillis() 671 672 message := notification.Message 673 message.ContactVerificationState = common.ContactVerificationStateDeclined 674 675 err = m.addActivityCenterNotification(response, notification, m.syncActivityCenterDismissedByIDs) 676 if err != nil { 677 m.logger.Error("failed to save notification", zap.Error(err)) 678 return nil, err 679 } 680 response.AddMessage(message) 681 } 682 683 return response, nil 684 } 685 686 func (m *Messenger) setContactVerificationStatus(contactID string, verificationStatus VerificationStatus) (*Contact, error) { 687 contact, ok := m.allContacts.Load(contactID) 688 if !ok || !contact.mutual() { 689 return nil, errors.New("must be a mutual contact") 690 } 691 692 contact.VerificationStatus = verificationStatus 693 contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() 694 695 err := m.persistence.SaveContact(contact, nil) 696 if err != nil { 697 return nil, err 698 } 699 700 err = m.syncContact(context.Background(), contact, m.dispatchMessage) 701 if err != nil { 702 return nil, err 703 } 704 705 m.allContacts.Store(contact.ID, contact) 706 707 // Dispatch profile message to save a contact to the encrypted profile part 708 err = m.DispatchProfileShowcase() 709 if err != nil { 710 return nil, err 711 } 712 713 return contact, nil 714 } 715 716 func (m *Messenger) setTrustStatusForContact(ctx context.Context, contactID string, trustStatus verification.TrustStatus) error { 717 currentTime := m.getTimesource().GetCurrentTime() 718 719 err := m.verificationDatabase.SetTrustStatus(contactID, trustStatus, currentTime) 720 if err != nil { 721 return err 722 } 723 724 return m.SyncTrustedUser(ctx, contactID, trustStatus, m.dispatchMessage) 725 } 726 727 func (m *Messenger) MarkAsTrusted(ctx context.Context, contactID string) error { 728 return m.setTrustStatusForContact(ctx, contactID, verification.TrustStatusTRUSTED) 729 } 730 731 func (m *Messenger) MarkAsUntrustworthy(ctx context.Context, contactID string) error { 732 return m.setTrustStatusForContact(ctx, contactID, verification.TrustStatusUNTRUSTWORTHY) 733 } 734 735 func (m *Messenger) RemoveTrustStatus(ctx context.Context, contactID string) error { 736 return m.setTrustStatusForContact(ctx, contactID, verification.TrustStatusUNKNOWN) 737 } 738 739 func (m *Messenger) RemoveTrustVerificationStatus(ctx context.Context, contactID string) (*MessengerResponse, error) { 740 err := m.setTrustStatusForContact(ctx, contactID, verification.TrustStatusUNKNOWN) 741 if err != nil { 742 return nil, err 743 } 744 745 contact, err := m.setContactVerificationStatus(contactID, VerificationStatusUNVERIFIED) 746 if err != nil { 747 return nil, err 748 } 749 750 response := &MessengerResponse{} 751 response.AddContact(contact) 752 753 return response, nil 754 } 755 756 func (m *Messenger) GetTrustStatus(contactID string) (verification.TrustStatus, error) { 757 return m.verificationDatabase.GetTrustStatus(contactID) 758 } 759 760 func ValidateContactVerificationRequest(request *protobuf.RequestContactVerification) error { 761 challengeLen := len(strings.TrimSpace(request.Challenge)) 762 if challengeLen < minContactVerificationMessageLen || challengeLen > maxContactVerificationMessageLen { 763 return errors.New("invalid verification request challenge length") 764 } 765 766 return nil 767 } 768 769 func (m *Messenger) HandleRequestContactVerification(state *ReceivedMessageState, request *protobuf.RequestContactVerification, statusMessage *v1protocol.StatusMessage) error { 770 if err := ValidateContactVerificationRequest(request); err != nil { 771 m.logger.Debug("Invalid verification request", zap.Error(err)) 772 return err 773 } 774 775 id := state.CurrentMessageState.MessageID 776 777 if common.IsPubKeyEqual(state.CurrentMessageState.PublicKey, &m.identity.PublicKey) { 778 return nil // Is ours, do nothing 779 } 780 781 myPubKey := hexutil.Encode(crypto.FromECDSAPub(&m.identity.PublicKey)) 782 contactID := hexutil.Encode(crypto.FromECDSAPub(state.CurrentMessageState.PublicKey)) 783 784 contact := state.CurrentMessageState.Contact 785 if !contact.mutual() { 786 m.logger.Debug("Received a verification request for a non added mutual contact", zap.String("contactID", contactID)) 787 return errors.New("must be a mutual contact") 788 } 789 790 persistedVR, err := m.verificationDatabase.GetVerificationRequest(id) 791 if err != nil { 792 m.logger.Debug("Error obtaining verification request", zap.Error(err)) 793 return err 794 } 795 796 if persistedVR != nil && persistedVR.RequestedAt > request.Clock { 797 return nil // older message, ignore it 798 } 799 800 if persistedVR == nil { 801 // This is a new verification request, and we have not received its acceptance/decline before 802 persistedVR = &verification.Request{} 803 persistedVR.ID = id 804 persistedVR.From = contactID 805 persistedVR.To = myPubKey 806 persistedVR.RequestStatus = verification.RequestStatusPENDING 807 } 808 809 if persistedVR.From != contactID { 810 return errors.New("mismatch contactID and ID") 811 } 812 813 persistedVR.Challenge = request.Challenge 814 persistedVR.RequestedAt = request.Clock 815 816 err = m.verificationDatabase.SaveVerificationRequest(persistedVR) 817 if err != nil { 818 m.logger.Debug("Error storing verification request", zap.Error(err)) 819 return err 820 } 821 m.logger.Info("SAVED", zap.String("id", persistedVR.ID)) 822 823 err = m.SyncVerificationRequest(context.Background(), persistedVR, m.dispatchMessage) 824 if err != nil { 825 return err 826 } 827 828 chat, ok := m.allChats.Load(contactID) 829 if !ok { 830 publicKey, err := contact.PublicKey() 831 if err != nil { 832 return err 833 } 834 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 835 // We don't want to show the chat to the user 836 chat.Active = false 837 } 838 839 m.allChats.Store(chat.ID, chat) 840 841 chatMessage, err := m.createContactVerificationMessage(request.Challenge, chat, state, common.ContactVerificationStatePending) 842 if err != nil { 843 return err 844 } 845 846 state.Response.AddMessage(chatMessage) 847 848 state.AllVerificationRequests = append(state.AllVerificationRequests, persistedVR) 849 850 return m.createOrUpdateIncomingContactVerificationNotification(contact, state, persistedVR, chatMessage, nil) 851 } 852 853 func ValidateAcceptContactVerification(request *protobuf.AcceptContactVerification) error { 854 responseLen := len(strings.TrimSpace(request.Response)) 855 if responseLen < minContactVerificationMessageLen || responseLen > maxContactVerificationMessageLen { 856 return errors.New("invalid verification request response length") 857 } 858 859 return nil 860 } 861 862 func (m *Messenger) HandleAcceptContactVerification(state *ReceivedMessageState, request *protobuf.AcceptContactVerification, statusMessage *v1protocol.StatusMessage) error { 863 if err := ValidateAcceptContactVerification(request); err != nil { 864 m.logger.Debug("Invalid AcceptContactVerification", zap.Error(err)) 865 return err 866 } 867 868 if common.IsPubKeyEqual(state.CurrentMessageState.PublicKey, &m.identity.PublicKey) { 869 return nil // Is ours, do nothing 870 } 871 872 myPubKey := hexutil.Encode(crypto.FromECDSAPub(&m.identity.PublicKey)) 873 contactID := hexutil.Encode(crypto.FromECDSAPub(state.CurrentMessageState.PublicKey)) 874 875 contact := state.CurrentMessageState.Contact 876 if !contact.mutual() { 877 m.logger.Debug("Received a verification response for a non mutual contact", zap.String("contactID", contactID)) 878 return errors.New("must be a mutual contact") 879 } 880 881 persistedVR, err := m.verificationDatabase.GetVerificationRequest(request.Id) 882 if err != nil { 883 m.logger.Debug("Error obtaining verification request", zap.Error(err)) 884 return err 885 } 886 887 if persistedVR == nil { 888 // This is a response for which we have not received its request before 889 persistedVR = &verification.Request{} 890 persistedVR.ID = request.Id 891 persistedVR.From = contactID 892 persistedVR.To = myPubKey 893 } else { 894 if persistedVR.RepliedAt > request.Clock { 895 return nil // older message, ignore it 896 } 897 898 if persistedVR.RequestStatus == verification.RequestStatusCANCELED { 899 return nil // Do nothing, We have already cancelled the verification request 900 } 901 } 902 903 persistedVR.RequestStatus = verification.RequestStatusACCEPTED 904 persistedVR.Response = request.Response 905 persistedVR.RepliedAt = request.Clock 906 907 err = m.verificationDatabase.SaveVerificationRequest(persistedVR) 908 if err != nil { 909 m.logger.Debug("Error storing verification request", zap.Error(err)) 910 return err 911 } 912 913 err = m.SyncVerificationRequest(context.Background(), persistedVR, m.dispatchMessage) 914 if err != nil { 915 return err 916 } 917 918 chat, ok := m.allChats.Load(contactID) 919 if !ok { 920 publicKey, err := contact.PublicKey() 921 if err != nil { 922 return err 923 } 924 chat = OneToOneFromPublicKey(publicKey, m.getTimesource()) 925 // We don't want to show the chat to the user 926 chat.Active = false 927 } 928 929 m.allChats.Store(chat.ID, chat) 930 931 chatMessage, err := m.createContactVerificationMessage(request.Response, chat, state, common.ContactVerificationStateAccepted) 932 if err != nil { 933 return err 934 } 935 936 state.Response.AddMessage(chatMessage) 937 938 msg, err := m.persistence.MessageByID(request.Id) 939 if err != nil { 940 return err 941 } 942 msg.ContactVerificationState = common.ContactVerificationStateAccepted 943 944 state.Response.AddMessage(msg) 945 946 err = m.createOrUpdateOutgoingContactVerificationNotification(contact, state.Response, persistedVR, msg, chatMessage) 947 if err != nil { 948 return err 949 } 950 951 state.AllVerificationRequests = append(state.AllVerificationRequests, persistedVR) 952 953 return nil 954 } 955 956 func (m *Messenger) HandleDeclineContactVerification(state *ReceivedMessageState, request *protobuf.DeclineContactVerification, statusMessage *v1protocol.StatusMessage) error { 957 if common.IsPubKeyEqual(state.CurrentMessageState.PublicKey, &m.identity.PublicKey) { 958 return nil // Is ours, do nothing 959 } 960 961 myPubKey := hexutil.Encode(crypto.FromECDSAPub(&m.identity.PublicKey)) 962 contactID := hexutil.Encode(crypto.FromECDSAPub(state.CurrentMessageState.PublicKey)) 963 964 contact := state.CurrentMessageState.Contact 965 if !contact.mutual() { 966 m.logger.Debug("Received a verification decline for a non mutual contact", zap.String("contactID", contactID)) 967 return errors.New("must be a mutual contact") 968 } 969 970 persistedVR, err := m.verificationDatabase.GetVerificationRequest(request.Id) 971 if err != nil { 972 m.logger.Debug("Error obtaining verification request", zap.Error(err)) 973 return err 974 } 975 976 if persistedVR != nil && persistedVR.RepliedAt > request.Clock { 977 return nil // older message, ignore it 978 } 979 980 if persistedVR.RequestStatus == verification.RequestStatusCANCELED { 981 return nil // Do nothing, We have already cancelled the verification request 982 } 983 984 contact.VerificationStatus = VerificationStatusUNVERIFIED 985 contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() 986 987 err = m.persistence.SaveContact(contact, nil) 988 if err != nil { 989 return err 990 } 991 992 // We sync the contact with the other devices 993 err = m.syncContact(context.Background(), contact, m.dispatchMessage) 994 if err != nil { 995 return err 996 } 997 998 m.allContacts.Store(contact.ID, contact) 999 1000 state.Response.AddContact(contact) 1001 1002 if persistedVR == nil { 1003 // This is a response for which we have not received its request before 1004 persistedVR = &verification.Request{} 1005 persistedVR.From = contactID 1006 persistedVR.To = myPubKey 1007 } 1008 1009 persistedVR.RequestStatus = verification.RequestStatusDECLINED 1010 persistedVR.RepliedAt = request.Clock 1011 1012 err = m.verificationDatabase.SaveVerificationRequest(persistedVR) 1013 if err != nil { 1014 m.logger.Debug("Error storing verification request", zap.Error(err)) 1015 return err 1016 } 1017 1018 err = m.SyncVerificationRequest(context.Background(), persistedVR, m.dispatchMessage) 1019 if err != nil { 1020 return err 1021 } 1022 1023 state.AllVerificationRequests = append(state.AllVerificationRequests, persistedVR) 1024 1025 msg, err := m.persistence.MessageByID(request.Id) 1026 if err != nil { 1027 return err 1028 } 1029 1030 if msg != nil { 1031 msg.ContactVerificationState = common.ContactVerificationStateDeclined 1032 state.Response.AddMessage(msg) 1033 } 1034 1035 return m.createOrUpdateOutgoingContactVerificationNotification(contact, state.Response, persistedVR, msg, nil) 1036 } 1037 1038 func (m *Messenger) HandleCancelContactVerification(state *ReceivedMessageState, request *protobuf.CancelContactVerification, statusMessage *v1protocol.StatusMessage) error { 1039 myPubKey := hexutil.Encode(crypto.FromECDSAPub(&m.identity.PublicKey)) 1040 contactID := hexutil.Encode(crypto.FromECDSAPub(state.CurrentMessageState.PublicKey)) 1041 1042 contact := state.CurrentMessageState.Contact 1043 1044 persistedVR, err := m.verificationDatabase.GetVerificationRequest(request.Id) 1045 if err != nil { 1046 m.logger.Debug("Error obtaining verification request", zap.Error(err)) 1047 return err 1048 } 1049 1050 if persistedVR != nil && persistedVR.RequestStatus != verification.RequestStatusPENDING { 1051 m.logger.Debug("Only pending verification request can be canceled", zap.String("contactID", contactID)) 1052 return errors.New("must be a pending verification request") 1053 } 1054 1055 if persistedVR == nil { 1056 // This is a response for which we have not received its request before 1057 persistedVR = &verification.Request{} 1058 persistedVR.From = contactID 1059 persistedVR.To = myPubKey 1060 } 1061 1062 persistedVR.RequestStatus = verification.RequestStatusCANCELED 1063 persistedVR.RepliedAt = request.Clock 1064 1065 err = m.verificationDatabase.SaveVerificationRequest(persistedVR) 1066 if err != nil { 1067 m.logger.Debug("Error storing verification request", zap.Error(err)) 1068 return err 1069 } 1070 1071 err = m.SyncVerificationRequest(context.Background(), persistedVR, m.dispatchMessage) 1072 if err != nil { 1073 return err 1074 } 1075 1076 state.AllVerificationRequests = append(state.AllVerificationRequests, persistedVR) 1077 1078 msg, err := m.persistence.MessageByID(request.Id) 1079 if err != nil { 1080 return err 1081 } 1082 1083 if msg != nil { 1084 msg.ContactVerificationState = common.ContactVerificationStateCanceled 1085 state.Response.AddMessage(msg) 1086 } 1087 1088 return m.createOrUpdateIncomingContactVerificationNotification(contact, state, persistedVR, msg, nil) 1089 } 1090 1091 func (m *Messenger) GetLatestVerificationRequestFrom(contactID string) (*verification.Request, error) { 1092 return m.verificationDatabase.GetLatestVerificationRequestFrom(contactID) 1093 } 1094 1095 func (m *Messenger) createOrUpdateOutgoingContactVerificationNotification(contact *Contact, response *MessengerResponse, vr *verification.Request, chatMessage *common.Message, replyMessage *common.Message) error { 1096 notification := &ActivityCenterNotification{ 1097 ID: types.FromHex(vr.ID), 1098 Name: contact.PrimaryName(), 1099 Type: ActivityCenterNotificationTypeContactVerification, 1100 Author: chatMessage.From, 1101 Message: chatMessage, 1102 ReplyMessage: replyMessage, 1103 Timestamp: chatMessage.WhisperTimestamp, 1104 ChatID: contact.ID, 1105 ContactVerificationStatus: vr.RequestStatus, 1106 Read: vr.RequestStatus != verification.RequestStatusACCEPTED, // Mark as Unread Accepted notification because we are waiting for the asnwer 1107 Accepted: vr.RequestStatus == verification.RequestStatusTRUSTED || vr.RequestStatus == verification.RequestStatusUNTRUSTWORTHY, 1108 Dismissed: vr.RequestStatus == verification.RequestStatusDECLINED, 1109 UpdatedAt: m.GetCurrentTimeInMillis(), 1110 } 1111 1112 return m.addActivityCenterNotification(response, notification, nil) 1113 } 1114 1115 func (m *Messenger) createOrUpdateIncomingContactVerificationNotification(contact *Contact, messageState *ReceivedMessageState, vr *verification.Request, chatMessage *common.Message, replyMessage *common.Message) error { 1116 notification := &ActivityCenterNotification{ 1117 ID: types.FromHex(vr.ID), 1118 Name: contact.PrimaryName(), 1119 Type: ActivityCenterNotificationTypeContactVerification, 1120 Author: messageState.CurrentMessageState.Contact.ID, 1121 Message: chatMessage, 1122 ReplyMessage: replyMessage, 1123 Timestamp: messageState.CurrentMessageState.WhisperTimestamp, 1124 ChatID: contact.ID, 1125 ContactVerificationStatus: vr.RequestStatus, 1126 Read: vr.RequestStatus != verification.RequestStatusPENDING, // Unread only for pending incomming 1127 Accepted: vr.RequestStatus == verification.RequestStatusACCEPTED || vr.RequestStatus == verification.RequestStatusTRUSTED || vr.RequestStatus == verification.RequestStatusUNTRUSTWORTHY, 1128 Dismissed: vr.RequestStatus == verification.RequestStatusDECLINED, 1129 UpdatedAt: m.GetCurrentTimeInMillis(), 1130 } 1131 1132 return m.addActivityCenterNotification(messageState.Response, notification, nil) 1133 } 1134 1135 func (m *Messenger) createContactVerificationMessage(challenge string, chat *Chat, state *ReceivedMessageState, verificationStatus common.ContactVerificationState) (*common.Message, error) { 1136 chatMessage := common.NewMessage() 1137 chatMessage.ID = state.CurrentMessageState.MessageID 1138 chatMessage.From = state.CurrentMessageState.Contact.ID 1139 chatMessage.Alias = state.CurrentMessageState.Contact.Alias 1140 chatMessage.SigPubKey = state.CurrentMessageState.PublicKey 1141 chatMessage.Identicon = state.CurrentMessageState.Contact.Identicon 1142 chatMessage.WhisperTimestamp = state.CurrentMessageState.WhisperTimestamp 1143 1144 chatMessage.ChatId = chat.ID 1145 chatMessage.Text = challenge 1146 chatMessage.ContentType = protobuf.ChatMessage_IDENTITY_VERIFICATION 1147 chatMessage.ContactVerificationState = verificationStatus 1148 1149 err := chatMessage.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey)) 1150 if err != nil { 1151 return nil, err 1152 } 1153 return chatMessage, nil 1154 } 1155 1156 func (m *Messenger) createLocalContactVerificationMessage(challenge string, chat *Chat, id string, status common.ContactVerificationState) (*common.Message, error) { 1157 1158 chatMessage := common.NewMessage() 1159 chatMessage.ID = id 1160 err := extendMessageFromChat(chatMessage, chat, &m.identity.PublicKey, m.getTimesource()) 1161 if err != nil { 1162 return nil, err 1163 } 1164 1165 chatMessage.ChatId = chat.ID 1166 chatMessage.Text = challenge 1167 chatMessage.ContentType = protobuf.ChatMessage_IDENTITY_VERIFICATION 1168 chatMessage.ContactVerificationState = status 1169 err = extendMessageFromChat(chatMessage, chat, &m.identity.PublicKey, m.getTimesource()) 1170 if err != nil { 1171 return nil, err 1172 } 1173 1174 err = chatMessage.PrepareContent(common.PubkeyToHex(&m.identity.PublicKey)) 1175 if err != nil { 1176 return nil, err 1177 } 1178 return chatMessage, nil 1179 }