예제 #1
0
def validateKeys(jr, ja, keysPath, dont_generate_keys):
    keys = list()
    with open(keysPath) as f:
        for k in f:
            # Fetch keys in byte format. Needed by ctypes
            keys.append(bytes(k.rstrip().upper(), encoding='utf-8'))

    jr_decoded = base64.b64decode(jr)
    jr_m_type = jr_decoded[0] & 0xE0

    ja_decoded = base64.b64decode(ja)
    ja_m_type = ja_decoded[0] & 0xE0

    if jr_m_type != 0x00 or ja_m_type != 0x20:
        print("\nMake sure you provided a valid JoinRequest and JoinAccept \n")
        return

    jr_result = LorawanWrapper.testAppKeysWithJoinRequest(
        keys, jr, dont_generate_keys)

    if len(jr_result) > 0:

        # Convert valid keys into bytes
        valid_keys = list()
        for valid_key in jr_result.split():
            valid_keys.append(bytes(valid_key.upper(), encoding='utf-8'))

        ja_result = LorawanWrapper.testAppKeysWithJoinAccept(
            valid_keys, ja, dontGenerateKeys=True)

        if len(ja_result) > 0:
            print("\n**** Key found: %s **** \n" % (ja_result.split()[0]))
예제 #2
0
def deriveSessionKeys(device_auth_obj, appKey):
    json_result = LorawanWrapper.generateSessionKeysFromJoins(
        device_auth_obj.join_request, device_auth_obj.join_accept, appKey)
    keys = json.loads(json_result)
    device_auth_obj.apps_key = keys["appSKey"]
    device_auth_obj.nwks_key = keys["nwkSKey"]
    return device_auth_obj
예제 #3
0
def parseJSONtoPHY(json, key, nwkskey):
    if json is None:
        print ("JSON not specified. Exiting.")
        return
    
    b64 = LorawanWrapper.marshalJsonToPHYPayload(json, key, nwkskey)

    print ("PHYPayload is %s \n"%(b64))
예제 #4
0
def generate_mic(message, key):
    if key is not None:
        search = re.search(b'(.*)"data"\s?:\s?"(.*?)"(.*)', message)
        message = search.group(
            1) + b'"data":"' + LorawanWrapper.generateValidMIC(
                search.group(2), key) + b'"' + search.group(3)

    return message
예제 #5
0
def bruteforce_accept_request(ja, jr, dont_generate_keys):
    global keys

    jr_result = LorawanWrapper.testAppKeysWithJoinRequest(
        keys, jr, dont_generate_keys)

    if len(jr_result) > 0:

        # Convert valid keys into bytes
        valid_keys = list()
        for valid_key in jr_result.split():
            valid_keys.append(bytes(valid_key.upper(), encoding='utf-8'))

        ja_result = LorawanWrapper.testAppKeysWithJoinAccept(
            valid_keys, ja, dontGenerateKeys=True)

        if len(ja_result) > 0:
            print("\n**** Key found: %s **** \n" % (ja_result.split()[0]))
예제 #6
0
def formatData(data):
    result = ""

    if data:
        search = re.search('(.*)"data":"(.*?)"(.*)',
                           data.decode('utf-8', 'backslashreplace'))
        if search:
            global key
            phyPayload = LorawanWrapper.printPHYPayload(search.group(2), key)
            result = "\nParsed data: " + phyPayload

    return result
예제 #7
0
def extractMIC(b64_packet):
    stringPHY = LorawanWrapper.printPHYPayload(b64_packet)

    jsonPHY = json.loads(stringPHY)

    return jsonPHY['mic']


# JoinReq: AppEUI - DevEUI - DevNonce
# JoinAccept: AppNonce - NetID - DevAddr

# NwkSKey = aes128_encrypt(AppKey, 0x01 | AppNonce | NetID | DevNonce | pad16)
# AppSKey = aes128_encrypt(AppKey, 0x02 | AppNonce | NetID | DevNonce | pad16)
예제 #8
0
def formatData(data):
    result = ""

    if data is None:
        return result

    else:
        search = re.search('(.*)"data":"(.*?)"(.*)', data)
        if search is not None:  #means that a PHYPayload was received
            result = "Parsed data: %s\n" % (LorawanWrapper.printPHYPayload(
                search.group(2), None))

    return result
예제 #9
0
def formatData(data):
    result = ""

    if data is None:
        return result
    else:
        search = re.search('(.*)"data":"(.*?)"(.*)',
                           data.decode('utf-8', 'backslashreplace'))
        if search is not None:  #means that a PHYPayload was received
            phyPayload = LorawanWrapper.printPHYPayload(search.group(2), None)
            result += "\nParsed data: " + phyPayload

        return result
예제 #10
0
파일: UdpSender.py 프로젝트: tpterovtt/laf
def formatData(data):
    result = ""
    global fuzzOutMode
    global key
    global timeout
    global new_counter
    global dev_address
    
    if data is None:
        return result
    else:
        search = re.search('(.*)"data":"(.*?)"(.*)', data.decode('utf-8', 'backslashreplace'))
        if search is not None: #means that a PHYPayload was received
            phyPayload = LorawanWrapper.printPHYPayload(search.group(2), None)
            result += "\nParsed data: " + phyPayload

        return result        
예제 #11
0
    print("LoRaWAN Security Framework - %s" % (sys.argv[0]))
    print("Copyright (c) 2019 IOActive Inc.  All rights reserved.")
    print("*****************************************************\n")

    parser = argparse.ArgumentParser(
        description=
        'This script receives a JoinAccept and a JoinRequest in Base64, and an AppKey to generate the session keys. An example of the usage: \npython sessionKeysGenerator.py -a IB1scNmwJRA32RfMbvwe3oI= -r AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU= -k f5a3b185dfe452c8edca3499abcd0341'
    )
    requiredGroup = parser.add_argument_group('Required arguments')

    requiredGroup.add_argument("-a",
                               "--jaccept",
                               help='JoinAccept payload in base64',
                               required=True)
    requiredGroup.add_argument("-r",
                               "--jrequest",
                               help='JoinRequest payload in base64',
                               required=True)
    requiredGroup.add_argument(
        "-k",
        "--key",
        help=
        'Enter a device AppKey (in hex format, a total of 32 characters / 16 bytes). eg. 00112233445566778899AABBCCDDEEFF',
        required=True)

    options = parser.parse_args()

    json_result = LorawanWrapper.generateSessionKeysFromJoins(
        options.jrequest, options.jaccept, options.key)
    keys = json.loads(json_result)
    print("NwkSKey: %s\nAppSKey: %s" % (keys["nwkSKey"], keys["appSKey"]))
예제 #12
0
def bruteForce(packet):
    result = ""
    global device_auth_obj
    global dontGenerateKeys
    global keys
    global hours_betweeen_bruteforce_trials
    device_auth_obj = None

    if packet.m_type == "JoinRequest":

        # Check if Device exists. Otherwise, create it
        device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id(
            packet.dev_eui, packet.join_eui, packet.data_collector_id)
        if device_obj is None:
            try:
                device_obj = Device(
                    dev_eui=packet.dev_eui,
                    join_eui=packet.join_eui,
                    organization_id=packet.organization_id,
                )
                device_obj.save()
            except Exception as exc:
                logging.error("Error trying to save Device: {0}".format(exc))

            # Associate Device with the DataCollector
            try:
                device_data_collector_obj = DataCollectorToDevice(
                    data_collector_id=packet.data_collector_id,
                    device_id=device_obj.id)
                device_data_collector_obj.save()
            except Exception as exc:
                logging.error(
                    "Error trying to save DataCollectorToDevice: {0}".format(
                        exc))

        # Before cracking with many different keys, try with a PotentialAppKey previously found. In case this key is valid, we are pretty sure that is the correct AppKey
        device_auth_obj = DeviceAuthData.find_one_by_device_id(device_obj.id)
        if device_auth_obj and extractMIC(
                device_auth_obj.join_request) != packet.mic:
            pot_app_keys = PotentialAppKey.find_all_by_device_auth_id(
                device_auth_obj.id)

            if len(pot_app_keys) > 0:

                keys_to_test = list()

                for pot_app_key in pot_app_keys:
                    keys_to_test.append(
                        bytes(pot_app_key.app_key_hex.rstrip().upper(),
                              encoding='utf-8'))

                keys_to_test = list(dict.fromkeys(keys_to_test))
                correct_app_keys = LorawanWrapper.testAppKeysWithJoinRequest(
                    keys_to_test, packet.data, True).split()

                if len(correct_app_keys) > 1:
                    logging.warning(
                        "Found more than one possible keys for the device {0}. One of them should be the correct. Check it manually. Keys: {1}"
                        .format(packet.dev_eui, correct_app_keys))
                elif len(correct_app_keys) == 1:
                    # AppKey found!!
                    device_auth_obj.second_join_request_packet_id = packet.id
                    device_auth_obj.second_join_request = packet.data
                    device_auth_obj.app_key_hex = correct_app_keys[0]

                    parameters = {}
                    parameters["dev_addr"] = "Unkwown"
                    parameters["dev_eui"] = LorawanWrapper.getDevEUI(
                        device_auth_obj.join_request)
                    parameters["app_key"] = correct_app_keys[0]
                    parameters[
                        "packet_id_1"] = device_auth_obj.join_request_packet_id
                    parameters["packet_type_1"] = "JoinRequest"
                    parameters["packet_type_2"] = "JoinRequest"
                    parameters['packet_date'] = packet.date.strftime(
                        '%Y-%m-%d %H:%M:%S')

                    # Try to get the gateway from the packet, or retrieve it from DB if possible
                    if packet.gateway:
                        parameters["gateway"] = packet.gateway
                    else:
                        # If we don't receive the gateway in the packet,
                        # get the hex ID of the gateway associated to the device if any.
                        # If we have more than 1 gateway associated to the device, this method returns None
                        gw_obj = Gateway.find_only_one_gateway_by_device_id(
                            device_obj.id)
                        if gw_obj:
                            parameters["gateway"] = gw_obj.gw_hex_id
                        else:
                            parameters["gateway"] = 'Unkwown'

                    try:
                        alert = Alert(
                            type="LAF-009",
                            created_at=datetime.datetime.now(),
                            packet_id=packet.id,
                            device_auth_id=device_auth_obj.id,
                            device_id=device_obj.id,
                            parameters=json.dumps(parameters),
                            data_collector_id=packet.data_collector_id)
                        alert.save()

                        ReportAlert.print_alert(alert)

                    except Exception as exc:
                        logging.error(
                            "Error trying to save Alert LAF-009: {0}".format(
                                exc))

                    return

        # Check if the DeviceAuthData wasn't already generated
        never_bruteforced = False

        if device_auth_obj is None:
            never_bruteforced = True
            try:
                device_auth_obj = DeviceAuthData(
                    device_id=device_obj.id,
                    data_collector_id=packet.data_collector_id,
                    organization_id=packet.organization_id,
                    join_request=packet.data,
                    created_at=datetime.datetime.now(),
                    join_request_packet_id=packet.id)
                device_auth_obj.save()
            except Exception as exc:
                logging.error(
                    "Error trying to save DeviceAuthData at JoinRequest: {0}".
                    format(exc))

        # Check when was the last time it was bruteforced and
        # Try checking with the keys dictionary and the keys generated on the fly
        today = datetime.datetime.now()
        device_auth_obj.created_at = device_auth_obj.created_at.replace(
            tzinfo=None)

        elapsed = today - device_auth_obj.created_at  # Time in seconds

        if elapsed.seconds > 3600 * hours_betweeen_bruteforce_trials or never_bruteforced:

            result = LorawanWrapper.testAppKeysWithJoinRequest(
                keys, packet.data, dontGenerateKeys)

            # Update the last time it was broteforced
            device_auth_obj.created_at = datetime.datetime.now()

            # If potential keys found...
            if result != "":

                device_auth_obj.join_request_packet_id = packet.id
                device_auth_obj.join_request = packet.data

                # Split string possibly containing keys separated by spaces
                candidate_keys_array = result.split()

                for hex_key in candidate_keys_array:
                    try:
                        potential_key_obj = PotentialAppKey(
                            app_key_hex=hex_key.upper(),
                            organization_id=packet.organization_id,
                            last_seen=packet.date,
                            packet_id=packet.id,
                            device_auth_data_id=device_auth_obj.id)
                        potential_key_obj.save()
                    except Exception as exc:
                        logging.error(
                            "Error trying to save PotentialAppKey at JoinRequest: {0}"
                            .format(exc))

    elif packet.m_type == "JoinAccept" and packet.data is not None:

        last_seconds_date = packet.date - datetime.timedelta(seconds=5)

        try:
            organization_keys = PotentialAppKey.find_all_by_organization_id_after_datetime(
                packet.organization_id, last_seconds_date)

            # Return if no JR keys were found
            if len(organization_keys) == 0:
                return

            keys_array = list()
            for pk in organization_keys:
                # Fetch keys in byte format. Needed by ctypes
                keys_array.append(
                    bytes(pk.app_key_hex.rstrip().upper(), encoding='utf-8'))

            # Remove possible duplicates in array
            keys_array = list(dict.fromkeys(keys_array))

            result = LorawanWrapper.testAppKeysWithJoinAccept(
                keys_array, packet.data, True)
        except Exception as es:
            logging.error("Error trying to bforce JA: {0}".format(es))

        if result != "":

            # Clean the key string
            result = result.rstrip().upper()

            for potential_key_obj in organization_keys:
                if potential_key_obj.app_key_hex.upper() == result:
                    device_auth_obj = DeviceAuthData.find_one_by_id(
                        potential_key_obj.device_auth_data_id)
                    break

            if device_auth_obj is None:
                logging.error(
                    "Cracked a JoinAccept but no device_auth object found")
                return

            # Get DevAddr from JA packet
            dev_addr = LorawanWrapper.getDevAddr(result, packet.data)

            # Check if DeviceSession exists. Otherwise, create it
            dev_ses_obj = DeviceSession.find_one_by_dev_addr_and_datacollector_id(
                dev_addr, packet.data_collector_id)
            if dev_ses_obj is None:
                try:
                    dev_ses_obj = DeviceSession(
                        dev_addr=dev_addr,
                        organization_id=packet.organization_id,
                    )
                    dev_ses_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save DeviceSession: {0}".format(exc))

                try:
                    device_session_data_collector_obj = DataCollectorToDeviceSession(
                        data_collector_id=packet.data_collector_id,
                        device_session_id=dev_ses_obj.id)
                    device_session_data_collector_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save DataCollectorToDeviceSession: {0}"
                        .format(exc))

            #Add missing data
            device_auth_obj.device_session_id = dev_ses_obj.id
            device_auth_obj.join_accept = packet.data
            device_auth_obj.join_accept_packet_id = packet.id
            device_auth_obj.app_key_hex = result

            # Add session keys
            device_auth_obj = deriveSessionKeys(device_auth_obj, result)

            # Get the device to get dev_eui
            device_obj = Device.find_one(device_auth_obj.device_id)

            parameters = {}
            parameters["dev_addr"] = dev_ses_obj.dev_addr
            parameters["dev_eui"] = LorawanWrapper.getDevEUI(
                device_auth_obj.join_request)
            parameters["app_key"] = result
            parameters["packet_id_1"] = device_auth_obj.join_request_packet_id
            parameters["packet_type_1"] = "JoinRequest"
            parameters["packet_type_2"] = "JoinAccept"
            parameters['packet_date'] = packet.date.strftime(
                '%Y-%m-%d %H:%M:%S')

            if packet.gateway:
                parameters["gateway"] = packet.gateway
            else:
                # If we don't receive the gateway in the packet,
                # get the hex ID of the gateway associated to the device if any.
                # If we have more than 1 gateway associated to the device, this method returns None
                gw_obj = Gateway.find_only_one_gateway_by_device_id(
                    device_obj.id)
                if gw_obj:
                    parameters["gateway"] = gw_obj.gw_hex_id
                else:
                    parameters["gateway"] = 'Unkwown'

            try:
                alert = Alert(type="LAF-009",
                              created_at=datetime.datetime.now(),
                              packet_id=packet.id,
                              device_session_id=dev_ses_obj.id,
                              device_id=device_obj.id,
                              device_auth_id=device_auth_obj.id,
                              parameters=json.dumps(parameters),
                              data_collector_id=packet.data_collector_id)
                alert.save()

                ReportAlert.print_alert(alert)

            except Exception as exc:
                logging.error(
                    "Error trying to save Alert LAF-009: {0}".format(exc))
예제 #13
0
        print("LoRaWAN Security Framework - %s" % (sys.argv[0]))
        print("Copyright (c) 2019 IOActive Inc.  All rights reserved.")
        print("*****************************************************\n")

        parser = argparse.ArgumentParser(
            description=
            'This script parses and prints a single LoRaWAN PHYPayload data in Base64. It does the inverse as packetCrafter.py, so the output of that script can be used here and vice-versa.'
        )

        requiredGroup = parser.add_argument_group('Required arguments')
        requiredGroup.add_argument(
            "-d",
            "--data",
            help=
            'Base64 data to be parsed. eg. -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=',
            default=None,
            required=True)
        parser.add_argument(
            "-k",
            "--key",
            help=
            'Enter a device AppKey or AppSKey depending on the packet to be decrypted (join accept or data packet). Must be in hex format, a total of 32 characters / 16 bytes. eg. 00112233445566778899AABBCCDDEEFF',
            default=None)

        options = parser.parse_args()
        print("Parsed data: %s \n" %
              (LorawanWrapper.printPHYPayload(options.data, options.key)))

    except KeyboardInterrupt:
        exit(0)
예제 #14
0
def bruteForce(packet):
    result = ""
    global device_auth_obj
    global dontGenerateKeys
    global keys
    device_auth_obj = None

    if packet.m_type == "JoinRequest":

        result = LorawanWrapper.testAppKeysWithJoinRequest(
            keys, packet.data, dontGenerateKeys)

        if result != "":

            # Check if Device exists. Otherwise, create it
            device_obj = Device.find_one_by_dev_eui_and_join_eui_and_datacollector_id(
                packet.dev_eui, packet.join_eui, packet.data_collector_id)
            if device_obj is None:
                try:
                    device_obj = Device(
                        dev_eui=packet.dev_eui,
                        join_eui=packet.join_eui,
                        organization_id=packet.organization_id,
                    )
                    device_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save Device: {0}".format(exc))

                # Associate Device with the DataCollector
                try:
                    device_data_collector_obj = DataCollectorToDevice(
                        data_collector_id=packet.data_collector_id,
                        device_id=device_obj.id)
                    device_data_collector_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save DataCollectorToDevice: {0}".
                        format(exc))

            # Check if the DeviceAuthData wasn't already generated
            device_auth_obj = DeviceAuthData.find_one_by_device_id(
                device_obj.id)
            if device_auth_obj is None:
                try:
                    device_auth_obj = DeviceAuthData(
                        device_id=device_obj.id,
                        data_collector_id=packet.data_collector_id,
                        organization_id=packet.organization_id,
                        join_request=packet.data,
                        created_at=datetime.datetime.now(),
                        join_request_packet_id=packet.id)
                    device_auth_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save DeviceAuthData at JoinRequest: {0}"
                        .format(exc))
            else:
                device_auth_obj.join_request_packet_id = packet.id
                device_auth_obj.join_request = packet.data

            # Split string possibly containing keys separated by spaces
            candidate_keys_array = result.split()

            for hex_key in candidate_keys_array:
                try:
                    potential_key_obj = PotentialAppKey(
                        app_key_hex=hex_key,
                        organization_id=packet.organization_id,
                        last_seen=packet.date,
                        packet_id=packet.id,
                        device_auth_data_id=device_auth_obj.id)
                    potential_key_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save PotentialAppKey at JoinRequest: {0}"
                        .format(exc))

    elif packet.m_type == "JoinAccept" and packet.data is not None:

        last_seconds_date = packet.date - datetime.timedelta(seconds=5)

        try:
            organization_keys = PotentialAppKey.find_all_by_organization_id_after_datetime(
                packet.organization_id, last_seconds_date)

            keys_array = list()
            for pk in organization_keys:
                # Fetch keys in byte format. Needed by ctypes
                keys_array.append(
                    bytes(pk.app_key_hex.rstrip().upper(), encoding='utf-8'))

            # Remove possible duplicates in array
            keys_array = list(dict.fromkeys(keys_array))

            result = LorawanWrapper.testAppKeysWithJoinAccept(
                keys_array, packet.data, True)
        except Exception as es:
            logging.error("Error trying to bforce JA: {0}".format(es))

        if result != "":

            # Clean the key string
            result = result.rstrip().upper()

            for potential_key_obj in organization_keys:
                if potential_key_obj.app_key_hex == result:
                    device_auth_obj = DeviceAuthData.find_one_by_id(
                        potential_key_obj.device_auth_data_id)
                    break

            # Get DevAddr from JA packet
            dev_addr = LorawanWrapper.getDevAddr(result, packet.data)

            # Check if DeviceSession exists. Otherwise, create it
            dev_ses_obj = DeviceSession.find_one_by_dev_addr_and_datacollector_id(
                dev_addr, packet.data_collector_id)
            if dev_ses_obj is None:
                try:
                    dev_ses_obj = DeviceSession(
                        dev_addr=dev_addr,
                        organization_id=packet.organization_id,
                    )
                    dev_ses_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save DeviceSession: {0}".format(exc))

                try:
                    device_session_data_collector_obj = DataCollectorToDeviceSession(
                        data_collector_id=packet.data_collector_id,
                        device_session_id=dev_ses_obj.id)
                    device_session_data_collector_obj.save()
                except Exception as exc:
                    logging.error(
                        "Error trying to save DataCollectorToDeviceSession: {0}"
                        .format(exc))

            #Add missing data
            device_auth_obj.device_session_id = dev_ses_obj.id
            device_auth_obj.join_accept = packet.data
            device_auth_obj.join_accept_packet_id = packet.id
            device_auth_obj.app_key_hex = result

            # Add session keys
            device_auth_obj = deriveSessionKeys(device_auth_obj, result)

            # Get the device to get dev_eui
            device_obj = Device.find_one(device_auth_obj.device_id)

            parameters = {}
            parameters["dev_addr"] = dev_ses_obj.dev_addr
            parameters["dev_eui"] = LorawanWrapper.getDevEUI(
                device_auth_obj.join_request)
            parameters["app_key"] = result
            parameters[
                "join_request_packet_id"] = device_auth_obj.join_request_packet_id
            try:
                alert = Alert(type="LAF-009",
                              created_at=datetime.datetime.now(),
                              packet_id=packet.id,
                              device_session_id=dev_ses_obj.id,
                              device_auth_id=device_auth_obj.id,
                              parameters=json.dumps(parameters),
                              data_collector_id=packet.data_collector_id)
                alert.save()
            except Exception as exc:
                logging.error(
                    "Error trying to save Alert LAF-009: {0}".format(exc))

            ReportAlert.print_alert(alert)
예제 #15
0
def setPHYPayload(data):
    packet = {}
    stringPHY = LorawanWrapper.printPHYPayload(data)

    # If the PHYPayload couldn't be parsed, just put the error and return
    if "Error" in stringPHY:
        packet['error'] = stringPHY
        return packet

    try:
        jsonPHY = json.loads(stringPHY)
    except Exception as e:
        logging.error('Error parsing PHYPayload: {0}'.format(e))
        packet['error'] = stringPHY
        return packet

    # The following fields are shared by every packet
    packet['m_type'] = jsonPHY['mhdr']['mType']
    packet['major'] = jsonPHY['mhdr']['major']
    packet['mic'] = jsonPHY['mic']

    if packet['m_type'] == "JoinRequest":
        # It's a JoinRequest
        packet['join_eui'] = jsonPHY['macPayload']['joinEUI']
        packet['dev_eui'] = jsonPHY['macPayload']['devEUI']
        packet['dev_nonce'] = jsonPHY['macPayload']['devNonce']
        return packet
    elif packet['m_type'] == "JoinAccept":
        # It's a JoinAccept Nothing to see
        return packet
    elif packet['m_type'] == "UnconfirmedDataDown" or packet[
            'm_type'] == "ConfirmedDataDown":
        # These are fCtrl fields for downlink packets
        packet['adr'] = jsonPHY['macPayload']['fhdr']['fCtrl']['adr']
        packet['class_b'] = jsonPHY['macPayload']['fhdr']['fCtrl']['classB']
        packet['adr_ack_req'] = jsonPHY['macPayload']['fhdr']['fCtrl'][
            'adrAckReq']
        packet['ack'] = jsonPHY['macPayload']['fhdr']['fCtrl']['ack']
        # These fields are common for every data packet
        packet['dev_addr'] = jsonPHY['macPayload']['fhdr']['devAddr']
        packet['f_count'] = jsonPHY['macPayload']['fhdr']['fCnt']

        if 'fOpts' in jsonPHY['macPayload']['fhdr'] and jsonPHY['macPayload'][
                'fhdr']['fOpts'] is not None:
            if isinstance(jsonPHY['macPayload']['fhdr']['fOpts'], dict):
                packet['f_opts'] = json.dumps(
                    jsonPHY['macPayload']['fhdr']['fOpts'])
            elif isinstance(jsonPHY['macPayload']['fhdr']['fOpts'], list):
                packet['f_opts'] = json.dumps(
                    jsonPHY['macPayload']['fhdr']['fOpts'])
            else:
                packet['f_opts'] = str(jsonPHY['macPayload']['fhdr']['fOpts'])

        if 'f_port' in jsonPHY['macPayload']['fhdr'] and jsonPHY['macPayload'][
                'fhdr']['fPort'] is not None:
            packet['f_port'] = jsonPHY['macPayload']['fhdr']['fPort']

        return packet
    elif packet['m_type'] == "UnconfirmedDataUp" or packet[
            'm_type'] == "ConfirmedDataUp":
        # These are fCtrl fields for uplink packets
        packet['adr'] = jsonPHY['macPayload']['fhdr']['fCtrl']['adr']
        packet['f_pending'] = jsonPHY['macPayload']['fhdr']['fCtrl'][
            'fPending']
        packet['ack'] = jsonPHY['macPayload']['fhdr']['fCtrl']['ack']
        # These fields are common for every data packet
        packet['dev_addr'] = jsonPHY['macPayload']['fhdr']['devAddr']
        packet['f_count'] = jsonPHY['macPayload']['fhdr']['fCnt']

        if 'fOpts' in jsonPHY['macPayload']['fhdr'] and jsonPHY['macPayload'][
                'fhdr']['fOpts'] is not None:
            if isinstance(jsonPHY['macPayload']['fhdr']['fOpts'], dict):
                packet['f_opts'] = json.dumps(
                    jsonPHY['macPayload']['fhdr']['fOpts'])
            elif isinstance(jsonPHY['macPayload']['fhdr']['fOpts'], list):
                packet['f_opts'] = json.dumps(
                    jsonPHY['macPayload']['fhdr']['fOpts'])
            else:
                packet['f_opts'] = str(jsonPHY['macPayload']['fhdr']['fOpts'])

        if 'f_port' in jsonPHY['macPayload']['fhdr'] and jsonPHY['macPayload'][
                'fhdr']['fPort'] is not None:
            packet['f_port'] = jsonPHY['macPayload']['fhdr']['fPort']
        return packet

    return packet
예제 #16
0
    parser = argparse.ArgumentParser(
        description=
        'This scripts receives a PHYPayload packet in Base64 and a key which can be the NwkSKey of the AppKey depending on the packet type and generates the new MIC.'
    )
    requiredGroup = parser.add_argument_group('Required arguments')

    requiredGroup.add_argument(
        "-d",
        "--data",
        help=
        'Base64 data to be signed. eg. -d AE0jb3GsOdJVAwD1HInrJ7i3yXAFxKU=',
        default=None,
        required=True)
    requiredGroup.add_argument(
        "-k",
        "--key",
        help=
        'Enter the new key (in hex format, a total of 32 characters / 16 bytes) to sign packets (calculate and add a new MIC). Note that for JoinRequest/JoinAccept it must be the AppKey, and the NwkSKey for Data packets. This cannot be validated beforehand by this program. eg. 00112233445566778899AABBCCDDEEFF',
        required=True,
        default=None)
    parser.add_argument(
        "--jakey",
        help=
        '[JoinAccept ONLY]. Enter the key used to encrypt the JoinAccept previously (in hex format, a total of 32 characters / 16 bytes). This cannot be validated beforehand by this program. eg. 00112233445566778899AABBCCDDEEFF. A valid key sample for the JoinAccept "IB1scNmwJRA32RfMbvwe3oI=" is "f5a3b185dfe452c8edca3499abcd0341"',
        default=None)
    options = parser.parse_args()

    print("\nYour PHYPayload with the new MIC is %s\n" %
          (LorawanWrapper.generateValidMIC(options.data, options.key,
                                           options.jakey)))