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  }