(self,encr)
| 115 | # no match is found, None is returned, otherwise the method returns |
| 116 | # a two items array: [key_name, decripted_packet]. |
| 117 | def decrypt(self,encr): |
| 118 | if len(encr) < 11 + 1 + 10: |
| 119 | return None # Min length is 11 (header) + some data + 10 (HMAC). |
| 120 | |
| 121 | copy = bytearray(encr) |
| 122 | copy[1] = copy[1] & (0xff^MessageFlagsRelayed) # Clear Relayed. |
| 123 | copy[6] = 0 # TTL. Set to zero for HMAC. |
| 124 | padlen = copy[-1] & 0x0f # Padding length. |
| 125 | copy[-1] = copy[-1] & 0xf0 # Clear padding len field. |
| 126 | hm = copy[-10:] # The HMAC part: we will check it against our HMAC. |
| 127 | |
| 128 | # Test every key for a matching HMAC. |
| 129 | for key_name in self.keys: |
| 130 | key = self.keys[key_name] |
| 131 | |
| 132 | # Derive the encryption and HMAC keys. |
| 133 | aes_key,hmac_key = self.derive_keys(key) |
| 134 | my_hm = bytearray(HMAC_SHA256(hmac_key,copy[:-10])[:10]) |
| 135 | my_hm[-1] = my_hm[-1] & 0xf0 |
| 136 | if hm != my_hm: continue # No match. |
| 137 | |
| 138 | # Decrypt the payload |
| 139 | iv = self.sha16(copy[:11]) |
| 140 | plain = cryptolib.aes(aes_key,2,iv).decrypt(encr[11:-10]) |
| 141 | |
| 142 | # Compose the final decrypted packet removing the IV |
| 143 | # field, the padding and the HMAC. |
| 144 | orig = bytearray(7 + len(plain) - padlen) |
| 145 | orig[:7] = encr[:7] |
| 146 | orig[7:] = plain if padlen == 0 else plain[:-padlen] |
| 147 | return (key_name,orig) |
| 148 | return None |
| 149 | |
| 150 | if __name__ == "__main__": |
| 151 | kc = Keychain() |
no test coverage detected