def test_data_deserializer_string(): token = "TOKEN12345" seq_id = 0x1234567890ABCDEF send_id = 0x5F5F5F5F5F5F5F5F data_id = "Text" data = "This is some text ..." x = pySRUPLib.SRUP_Data() y = pySRUPLib.SRUP_Data() x.token = token x.sequence_id = seq_id x.sender_id = send_id x.data_id = data_id x.bytes_data = data assert x.sign(keyfile) is True z = x.serialize() assert y.deserialize(z) is True assert y.token == token assert y.sender_id == send_id assert y.sequence_id == seq_id assert y.data_id == data_id assert y.bytes_data == data assert y.verify(pubkeyfile) is True
def test_data_deserializer_int16(): token = "TOKEN12345" seq_id = 0x1234567890ABCDEF send_id = 0x5F5F5F5F5F5F5F5F data_id = "COUNT" data = 20 x = pySRUPLib.SRUP_Data() y = pySRUPLib.SRUP_Data() x.token = token x.sequence_id = seq_id x.sender_id = send_id x.data_id = data_id x.int16_data = data assert x.sign(keyfile) is True z = x.serialize() assert y.deserialize(z) is True assert y.token == token assert y.sender_id == send_id assert y.sequence_id == seq_id assert y.data_id == data_id assert y.int16_data == data assert y.verify(pubkeyfile) is True
def test_data_deserializer_double(): token = "TOKEN12345" seq_id = 0x1234567890ABCDEF send_id = 0x5F5F5F5F5F5F5F5F data_id = "Temperature" data = 18.94 x = pySRUPLib.SRUP_Data() y = pySRUPLib.SRUP_Data() x.token = token x.sequence_id = seq_id x.sender_id = send_id x.data_id = data_id x.double_data = data assert x.sign(keyfile) is True z = x.serialize() assert y.deserialize(z) is True assert y.token == token assert y.sender_id == send_id assert y.sequence_id == seq_id assert y.data_id == data_id assert y.double_data == data assert y.verify(pubkeyfile) is True
def test_data_signing(): blank = "" x = pySRUPLib.SRUP_Data() assert x.sign(blank) is False assert x.sign(keyfile) is False assert x.sign(keyfile) is False x.token = "TOKEN12345" assert x.sign(keyfile) is False x.sequence_id = 0x1234567890ABCDEF assert x.sign(keyfile) is False x.sender_id = 0x5F5F5F5F5F5F5F5F assert x.sign(keyfile) is False x.data_id = "BOB" assert x.sign(keyfile) is False x.int8_data = 7 assert x.sign(blank) is False assert x.sign(keyfile) is True assert x.verify(pubkeyfile) is True x.sequence_id = 43 assert x.verify(pubkeyfile) is False
def test_int8_data(): MIN_DATA = -128 MAX_DATA = 127 STRING = "Test" FLOAT = 123.45 x = pySRUPLib.SRUP_Data() x.int8_data = MIN_DATA assert x.int8_data == MIN_DATA x.int8_data = MAX_DATA assert x.int8_data == MAX_DATA with pytest.raises(OverflowError): x.int8_data = MAX_DATA + 1 with pytest.raises(OverflowError): x.int8_data = MIN_DATA - 1 with pytest.raises(TypeError): x.int8_data = STRING with pytest.raises(TypeError): x.int8_data = FLOAT
def test_uint16_data(): MIN_DATA = 0x0000 MAX_DATA = 0xFFFF STRING = "Test" FLOAT = 123.45 x = pySRUPLib.SRUP_Data() x.uint16_data = MIN_DATA assert x.uint16_data == MIN_DATA x.uint16_data = MAX_DATA assert x.uint16_data == MAX_DATA with pytest.raises(OverflowError): x.uint16_data = MAX_DATA + 1 with pytest.raises(OverflowError): x.uint16_data = MIN_DATA - 1 with pytest.raises(TypeError): x.uint16_data = STRING with pytest.raises(TypeError): x.uint16_data = FLOAT
def test_data_id(): x = pySRUPLib.SRUP_Data() SHORT_DATA_ID = "TEST_DATA" LONGER_DATA_ID = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" LONGEST_DATA_ID = "" for i in range(0, 65535): LONGEST_DATA_ID += "x" assert x.data_id is None x.data_id = SHORT_DATA_ID assert x.data_id == SHORT_DATA_ID x.data_id = LONGER_DATA_ID assert x.data_id == LONGER_DATA_ID x.data_id = LONGEST_DATA_ID assert x.data_id == LONGEST_DATA_ID LONGEST_DATA_ID += "s" assert (len(LONGEST_DATA_ID) > 65535) x.data_id = LONGEST_DATA_ID assert x.data_id != LONGEST_DATA_ID assert x.data_id == LONGEST_DATA_ID[0:65535]
def test_deserializer_from_data(): # To test deserialization - we need to start with a different message-type and then convert # back to a generic message... token = "TOKEN12345" seq_id = 0x1234567890ABCDEF send_id = 0x5F5F5F5F5F5F5F5F data = "This is some data that I might store in the data field" data_id = "A string" x = pySRUPLib.SRUP_Data() y = pySRUPLib.SRUP_Generic() x.token = token x.sequence_id = seq_id x.sender_id = send_id x.bytes_data = data x.data_id = data_id assert x.sign(keyfile) is True z = x.serialize() assert y.deserialize(z) is True # Remember we can't verify the generic message... assert y.verify(pubkeyfile) is False assert y.sender_id == send_id assert y.sequence_id == seq_id assert y.token == token
def test_data_serialize_blank_token(): x = pySRUPLib.SRUP_Data() x.token = "" x.sequence_id = 0x1234567890ABCDEF x.sender_id = 0x5F5F5F5F5F5F5F5F assert x.sign(keyfile) is False z = x.serialize() assert z is None
def test_data_serializer_long_long_int(): x = pySRUPLib.SRUP_Data() x.token = "TOKEN12345" x.sequence_id = 0x1234567890ABCDEF x.sender_id = 0x5F5F5F5F5F5F5F5F x.data_id = "COUNT" x.uint64_data = 0x1234567890ABCDEF assert x.sign(keyfile) is True z = x.serialize() assert z is not None
def test_data_serializer_int(): x = pySRUPLib.SRUP_Data() x.action_id = 7 x.token = "TOKEN12345" x.sequence_id = 0x1234567890ABCDEF x.sender_id = 0x5F5F5F5F5F5F5F5F x.data_id = "COUNT" x.uint8_data = 20 assert x.sign(keyfile) is True z = x.serialize()
def test_data_serializer_specific(): x = pySRUPLib.SRUP_Data() x.token = 'b42c27f3-48bd-4ee6-bd86-09bae2e3a546' x.sequence_id = 17 x.sender_id = 13389333505314606326 x.data_id = 'IDENTIFICATION_RESPONSE' x.bytes_data = 'pySRUP version 1.0' assert x.sign(keyfile) is True z = x.serialize() assert z is not None
def test_data_serializer_string(): x = pySRUPLib.SRUP_Data() x.token = "TOKEN12345" x.sequence_id = 0x1234567890ABCDEF x.sender_id = 0x5F5F5F5F5F5F5F5F x.data_id = "COUNT" x.bytes_data = "This is a test message that someone might want to send" assert x.sign(keyfile) is True z = x.serialize() assert z is not None
def test_data_serializer_double(): x = pySRUPLib.SRUP_Data() x.token = "TOKEN12345" x.sequence_id = 0x1234567890ABCDEF x.sender_id = 0x5F5F5F5F5F5F5F5F x.data_id = "COUNT" x.double_data = 1234567.89012345 assert x.sign(keyfile) is True z = x.serialize() assert z is not None
def test_double_data(): MIN_DATA = sys.float_info.max MAX_DATA = sys.float_info.min STRING = "Test" x = pySRUPLib.SRUP_Data() x.double_data = MIN_DATA assert x.double_data == MIN_DATA x.double_data = MAX_DATA assert x.double_data == MAX_DATA with pytest.raises(TypeError): x.double_data = STRING
def test_empty_object(): x = pySRUPLib.SRUP_Data() assert x.token is None assert x.sequence_id is None assert x.sender_id is None assert x.data_id is None assert x.bytes_data is None assert x.int8_data is None assert x.uint8_data is None assert x.int16_data is None assert x.uint16_data is None assert x.int32_data is None assert x.uint32_data is None assert x.int64_data is None assert x.uint64_data is None assert x.float_data is None assert x.double_data is None assert x.sign("") is False
def test_string_data(): SHORT_STRING = "Test" LONG_STRING = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()-=_+{}[];':\",./<>?~|\\" LONGEST_STRING = "" for i in range(0, 65535): LONGEST_STRING += "x" assert (len(LONGEST_STRING) == 65535) x = pySRUPLib.SRUP_Data() x.bytes_data = SHORT_STRING assert x.bytes_data == SHORT_STRING x.bytes_data = LONG_STRING assert x.bytes_data == LONG_STRING x.bytes_data = LONGEST_STRING assert x.bytes_data == LONGEST_STRING
def send_SRUP_Data(self, target_id, data_id, data): SRUP_data_message = pySRUPLib.SRUP_Data() SRUP_data_message.token = self.__getToken() iTarget = int(target_id, 16) if iTarget not in self.__seq_id: self.__seq_id.update({iTarget: 0}) self.__seq_id.update({iTarget: self.__seq_id[iTarget] + 1}) s = self.__seq_id[iTarget] SRUP_data_message.sequence_id = s SRUP_data_message.sender_id = int(self.__device_id, 16) SRUP_data_message.data_id = data_id # When we're sending data to a SRUP receiver we can determine the correct type function to used; # based on the type of the Python variable being sent… # Noting that there are actually far-fewer types in Python that we can use – than there are in C++... if type(data) is int: SRUP_data_message.int32_data = data elif type(data) is float: # Remember Python only has double-precision floats... SRUP_data_message.double_data = data elif type(data) is str: SRUP_data_message.bytes_data = data # We can't do the converse however - so when we're getting data from the system – we must already know what # type it is: based on it's data_id... SRUP_data_message.sign(self.__local_private_key) serial_data = SRUP_data_message.serialize() if self.__isServer: pre_topic = target_id else: pre_topic = self.__device_id if serial_data is not None: topic = "SRUP/{}".format(pre_topic) self.__mqtt_client.publish(topic, serial_data) time.sleep(1) # self.__mqtt_client.loop_write() else: # TODO: THROW A CUSTOM EXCEPTION print("Message did not serialize")
def test_data_seqid(): MAX_SEQID = 0xFFFFFFFFFFFFFFFF ZERO_SEQID = 0x00 VALID_SEQID = 0x7FFFFFFFFFFFFFE7 x = pySRUPLib.SRUP_Data() x.sequence_id = MAX_SEQID assert x.sequence_id == MAX_SEQID x.sequence_id = VALID_SEQID assert x.sequence_id == VALID_SEQID x.sequence_id = ZERO_SEQID assert x.sequence_id == ZERO_SEQID with pytest.raises(OverflowError): x.sequence_id = MAX_SEQID + 1 with pytest.raises(OverflowError): x.sequence_id = ZERO_SEQID - 1
def test_data_sender(): MAX_SENDER = 0xFFFFFFFFFFFFFFFF ZERO_SENDER = 0x00 VALID_SENDER = 0x7FFFFFFFFFFFFFE7 x = pySRUPLib.SRUP_Data() x.sender_id = MAX_SENDER assert x.sender_id == MAX_SENDER x.sender_id = VALID_SENDER assert x.sender_id == VALID_SENDER x.sender_id = ZERO_SENDER assert x.sender_id == ZERO_SENDER with pytest.raises(OverflowError): x.sender_id = MAX_SENDER + 1 with pytest.raises(OverflowError): x.sender_id = ZERO_SENDER - 1
def test_data_generic_deserializer(): token = "TOKEN12345" seq_id = 0x1234567890ABCDEF send_id = 0x5F5F5F5F5F5F5F5F data_id = "Text" data = "This is some text ..." x = pySRUPLib.SRUP_Data() i = pySRUPLib.SRUP_Generic() x.token = token x.sequence_id = seq_id x.sender_id = send_id x.data_id = data_id x.bytes_data = data assert x.sign(keyfile) is True z = x.serialize() assert z is not None assert i.deserialize(z) is True assert i.msg_type == pySRUPLib.__data_message_type()
def __on_message(self, client, userdata, msg): # First check if the message is even for us... # Remembering that server's are wild... topic = None ch_topic = msg.topic if ch_topic[0:5] == 'SRUP/': topic = ch_topic[5:] # First check if the message is for us (or if we're a server read it anyway) if topic == self.__device_id or self.__isServer: SRUP_generic_message = pySRUPLib.SRUP_Generic() # if if deserializes then it's probably a SRUP message... if SRUP_generic_message.deserialize(msg.payload): # Did we send it? If so, ignore it... if SRUP_generic_message.sender_id != int(self.__device_id, 16): # Check to see if we've had a message from this sender before (creating a counter if we haven't) if SRUP_generic_message.sender_id not in self.__seq_id: self.__seq_id.update( {SRUP_generic_message.sender_id: 0}) # Get current sequence ID for this sender... s = self.__seq_id[SRUP_generic_message.sender_id] # Check to see the sequence ID of the message is greater than the last received message # to avoid replay attack... if SRUP_generic_message.sequence_id > s: # Update the "last received" sequence ID for this sender... self.__seq_id[ SRUP_generic_message. sender_id] = SRUP_generic_message.sequence_id msg_type = SRUP_generic_message.msg_type if msg_type == SRUP_ACTION_MESSAGE_TYPE: SRUP_action_message = pySRUPLib.SRUP_Action() SRUP_action_message.deserialize(msg.payload) if SRUP_action_message.verify( self.__remote_public_key): self.__on_action(SRUP_action_message) else: # TODO: THROW A CUSTOM EXCEPTION print("Message did not verify using {}".format( self.__remote_public_key)) elif msg_type == SRUP_DATA_MESSAGE_TYPE: SRUP_data_message = pySRUPLib.SRUP_Data() SRUP_data_message.deserialize(msg.payload) if SRUP_data_message.verify( self.__remote_public_key): self.__on_data(SRUP_data_message) else: # TODO: THROW A CUSTOM EXCEPTION print("Message did not verify using {}".format( self.__remote_public_key)) elif msg_type == SRUP_INITIATE_MESSAGE_TYPE: # Devices can't send init messages – so skip this if we're a server... if not self.__isServer: SRUP_initiate_message = pySRUPLib.SRUP_Initiate( ) SRUP_initiate_message.deserialize(msg.payload) if SRUP_initiate_message.verify( self.__remote_public_key): self.__on_initiate(SRUP_initiate_message) else: # TODO: THROW A CUSTOM EXCEPTION print("Message did not verify using {}". format(self.__remote_public_key)) elif msg_type == SRUP_RESPONSE_MESSAGE_TYPE: SRUP_response_message = pySRUPLib.SRUP_Response() SRUP_response_message.deserialize(msg.payload) if SRUP_response_message.verify( self.__remote_public_key): self.__on_response(SRUP_response_message) else: # TODO: THROW A CUSTOM EXCEPTION print("Message did not verify using {}".format( self.__remote_public_key)) elif msg_type == SRUP_ACTIVATE_MESSAGE_TYPE: # Devices can't send activate messages either – so again, we'll skip if we're a server. if not self.__isServer: SRUP_activate_message = pySRUPLib.SRUP_Activate( ) SRUP_activate_message.deserialize(msg.payload) if SRUP_activate_message.verify( self.__remote_public_key): self.__on_activate(SRUP_activate_message) else: # TODO: THROW A CUSTOM EXCEPTION print("Message did not verify using {}". format(self.__remote_public_key)) else: # We have received a message type that we can't handle... # TODO: THROW A CUSTOM EXCEPTION print("Invalid message type or format") print(SRUP_generic_message.sequence_id) else: # TODO: THROW A CUSTOM EXCEPTION print("Sequence ID 0x{:02X} is invalid".format( SRUP_generic_message.sequence_id)) # print("Message Type: {}".format(SRUP_generic_message.msg_type)) else: pass # This is our own message – so ignore it... else: pass # TODO: Not a SRUP Message ... else: pass
def test_data_type(): x = pySRUPLib.SRUP_Data() assert x.msg_type == pySRUPLib.__data_message_type()
def test_data_token(): x = pySRUPLib.SRUP_Data() assert x.token is None x.token = "TEST_TOKEN" assert x.token == "TEST_TOKEN"