A frontend towards lora-packet.
Assuming hex-encoded packet 40111111110001000175CD660A58A64C1C6815A92D1ECF15 Message Type = Data PHYPayload = 40111111110001000175CD660A58A64C1C6815A92D1ECF15 ( PHYPayload = MHDR | MACPayload[..] | MIC ) MHDR = 40 MACPayload = 111111110001000175CD660A58A64C1C6815A9 MIC = 2D1ECF15 (from packet) = 2D1ECF15 (expected, assuming 32 bits frame counter with MSB 0000) ( MACPayload = FHDR | FPort | FRMPayload ) FHDR = 11111111000100 FPort = 01 FRMPayload = 75CD660A58A64C1C6815A9 (from packet, encrypted) = 48656C6C6F20576F726C64 (decrypted) ( FHDR = DevAddr | FCtrl | FCnt | FOpts[0..15] ) DevAddr = 11111111 (Big Endian) FCtrl = 00 FCnt = 0001 (Big Endian) FOpts = Message Type = Unconfirmed Data Up Direction = up FCnt = 1 (from packet, 16 bits) = 1 (32 bits, assuming MSB 0x0000) FCtrl.ACK = false FCtrl.ADR = false
Beware that LoRaWAN packets are binary data, so do not remove leading zeroes. Also note that erroneous packets (including packets that are just LoRa, not LoRaWAN) are likely to show incorrect results without any warning, so specify the secrets to validate the Message Integrity Code (MIC).
If the 4 bytes MIC is valid, then it's safe to assume the packet has not been altered, that it is indeed a LoRaWAN packet, and that the secret NwkSKey is valid too. But even then one cannot tell if the secret AppSKey is valid as well; specifying the wrong AppSKey simply yields different decryption results.
In LoRaWAN 1.0.x, the value of FCnt only holds the 16 least-significant bits (LSB) of the actual frame counter. But for a 32 bits frame counter still all 32 bits are used when calculating the MIC. So, a LoRaWAN server needs to guess or try the other 16 bits when validating the MIC. Such server can use its own internal counters for a best guess, and as LoRaWAN defines a maximum allowed gap between the last known value and current value (MAX_FCNT_GAP, being 16,384), the server will probably only try one additional value for the MSB. Above, boldly all possible 65,536 values for MSB are tried until a valid MIC is found.
Note that a DevAddr is not unique, and a provider will need to try to validate the MIC using the NwkSKey of all devices it knows for a given DevAddr, until it finds a valid MIC. Only when it finds a valid MIC it knows which device the packet belongs to. Beware that in The Things Network, failing to find a match will NOT be reported in the trace part of the gateway's Traffic page in TTN Console.
The output above is the standard output of lora-packet with some enhancements if the secrets are known, to show if the MIC is valid, brute-forcing the 32 bits frame counter, and to show the decrypted payload.
OTAA Join Requests are not encrypted. OTAA Join Accepts are not fully supported above, as those need some additional data to validate their MIC and derive the secret session keys.
lora-packet can also be installed as a command line utility, and since 0.7.7 can also validate/decrypt then:
npm install -g lora-packet
lora-packet-decode --base64 ADFGUkFEshgAdAoAAACyGADXQ5rzpZs=
lora-packet-decode --hex 003146524144B21800740A000000B21800D7439AF3A59B
The maintainer of this page is not affiliated with lora-packet. See & star https://github.com/anthonykirby/lora-packet.