示例#1
0
文件: mac.py 项目: ikvm/floranet
 def encode(self):
     """Create a binary representation of JoinAcceptMessage object.
     
     Returns:
         Packed JoinAccept message.
     """
     # Encoding Join-accept:
     # MAC Header
     # 3 bytes appnonce
     # 3 bytes netid 
     # 4 bytes devaddr
     # 1 byte dlsettings
     # 1 byte rxdelay
     # Optional cflist
     
     # Create the message
     header = self.mhdr.encode()
     msg =  intPackBytes(self.appnonce, 3, endian='little') + \
            intPackBytes(self.netid, 3, endian='little') + \
            struct.pack('<L', self.devaddr) + \
            struct.pack('B', self.dlsettings) + \
            struct.pack('B', self.rxdelay)
     # CFList is not used in a Join Accept message for US/AU bands
     if self.cflist:
         pass
     # Create the MIC over the entire message
     self.mic = aesEncrypt(intPackBytes(self.appkey, 16), header + msg,
                           mode='CMAC')[0:4]
     msg += self.mic
     # Add the header and encrypt the message using AES-128 decrypt
     data = header + aesDecrypt(intPackBytes(self.appkey, 16), msg)
     return data
示例#2
0
文件: mac.py 项目: ikvm/floranet
    def encrypt(self, key, dir):
        """Encrypt FRMPayload
        
        The algorithm defines a sequence of Blocks Ai for i = 1..k with k =
        ceil(len(pld) / 16):
        Ai: [0x01 | 4 x 0x00 | dir | devaddr | Fcntup or FcntDown | 0x00 | i]
        
        dir is 0 for uplink and 1 for downlink
        
        The blocks Ai are encrypted to get a sequence S of blocks Si:
          Si = aes128_encrypt(K, Ai) for i = 1..k
          
        Encryption and decryption of the payload is done by
        truncating (pld | pad16) xor S to the first len(pld) octets.
        i.e. pad pld to a 16 byte boundary, then xor with S, and
        truncate to the original length.
        
        Args:
            key (int): AES encryption key - device NwkSKey or AppSkey
            dir (int): Direction - 0 for uplink and 1 for downlink
        
        """
        if self.payload.frmpayload == None:
            return
        plen = len(self.payload.frmpayload)
        if plen == 0:
            return
        k = int(math.ceil(plen/16.0))
        # Create the concatenated block S
        S = ''
        for i in range(k):
            # Ai: [0x01 | 4 x 0x00 | dir | devaddr | Fcntup or FcntDown | 0x00 | i]
            Ai = struct.pack('<BLBLLBB', 1, 0, dir, self.payload.fhdr.devaddr,
                             self.payload.fhdr.fcnt, 0, i+1)
            # Si = aes128_encrypt(K, Ai) 
            S += aesEncrypt(intPackBytes(key, 16), Ai)

        # Pad frmpayload to a byte multiple of 16
        padlen = k * 16 - plen
        padded = self.payload.frmpayload + intPackBytes(0, padlen)
        
        # Unpack S and padded payload into arrays of long long ints
        ufmt = '{}Q'.format(k*2)
        s = struct.unpack(ufmt, S)
        p = struct.unpack(ufmt, padded)
        
        # Perform the XOR function over the data, and pack
        pld = ''
        for i in range (len(s)):
            pld += struct.pack('Q', s[i] ^ p[i])
            
        # Truncate the result to the original length
        self.payload.frmpayload = pld[:plen]
示例#3
0
 def test_intPackBytes(self, ):
     k = int('0x017E151638AEC2A6ABF7258809CF4F3C', 16)
     length = 16
     
     expected = '\x01~\x15\x168\xae\xc2\xa6\xab\xf7%\x88\t\xcfO<'
     result = util.intPackBytes(k, length)
     
     self.assertEqual(expected, result)
示例#4
0
 def _createSessionKey(self, pre, app, msg):
     """Create a NwkSKey or AppSKey
     
     Creates the session keys NwkSKey and AppSKey specific for
     an end-device to encrypt and verify network communication
     and application data.
     
     Args:
         pre (int): 0x01 ofr NwkSKey, 0x02 for AppSKey
         app (Application): The applicaiton object.
         msg (JoinRequestMessage): The MAC Join Request message.
     
     Returns:
         int: 128 bit session key
     """
     # Session key data: 0x0n | appnonce | netid | devnonce | pad (16)
     data = struct.pack('B', pre) + \
            intPackBytes(app.appnonce, 3, endian='little') + \
            intPackBytes(self.config.netid, 3, endian='little') + \
            struct.pack('<H', msg.devnonce) + intPackBytes(0, 7)
     aesdata = aesEncrypt(intPackBytes(app.appkey, 16), data)
     key = intUnpackBytes(aesdata)
     return key
示例#5
0
文件: mac.py 项目: ikvm/floranet
 def checkMIC(self, appkey):
     """Verify the message integrity code (MIC).
     
     The MIC is calculated over the binary join request message
     excluding the MIC. Use the first four bytes of AES CMAC
     encrypted data, convert from little endian data to int.
     
     Args:
         appkey (int): The application key.
         
     Returns:
         True on success, False otherwise.
     """
     data = self.mhdr.encode() + struct.pack('<QQH', self.appeui,
                                             self.deveui, self.devnonce)
     aesdata = aesEncrypt(intPackBytes(appkey, 16), data, mode='CMAC')
     mic = struct.unpack('<L', aesdata[:4])[0]
     return mic == self.mic
示例#6
0
文件: mac.py 项目: ikvm/floranet
    def checkMIC(self, key):
        """Check the message integrity code
        
        Args:
            key (int): NwkSkey
        
        Returns:
            True on success, False otherwise
        """

        # Calculate the MIC for this message using key
        msg = self.mhdr.encode() + self.payload.encode()
        B0 = struct.pack('<BLBLLBB',
                         int('0x49', 16), 0, 0, self.payload.fhdr.devaddr,
                         self.payload.fhdr.fcnt, 0, len(msg))
        data = B0 + msg
        aesdata = aesEncrypt(intPackBytes(key, 16), data, mode='CMAC')
        mic = struct.unpack('<L', aesdata[:4])[0]
        # Compare to message MIC
        return mic == self.mic
示例#7
0
文件: mac.py 项目: ikvm/floranet
 def encode(self):
     """Create a binary representation of MACMessage object.
     
     Returns:
         String of packed data.
     
     """
     # Calculate the MIC.
     # The MIC is calculated as cmac = aes128_cmac(NwkSKey, B0 | msg)
     # MIC = cmac[0:3]
     # msg is defined as: MHDR | FHDR | FPort | FRMPayload
     # B0 is defined as:
     # 1 byte 0x49 | 4 bytes 0x00 | 1 byte dir=0 for uplink, 1 for downlink
     # 4 bytes devaddr | 4 bytes fcntup or fcntdown
     # 1 byte 0x00 | 1 bytes len
     msg = self.mhdr.encode() + self.payload.encode()
     B0 = struct.pack('<BLBLLBB', int('0x49', 16), 0, 1,
                      self.devaddr, self.payload.fhdr.fcnt, 0, len(msg))
     data = B0 + msg
     # Create the MIC over the entire message
     self.mic = aesEncrypt(intPackBytes(self.key, 16), data,
                           mode='CMAC')[0:4]
     msg += self.mic
     return msg