def processPendingContacts(torId): print("Process pending contact accept responses from:", torId) foundReq = False for resp in DbI.getPendingContactMessages(torId): name = resp.get("fromName", None) if not name: profile = DbI.getProfile(torId) name = profile["displayName"] print("Found pending contact accept request from: ", name) # Check signature using keyring _, signatureKey = CryptoClient.decryptAndCheckSignature( resp.get("encryptedMsg", None)) if signatureKey: foundReq = True # Insert new message into inbox with message contents rowToStore = { "messageType": "contactresponse", "fromId": resp.get("fromId", None), "fromName": name, "accepted": True, "messageBody": resp.get("messageBody", ""), "timestamp": resp.get("timestamp", None), "messageRead": True, "messageReplied": True, "recipients": DbI.getOwnTorid() } DbI.addToInbox(rowToStore) if foundReq: DbI.updateProfile(torId, {"status": "untrusted"}) # Delete all pending contact responses from this torId DbI.deletePendingContactMessages(torId)
def construct(payload, isEncrypted=True): '''Factory constructor using a given payload and extracting the fields''' if not payload: return None signatureKey = None if isEncrypted: # Decrypt the payload with our key decrypted, signatureKey = CryptoClient.decryptAndCheckSignature( payload) else: decrypted = payload if decrypted: print("Asymmetric message, length of decrypted is", len(decrypted)) else: print("Asymmetric message has no decrypted") # Separate fields of message into common ones and the type-specific payload msgType, subpayload, tstmp = AsymmetricMessage._stripFields(decrypted) print("Recovered timestamp='", tstmp, "' (", len(tstmp), ")") # Find a suitable subclass to call using the messageType msg = None if msgType == Message.TYPE_CONTACT_RESPONSE: msg = ContactResponseMessage.constructFrom(subpayload) elif msgType == Message.TYPE_STATUS_NOTIFY: msg = StatusNotifyMessage.constructFrom(subpayload) elif msgType == Message.TYPE_ASYM_MESSAGE: msg = RegularMessage.constructFrom(subpayload) elif msgType == Message.TYPE_INFO_REQUEST: msg = InfoRequestMessage.constructFrom(subpayload) elif msgType == Message.TYPE_INFO_RESPONSE: msg = InfoResponseMessage.constructFrom(subpayload) elif msgType == Message.TYPE_FRIEND_REFERRAL: msg = ContactReferralMessage.constructFrom(subpayload) elif msgType == Message.TYPE_FRIENDREFER_REQUEST: msg = ContactReferRequestMessage.constructFrom(subpayload) # Ask the message if it's ok to have no signature if isEncrypted and msg: if msg.acceptUnrecognisedSignature(): # Save the encrypted contents so we can verify it later msg.encryptedContents = payload elif not signatureKey: msg = None if msg: try: msgTimestamp = tstmp.decode('utf-8') except: msgTimestamp = msg.makeCurrentTimestamp() msg.timestamp = Message.convertTimestampFromString(msgTimestamp) msg.signatureKeyId = signatureKey if signatureKey: print( "Asymm setting senderId because I've got a signatureKey: '%s'" % signatureKey) signatureId = DbI.findUserIdFromKeyId(signatureKey) if signatureId: msg.senderId = signatureId return msg
def construct(payload, isEncrypted=True): '''Factory constructor using a given payload and extracting the fields''' if not payload: return None signatureKey = None if isEncrypted: # Decrypt the payload with our key decrypted, signatureKey = CryptoClient.decryptAndCheckSignature(payload) else: decrypted = payload if decrypted: print("Asymmetric message, length of decrypted is", len(decrypted)) else: print("Asymmetric message has no decrypted") # Separate fields of message into common ones and the type-specific payload msgType, subpayload, tstmp = AsymmetricMessage._stripFields(decrypted) print("Recovered timestamp='", tstmp, "' (", len(tstmp), ")") # Find a suitable subclass to call using the messageType msg = None if msgType == Message.TYPE_CONTACT_RESPONSE: msg = ContactResponseMessage.constructFrom(subpayload) elif msgType == Message.TYPE_STATUS_NOTIFY: msg = StatusNotifyMessage.constructFrom(subpayload) elif msgType == Message.TYPE_ASYM_MESSAGE: msg = RegularMessage.constructFrom(subpayload) elif msgType == Message.TYPE_INFO_REQUEST: msg = InfoRequestMessage.constructFrom(subpayload) elif msgType == Message.TYPE_INFO_RESPONSE: msg = InfoResponseMessage.constructFrom(subpayload) elif msgType == Message.TYPE_FRIEND_REFERRAL: msg = ContactReferralMessage.constructFrom(subpayload) # Ask the message if it's ok to have no signature if isEncrypted and msg: if msg.acceptUnrecognisedSignature(): # Save the encrypted contents so we can verify it later msg.encryptedContents = payload elif not signatureKey: msg = None if msg: try: msgTimestamp = tstmp.decode('utf-8') except: msgTimestamp = msg.makeCurrentTimestamp() msg.timestamp = Message.convertTimestampFromString(msgTimestamp) msg.signatureKeyId = signatureKey if signatureKey: print("Asymm setting senderId because I've got a signatureKey: '%s'" % signatureKey) signatureId = DbClient.findUserIdFromKeyId(signatureKey) if signatureId: msg.senderId = signatureId return msg
def testEncDecryption(self): self._setupKeyring(["key1_private", "key1_public"]) MESSAGE = "This is the unencrypted source text we're going to use".encode("utf-8") RECPTKEYID = self.KEYID_1 # encrypt for ourselves ans = CryptoClient.encryptAndSign(MESSAGE, RECPTKEYID, RECPTKEYID) self.assertIsNotNone(ans, "Encrypted result shouldn't be none") backAgain, sigok = CryptoClient.decryptAndCheckSignature(ans) self.assertIsNotNone(backAgain, "Decrypted result shouldn't be none") self.assertTrue(sigok, "Signature check should be ok") self.assertNotEqual(len(backAgain), 0, "Decrypted result shouldn't have zero length") self.assertNotEqual(ans, MESSAGE, "Encrypted result shouldn't be the same as the input") self.assertEqual(backAgain, MESSAGE, "Decrypted result should be the same as the input")
def testDecryptValid(self): self._setupKeyring(["key1_private", "key2_public"]) ENCRYPTED_MESSAGE = self.MESSAGE_FROM_2_FOR_1 backAgain, sigok = CryptoClient.decryptAndCheckSignature(ENCRYPTED_MESSAGE) self.assertIsNotNone(backAgain, "Decryption of valid data shouldn't give none") self.assertTrue(sigok, "Signature check should be ok")
def testDecryptUnrecognisedSig(self): self._setupKeyring(["key1_private"]) ENCRYPTED_MESSAGE = self.MESSAGE_FROM_2_FOR_1 backAgain, sigok = CryptoClient.decryptAndCheckSignature(ENCRYPTED_MESSAGE) self.assertIsNotNone(backAgain, "Decryption of encrypted text with unrecognised signature should still give a result") self.assertFalse(sigok, "Signature check should give false")
def testDecryptNotForMe(self): self._setupKeyring(["key1_public", "key2_private"]) ENCRYPTED_MESSAGE = self.MESSAGE_FROM_2_FOR_1 backAgain, sigok = CryptoClient.decryptAndCheckSignature(ENCRYPTED_MESSAGE) self.assertIsNone(backAgain, "Failed decryption should give none") self.assertFalse(sigok, "Signature check should give false")
def testDecryptBlank(self): self._setupKeyring(["key1_private", "key1_public"]) backAgain, sigok = CryptoClient.decryptAndCheckSignature("") self.assertIsNone(backAgain, "Decryption of empty string should give none") self.assertFalse(sigok, "Signature check should give false")
def testDecryptPlaintext(self): self._setupKeyring(["key1_private", "key1_public"]) MESSAGE = "This is the unencrypted source text we're going to use".encode("utf-8") backAgain, sigok = CryptoClient.decryptAndCheckSignature(MESSAGE) self.assertIsNone(backAgain, "Decryption of plaintext should give none") self.assertFalse(sigok, "Signature check should give false")