LoRaWAN 1.0.x packet decoder

A frontend towards lora-packet.

Specify the secrets if you want to validate the MIC and decrypt the payload. Secrets are sent to the server and might be stored in log files of RunKit.

Assuming base64-encoded packet

Message Type = Data
  PHYPayload = 40AE130426800000016F895D98810714E3268295

( PHYPayload = MHDR[1] | MACPayload[..] | MIC[4] )
        MHDR = 40
  MACPayload = AE130426800000016F895D98810714
         MIC = E3268295 (from packet)
             = E3268295 (expected, assuming 32 bits frame counter below 65,536)

( MACPayload = FHDR | FPort | FRMPayload )
        FHDR = AE130426800000
       FPort = 01
  FRMPayload = 6F895D98810714 (from packet, encrypted)
             = 61626364656667 (decrypted)

      ( FHDR = DevAddr[4] | FCtrl[1] | FCnt[2] | FOpts[0..15] )
     DevAddr = 260413AE (Big Endian)
       FCtrl = 80
        FCnt = 0000 (Big Endian)
       FOpts = 

Message Type = Unconfirmed Data Up
   Direction = up
        FCnt = 0
   FCtrl.ACK = false
   FCtrl.ADR = true

Beware that LoRaWAN packets are binary data, so do not remove leading zeroes. Also note that erroneous packets are likely to show incorrect results without any warning, so specify the secrets to validate the Message Integrity Code (MIC).

In LoRaWAN 1.0.x, the value of FCnt only holds the 16 most significant bits (MSB) of the actual frame counter. But for a 32 bits frame counter still all 32 bits are used when calculating the MIC. So, the server needs to guess or try the other 16 bits when validating the MIC. The server can use its own internal counters for a best guess (and LoRaWAN defines the maximum gap between the last known value and current value, so the server only needs to try one additional value), but no guessing is done here: the verification above might fail if the actual frame counter exceeds 65,536.

The output above is the standard output of lora-packet with some minor enhancements if the secrets are known, to show if the MIC is valid (see note about 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, but cannot validate/decrypt then:

  • install Node.js and npm
  • run: npm install -g lora-packet
  • run: lora-packet-decode --base64 ADFGUkFEshgAdAoAAACyGADXQ5rzpZs=
    or lora-packet-decode --hex 003146524144B21800740A000000B21800D7439AF3A59B

The maintainer of this page is not affiliated with lora-packet. See & star https://github.com/anthonykirby/lora-packet.