512 lines
21 KiB
Go
512 lines
21 KiB
Go
|
|
// peerChatKeys provides functions to store user chat keys
|
|
|
|
package peerChatKeys
|
|
|
|
// We need to keep their keys in a seperate location, as opposed to reading user chat keys from the database
|
|
// We do this because if a user's profile expires/is banned, the person chatting with them may want to continue talking to them.
|
|
// If we prevented deleting their profile from the database, that could pose a fingerprinting risk when contacting hosts
|
|
// Hosts would know that the requestor had been chatting with the profiles which were expired, because they would normally be deleted
|
|
// Therefore, we store the user's chat keys in peerChatKeys, so we can delete their expired profile and still keep their chat keys
|
|
// Their profile will be deleted from the database when the identity expires/is banned.
|
|
|
|
// Active keys are keys that are a maximum of 1 day older than any any known peer latestChatKeysUpdateTime
|
|
|
|
// TODO: create updateStoredChatKeys to refresh all chat keys for all saved identities
|
|
// TODO: Delete chat keys for users who are not chatting partners
|
|
|
|
import "seekia/internal/encoding"
|
|
import "seekia/internal/helpers"
|
|
import "seekia/internal/identity"
|
|
import "seekia/internal/messaging/peerDevices"
|
|
import "seekia/internal/myDatastores/myMap"
|
|
import "seekia/internal/myDatastores/myMapList"
|
|
import "seekia/internal/profiles/profileStorage"
|
|
import "seekia/internal/profiles/readProfiles"
|
|
import "seekia/internal/unixTime"
|
|
|
|
import "strings"
|
|
import "sync"
|
|
import "errors"
|
|
|
|
// This mutex will be locked whenever we are updating the peer chat keys MyMapList
|
|
var updatingPeerChatKeysMutex sync.Mutex
|
|
|
|
// This mutex will be locked whenever we are updating the peer chat keys latest update time MyMap
|
|
var updatingPeerChatKeysLatestUpdateTimeMutex sync.Mutex
|
|
|
|
var peerChatKeysMapListDatastore *myMapList.MyMapList
|
|
|
|
// Map Structure: Peer Identity Hash + "@" + networkType -> Latest update unix time
|
|
var peerChatKeysLatestUpdateTimeMapDatastore *myMap.MyMap
|
|
|
|
// This function must be called whenever an app user signs in
|
|
func InitializePeerChatKeysDatastores()error{
|
|
|
|
updatingPeerChatKeysMutex.Lock()
|
|
defer updatingPeerChatKeysMutex.Unlock()
|
|
|
|
updatingPeerChatKeysLatestUpdateTimeMutex.Lock()
|
|
defer updatingPeerChatKeysLatestUpdateTimeMutex.Unlock()
|
|
|
|
newPeerChatKeysMapListDatastore, err := myMapList.CreateNewMapList("PeerChatKeys")
|
|
if (err != nil) { return err }
|
|
|
|
newPeerChatKeysLatestUpdateTimeMapDatastore, err := myMap.CreateNewMap("PeerChatKeysLatestUpdateTime")
|
|
if (err != nil) { return err }
|
|
|
|
peerChatKeysMapListDatastore = newPeerChatKeysMapListDatastore
|
|
peerChatKeysLatestUpdateTimeMapDatastore = newPeerChatKeysLatestUpdateTimeMapDatastore
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function will return true if we need to download a user's newest chat keys
|
|
// It determines this by comparing a user's saved chat keys to their latest chat keys update time
|
|
//Outputs:
|
|
// -bool: User's chat keys are missing (will return false if their newest profile is disabled)
|
|
// -error
|
|
func CheckIfUsersChatKeysAreMissing(userIdentityHash [16]byte, networkType byte)(bool, error){
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, errors.New("CheckIfUsersChatKeysAreMissing called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
profileIsDisabled, chatKeysExist, _, _, err := GetPeerNewestActiveChatKeys(userIdentityHash, networkType)
|
|
if (err != nil) { return false, err }
|
|
if (profileIsDisabled == true){
|
|
// We treat this as the chat keys not being missing
|
|
return false, nil
|
|
}
|
|
if (chatKeysExist == true){
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// This function saves a user's chat key latest update time from a message
|
|
// It is used to keep track of when peer updates their key set, so the app knows to retrieve new chat keys
|
|
// This information could be wrong, if newer keys have been shared since the user sent their message
|
|
func SavePeerMessageLatestChatKeysUpdateTime(peerIdentityHash [16]byte, networkType byte, theirLatestChatKeysUpdateTime int64, theirMessageCreationTime int64)error{
|
|
|
|
updatingPeerChatKeysLatestUpdateTimeMutex.Lock()
|
|
defer updatingPeerChatKeysLatestUpdateTimeMutex.Unlock()
|
|
|
|
peerIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(peerIdentityHash)
|
|
if (err != nil){
|
|
peerIdentityHashHex := encoding.EncodeBytesToHexString(peerIdentityHash[:])
|
|
return errors.New("SavePeerMessageLatestChatKeysUpdateTime called with invalid peerIdentityHash: " + peerIdentityHashHex)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return errors.New("SavePeerMessageLatestChatKeysUpdateTime called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
existingLatestUpdateTimeExists, existingLatestUpdateTime, existingLatestUpdateTimeCreationTime, err := getSavedPeerMessageLatestChatKeysUpdateTime(peerIdentityHash, networkType)
|
|
if (err != nil){ return err }
|
|
if (existingLatestUpdateTimeExists == true){
|
|
|
|
if (existingLatestUpdateTimeCreationTime > theirMessageCreationTime){
|
|
// We already have a latest update time which was sent at later time
|
|
// Nothing to do
|
|
return nil
|
|
}
|
|
|
|
// We have a latest update time that was created earler
|
|
// We see if the newer created latest update time is actually newer
|
|
if (existingLatestUpdateTime > theirLatestChatKeysUpdateTime){
|
|
// They are sending a latestUpdateTime that is older than one they have previously sent
|
|
// The user has probably moved to a different device, and then moved back to their previous device
|
|
// This should not happen
|
|
// To avoid this happening we should make sure there is an option in the GUI to reinitialize the application as if it is a new device
|
|
// This will require sharing a new LatestChatKeysUpdateTime in our profile
|
|
//
|
|
// We will delete our stored chatKeys and update our datastore latestChatKeysUpdateTime
|
|
// This will allow their older chat keys to be used if and when they created a profile from their device.
|
|
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
|
|
mapToDelete := map[string]string{
|
|
"PeerIdentityHash": peerIdentityHashString,
|
|
"NetworkType": networkTypeString,
|
|
}
|
|
|
|
err := peerChatKeysMapListDatastore.DeleteMapListItems(mapToDelete)
|
|
if (err != nil) { return err }
|
|
}
|
|
}
|
|
|
|
theirLatestChatKeysUpdateTimeString := helpers.ConvertInt64ToString(theirLatestChatKeysUpdateTime)
|
|
theirMessageCreationTimeString := helpers.ConvertInt64ToString(theirMessageCreationTime)
|
|
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
|
|
newMapKey := peerIdentityHashString + "@" + networkTypeString
|
|
newMapValue := theirLatestChatKeysUpdateTimeString + "$" + theirMessageCreationTimeString
|
|
|
|
err = peerChatKeysLatestUpdateTimeMapDatastore.SetMapEntry(newMapKey, newMapValue)
|
|
if (err != nil) { return err }
|
|
|
|
return nil
|
|
}
|
|
|
|
|
|
// This function retrieves our saved peer latest chat keys update time that we received in a message
|
|
//Outputs:
|
|
// -bool: Latest update time info exists
|
|
// -int64: Latest Update Time
|
|
// -int64: Latest update time creation time (the time when the user shared this latestUpdateTime)
|
|
// -error
|
|
func getSavedPeerMessageLatestChatKeysUpdateTime(peerIdentityHash [16]byte, networkType byte)(bool, int64, int64, error){
|
|
|
|
peerIdentityHashString, _, err := identity.EncodeIdentityHashBytesToString(peerIdentityHash)
|
|
if (err != nil){
|
|
peerIdentityHashHex := encoding.EncodeBytesToHexString(peerIdentityHash[:])
|
|
return false, 0, 0, errors.New("getSavedPeerMessageLatestChatKeysUpdateTime called with invalid peerIdentityHash: " + peerIdentityHashHex)
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, 0, 0, errors.New("getSavedPeerMessageLatestChatKeysUpdateTime called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
|
|
mapKey := peerIdentityHashString + "@" + networkTypeString
|
|
|
|
entryExists, mapValue, err := peerChatKeysLatestUpdateTimeMapDatastore.GetMapEntry(mapKey)
|
|
if (err != nil) { return false, 0, 0, err }
|
|
if (entryExists == false){
|
|
return false, 0, 0, nil
|
|
}
|
|
|
|
latestUpdateTime, latestUpdateTimeCreationTime, delimiterFound := strings.Cut(mapValue, "$")
|
|
if (delimiterFound == false){
|
|
return false, 0, 0, errors.New("peerChatKeysLatestUpdateTimeMapDatastore entry is malformed: Map value missing $: " + mapValue)
|
|
}
|
|
|
|
latestUpdateTimeInt64, err := helpers.ConvertStringToInt64(latestUpdateTime)
|
|
if (err != nil){
|
|
return false, 0, 0, errors.New("peerChatKeysLatestUpdateTimeMapDatastore entry value is malformed: Invalid latestUpdateTime: " + latestUpdateTime)
|
|
}
|
|
|
|
latestUpdateTimeCreationTimeInt64, err := helpers.ConvertStringToInt64(latestUpdateTimeCreationTime)
|
|
if (err != nil){
|
|
return false, 0, 0, errors.New("peerChatKeysLatestUpdateTimeMapDatastore entry value is malformed: Invalid latestUpdateTimeCreationTime: " + latestUpdateTimeCreationTime)
|
|
}
|
|
|
|
return true, latestUpdateTimeInt64, latestUpdateTimeCreationTimeInt64, nil
|
|
}
|
|
|
|
|
|
// This function returns the newest saved device chat keys list for a user
|
|
// It also checks saved profiles to update saved keys.
|
|
//Outputs:
|
|
// -bool: Peer newest profile is known to be disabled
|
|
// -bool: Peer active chat keys found
|
|
// -[32]byte: Nacl Key
|
|
// -[1568]byte: Kyber key
|
|
// -error
|
|
func GetPeerNewestActiveChatKeys(peerIdentityHash [16]byte, networkType byte)(bool, bool, [32]byte, [1568]byte, error){
|
|
|
|
peerIdentityHashString, userIdentityType, err := identity.EncodeIdentityHashBytesToString(peerIdentityHash)
|
|
if (err != nil) {
|
|
peerIdentityHashHex := encoding.EncodeBytesToHexString(peerIdentityHash[:])
|
|
return false, false, [32]byte{}, [1568]byte{}, errors.New("GetPeerNewestActiveChatKeys called with invalid peerIdentityHash: " + peerIdentityHashHex)
|
|
}
|
|
|
|
if (userIdentityType != "Mate" && userIdentityType != "Moderator"){
|
|
return false, false, [32]byte{}, [1568]byte{}, errors.New("Trying to get peer chat keys for host identity")
|
|
}
|
|
|
|
isValid := helpers.VerifyNetworkType(networkType)
|
|
if (isValid == false){
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
return false, false, [32]byte{}, [1568]byte{}, errors.New("GetPeerNewestActiveChatKeys called with invalid networkType: " + networkTypeString)
|
|
}
|
|
|
|
updatingPeerChatKeysMutex.Lock()
|
|
defer updatingPeerChatKeysMutex.Unlock()
|
|
|
|
//Outputs:
|
|
// -bool: Peer newest profile is known to be disabled
|
|
// -bool: Any keys found
|
|
// -[32]byte: User Nacl key
|
|
// -[1568]byte: User Kyber key
|
|
// -int64: Time keys were created
|
|
// -error
|
|
getPeerNewestKnownChatKeys := func()(bool, bool, [32]byte, [1568]byte, int64, error){
|
|
|
|
// We get newest known user chat keys
|
|
// We check database and storage, and return whichever are newer
|
|
|
|
// Database = Profiles within the badger database
|
|
// Storage = myMapList datastore
|
|
|
|
//Outputs:
|
|
// -bool: Profile found
|
|
// -bool: Profile is disabled
|
|
// -int64: Profile creation time
|
|
// -[32]byte: Peer Nacl key
|
|
// -[1568]byte: Peer Kyber key
|
|
// -error
|
|
getPeerChatKeysMapFromDatabase := func()(bool, bool, int64, [32]byte, [1568]byte, error){
|
|
|
|
profileExists, _, _, _, profileCreationTime, rawProfileMap, err := profileStorage.GetNewestUserProfile(peerIdentityHash, networkType)
|
|
if (err != nil) { return false, false, 0, [32]byte{}, [1568]byte{}, err }
|
|
if (profileExists == false) {
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
|
|
profileIsDisabled, _, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(rawProfileMap, "Disabled")
|
|
if (err != nil) { return false, false, 0, [32]byte{}, [1568]byte{}, err }
|
|
if (profileIsDisabled == true){
|
|
return true, true, profileCreationTime, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
|
|
exists, peerNaclKey, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(rawProfileMap, "NaclKey")
|
|
if (err != nil) { return false, false, 0, [32]byte{}, [1568]byte{}, err }
|
|
if (exists == false){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Database corrupt: Contains Mate/Moderator profile missing NaclKey")
|
|
}
|
|
|
|
exists, peerKyberKey, err := readProfiles.GetFormattedProfileAttributeFromRawProfileMap(rawProfileMap, "KyberKey")
|
|
if (err != nil) { return false, false, 0, [32]byte{}, [1568]byte{}, err }
|
|
if (exists == false){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Database corrupt: Contains Mate/Moderator profile missing KyberKey")
|
|
}
|
|
|
|
peerNaclKeyBytes, err := encoding.DecodeBase64StringToBytes(peerNaclKey)
|
|
if (err != nil){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Database corrupt: Contains Mate/Moderator profile with invalid NaclKey: Not Base64: " + peerNaclKey)
|
|
}
|
|
|
|
if (len(peerNaclKeyBytes) != 32){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Database corrupt: Contains Mate/Moderator profile with invalid NaclKey: Invalid length: " + peerNaclKey)
|
|
}
|
|
|
|
peerNaclKeyArray := [32]byte(peerNaclKeyBytes)
|
|
|
|
peerKyberKeyBytes, err := encoding.DecodeBase64StringToBytes(peerKyberKey)
|
|
if (err != nil){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Database corrupt: Contains Mate/Moderator profile with invalid KyberKey: Not Base64: " + peerKyberKey)
|
|
}
|
|
|
|
if (len(peerKyberKeyBytes) != 1568){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Database corrupt: Contains Mate/Moderator profile with invalid KyberKey: Invalid length: " + peerKyberKey)
|
|
}
|
|
|
|
peerKyberKeyArray := [1568]byte(peerKyberKeyBytes)
|
|
|
|
return true, false, profileCreationTime, peerNaclKeyArray, peerKyberKeyArray, nil
|
|
}
|
|
|
|
//Outputs:
|
|
// -bool: Peer stored keys found
|
|
// -bool: Peer is disabled
|
|
// -int64: Creation time of these keys/disabled status
|
|
// -[32]byte: Peer Nacl Key
|
|
// -[1568]byte: Peer Kyber key
|
|
// -error
|
|
getPeerChatKeysMapListFromMyMapListStorage := func()(bool, bool, int64, [32]byte, [1568]byte, error){
|
|
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
|
|
lookupMap := map[string]string{
|
|
"PeerIdentityHash": peerIdentityHashString,
|
|
"NetworkType": networkTypeString,
|
|
}
|
|
|
|
exists, retrievedMapListItems, err := peerChatKeysMapListDatastore.GetMapListItems(lookupMap)
|
|
if (err != nil) { return false, false, 0, [32]byte{}, [1568]byte{}, err }
|
|
if (exists == false){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
|
|
if (len(retrievedMapListItems) != 1) {
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: multiple entries found.")
|
|
}
|
|
|
|
peerChatKeysMap := retrievedMapListItems[0]
|
|
|
|
keysCreationTime, exists := peerChatKeysMap["CreationTime"]
|
|
if (exists == false) {
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item missing CreationTime")
|
|
}
|
|
|
|
keysCreationTimeInt64, err := helpers.ConvertCreationTimeStringToInt64(keysCreationTime)
|
|
if (err != nil) {
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item contains invalid CreationTime: " + keysCreationTime)
|
|
}
|
|
|
|
peerIsDisabled, exists := peerChatKeysMap["PeerIsDisabled"]
|
|
if (exists == true && peerIsDisabled == "Yes"){
|
|
return true, true, keysCreationTimeInt64, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
|
|
peerNaclKey, exists := peerChatKeysMap["NaclKey"]
|
|
if (exists == false) {
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item missing NaclKey")
|
|
}
|
|
|
|
peerKyberKey, exists := peerChatKeysMap["KyberKey"]
|
|
if (exists == false) {
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item missing KyberKey")
|
|
}
|
|
|
|
peerNaclKeyBytes, err := encoding.DecodeBase64StringToBytes(peerNaclKey)
|
|
if (err != nil){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item contains invalid NaclKey: Not Base64: " + peerNaclKey)
|
|
}
|
|
|
|
if (len(peerNaclKeyBytes) != 32){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item contains invalid NaclKey: Invalid length: " + peerNaclKey)
|
|
}
|
|
|
|
peerNaclKeyArray := [32]byte(peerNaclKeyBytes)
|
|
|
|
peerKyberKeyBytes, err := encoding.DecodeBase64StringToBytes(peerKyberKey)
|
|
if (err != nil){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item contains invalid KyberKey: Not Base64: " + peerKyberKey)
|
|
}
|
|
|
|
if (len(peerKyberKeyBytes) != 1568){
|
|
return false, false, 0, [32]byte{}, [1568]byte{}, errors.New("Malformed peer chat keys maplist: Item contains invalid KyberKey: Invalid length: " + peerKyberKey)
|
|
}
|
|
|
|
peerKyberKeyArray := [1568]byte(peerKyberKeyBytes)
|
|
|
|
return true, false, keysCreationTimeInt64, peerNaclKeyArray, peerKyberKeyArray, nil
|
|
}
|
|
|
|
databaseUserProfileExists, databaseProfileIsDisabled, databaseUserProfileCreationTime, databaseUserNaclKey, databaseUserKyberKey, err := getPeerChatKeysMapFromDatabase()
|
|
if (err != nil) { return false, false, [32]byte{}, [1568]byte{}, 0, err }
|
|
|
|
storageUserChatKeysInfoExists, storageProfileIsDisabled, storageUserProfileCreationTime, storageUserNaclKey, storageUserKyberKey, err := getPeerChatKeysMapListFromMyMapListStorage()
|
|
if (err != nil) { return false, false, [32]byte{}, [1568]byte{}, 0, err }
|
|
|
|
if (databaseUserProfileExists == false){
|
|
|
|
if (storageUserChatKeysInfoExists == false){
|
|
return false, false, [32]byte{}, [1568]byte{}, 0, nil
|
|
}
|
|
|
|
if (storageProfileIsDisabled == true){
|
|
return true, false, [32]byte{}, [1568]byte{}, 0, nil
|
|
}
|
|
|
|
return false, true, storageUserNaclKey, storageUserKyberKey, storageUserProfileCreationTime, nil
|
|
}
|
|
// Database chat keys exist
|
|
|
|
if (storageUserChatKeysInfoExists == true){
|
|
|
|
// Both the database profile and the datastore info exist
|
|
// We see which contains newer information
|
|
|
|
if (databaseUserProfileCreationTime <= storageUserProfileCreationTime){
|
|
// myMapList storage is up to date, or even more recent than the stored profile
|
|
// The latter would occur if a newer profile was deleted at some point, and an older profile was downloaded
|
|
// We return the myMapList stored data
|
|
|
|
if (storageProfileIsDisabled == true){
|
|
return true, false, [32]byte{}, [1568]byte{}, 0, nil
|
|
}
|
|
return false, true, storageUserNaclKey, storageUserKyberKey, storageUserProfileCreationTime, nil
|
|
}
|
|
}
|
|
|
|
// MyMapList chat keys entry is either missing or out of date.
|
|
// Update them with database profile keys, and return the database profile chat keys
|
|
// Note that just because the created profile is newer does not mean the chat keys are any different.
|
|
|
|
networkTypeString := helpers.ConvertByteToString(networkType)
|
|
|
|
deleteLookupMap := map[string]string{
|
|
"PeerIdentityHash": peerIdentityHashString,
|
|
"NetworkType": networkTypeString,
|
|
}
|
|
|
|
err = peerChatKeysMapListDatastore.DeleteMapListItems(deleteLookupMap)
|
|
if (err != nil) { return false, false, [32]byte{}, [1568]byte{}, 0, err }
|
|
|
|
creationTimeString := helpers.ConvertInt64ToString(databaseUserProfileCreationTime)
|
|
|
|
newChatKeysMap := map[string]string{
|
|
"PeerIdentityHash": peerIdentityHashString,
|
|
"NetworkType": networkTypeString,
|
|
"CreationTime": creationTimeString,
|
|
}
|
|
|
|
if (databaseProfileIsDisabled == true){
|
|
newChatKeysMap["PeerIsDisabled"] = "Yes"
|
|
} else {
|
|
|
|
databaseUserNaclKeyString := encoding.EncodeBytesToBase64String(databaseUserNaclKey[:])
|
|
databaseUserKyberKeyString := encoding.EncodeBytesToBase64String(databaseUserKyberKey[:])
|
|
|
|
newChatKeysMap["NaclKey"] = databaseUserNaclKeyString
|
|
newChatKeysMap["KyberKey"] = databaseUserKyberKeyString
|
|
}
|
|
|
|
err = peerChatKeysMapListDatastore.AddMapListItem(newChatKeysMap)
|
|
if (err != nil) { return false, false, [32]byte{}, [1568]byte{}, 0, err }
|
|
|
|
if (databaseProfileIsDisabled == true){
|
|
return true, false, [32]byte{}, [1568]byte{}, 0, nil
|
|
}
|
|
|
|
return false, true, databaseUserNaclKey, databaseUserKyberKey, databaseUserProfileCreationTime, nil
|
|
}
|
|
|
|
peerProfileIsDisabled, peerChatKeysExist, peerNewestKnownNaclKey, peerNewestKnownKyberKey, peerNewestKnownKeysCreationTime, err := getPeerNewestKnownChatKeys()
|
|
if (err != nil) { return false, false, [32]byte{}, [1568]byte{}, err }
|
|
if (peerProfileIsDisabled == true){
|
|
return true, false, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
if (peerChatKeysExist == false){
|
|
return false, false, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
|
|
// We check to see if user has updated their device since they created these keys
|
|
|
|
deviceInfoFound, _, deviceFirstSeenTime, err := peerDevices.GetPeerNewestDeviceInfo(peerIdentityHash, networkType)
|
|
if (err != nil) { return false, false, [32]byte{}, [1568]byte{}, err }
|
|
if (deviceInfoFound == true){
|
|
if (deviceFirstSeenTime > peerNewestKnownKeysCreationTime){
|
|
// User has changed their device since they created these keys
|
|
// We do not have access to the user's chat keys
|
|
return false, false, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
}
|
|
|
|
// Now we check to see if user has sent a newer ChatKeysLatestUpdateTime
|
|
// We allow a 1 day grace period where old keys will still work
|
|
|
|
newestUpdateTimeIsKnown, newestUpdateTime, _, err := getSavedPeerMessageLatestChatKeysUpdateTime(peerIdentityHash, networkType)
|
|
if (err != nil) { return false, false, [32]byte{}, [1568]byte{}, err }
|
|
if (newestUpdateTimeIsKnown == true){
|
|
|
|
dayUnix := unixTime.GetDayUnix()
|
|
|
|
keysExpirationTime := newestUpdateTime - dayUnix
|
|
|
|
if (peerNewestKnownKeysCreationTime < keysExpirationTime){
|
|
return false, false, [32]byte{}, [1568]byte{}, nil
|
|
}
|
|
}
|
|
|
|
return false, true, peerNewestKnownNaclKey, peerNewestKnownKyberKey, nil
|
|
}
|
|
|
|
|
|
|
|
|
|
|