def encrypt(key, msg, iv=None, alg="aes_128_cbc", padding="PKCS#7", b64enc=True, block_size=BLOCK_SIZE): """ :param key: The encryption key :param iv: init vector :param msg: Message to be encrypted :param padding: Which padding that should be used :param b64enc: Whether the result should be base64encoded :param block_size: If PKCS#7 padding which block size to use :return: The encrypted message """ if padding == "PKCS#7": _block_size = block_size elif padding == "PKCS#5": _block_size = 8 else: _block_size = 0 if _block_size: plen = _block_size - (len(msg) % _block_size) c = chr(plen) msg += (c * plen) cipher, iv = build_cipher(tobytes(key), iv, alg) cmsg = iv + cipher.encrypt(tobytes(msg)) if b64enc: return b64encode(cmsg) else: return cmsg
def build_cipher(key, iv, alg="aes_128_cbc"): """ :param key: encryption key :param iv: init vector :param alg: cipher algorithm :return: A Cipher instance """ typ, bits, cmode = alg.split("_") if not iv: iv = Random.new().read(AES.block_size) else: assert len(iv) == AES.block_size if bits not in ["128", "192", "256"]: raise AESError("Unsupported key length") try: assert len(key) == int(bits) >> 3 except AssertionError: raise AESError("Wrong Key length") try: return AES.new(tobytes(key), POSTFIX_MODE[cmode], tobytes(iv)), iv except KeyError: raise AESError("Unsupported chaining mode")
def config_set_config_request(security_ctx, ssid, passphrase): # Form protobuf request packet for SetConfig command cmd = proto.wifi_config_pb2.WiFiConfigPayload() cmd.msg = proto.wifi_config_pb2.TypeCmdSetConfig cmd.cmd_set_config.ssid = tobytes(ssid) cmd.cmd_set_config.passphrase = tobytes(passphrase) enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()).decode('latin-1') print_verbose(security_ctx, "Client -> Device (SetConfig cmd) " + utils.str_to_hexstr(enc_cmd)) return enc_cmd
def custom_cloud_config_request(security_ctx, userid, secretkey): # Form protobuf request packet from custom-config data cmd = proto.custom_cloud_config_pb2.CloudConfigPayload() cmd.msg = proto.custom_cloud_config_pb2.TypeCmdGetSetDetails cmd.cmd_get_set_details.UserID = tobytes(userid) cmd.cmd_get_set_details.SecretKey = tobytes(secretkey) enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()).decode('latin-1') print_verbose(security_ctx, "Client -> Device (CustomConfig cmd) " + utils.str_to_hexstr(enc_cmd)) return enc_cmd
def get_prop_vals_response(response_data): resp = local_ctrl_pb2.LocalCtrlMessage() resp.ParseFromString(tobytes(response_data)) results = [] if (resp.resp_get_prop_vals.status == 0): for prop in resp.resp_get_prop_vals.props: results += [{ "name": prop.name, "type": prop.type, "flags": prop.flags, "value": tobytes(prop.value) }] return results
def get_prop_vals_response(security_ctx, response_data): decrypt = security_ctx.decrypt_data(tobytes(response_data)) resp = local_ctrl_pb2.LocalCtrlMessage() resp.ParseFromString(decrypt) results = [] if (resp.resp_get_prop_vals.status == 0): for prop in resp.resp_get_prop_vals.props: results += [{ 'name': prop.name, 'type': prop.type, 'flags': prop.flags, 'value': tobytes(prop.value) }] return results
def scan_result_response(security_ctx, response_data): # Interpret protobuf response packet from ScanResult command dec_resp = security_ctx.decrypt_data(tobytes(response_data)) resp = proto.wifi_scan_pb2.WiFiScanPayload() resp.ParseFromString(dec_resp) print_verbose(security_ctx, 'ScanResult status ' + str(resp.status)) if resp.status != 0: raise RuntimeError authmode_str = [ 'Open', 'WEP', 'WPA_PSK', 'WPA2_PSK', 'WPA_WPA2_PSK', 'WPA2_ENTERPRISE' ] results = [] for entry in resp.resp_scan_result.entries: results += [{ 'ssid': entry.ssid.decode('latin-1').rstrip('\x00'), 'bssid': utils.str_to_hexstr(entry.bssid.decode('latin-1')), 'channel': entry.channel, 'rssi': entry.rssi, 'auth': authmode_str[entry.auth] }] print_verbose(security_ctx, 'ScanResult SSID : ' + str(results[-1]['ssid'])) print_verbose(security_ctx, 'ScanResult BSSID : ' + str(results[-1]['bssid'])) print_verbose(security_ctx, 'ScanResult Channel : ' + str(results[-1]['channel'])) print_verbose(security_ctx, 'ScanResult RSSI : ' + str(results[-1]['rssi'])) print_verbose(security_ctx, 'ScanResult AUTH : ' + str(results[-1]['auth'])) return results
def config_apply_config_response(security_ctx, response_data): # Interpret protobuf response packet from ApplyConfig command decrypt = security_ctx.decrypt_data(tobytes(response_data)) cmd_resp5 = proto.wifi_config_pb2.WiFiConfigPayload() cmd_resp5.ParseFromString(decrypt) print_verbose(security_ctx, "ApplyConfig status " + str(cmd_resp5.resp_apply_config.status)) return cmd_resp5.resp_apply_config.status
def scan_result_response(security_ctx, response_data): # Interpret protobuf response packet from ScanResult command dec_resp = security_ctx.decrypt_data(tobytes(response_data)) resp = proto.wifi_scan_pb2.WiFiScanPayload() resp.ParseFromString(dec_resp) print_verbose(security_ctx, "ScanResult status " + str(resp.status)) if resp.status != 0: raise RuntimeError authmode_str = [ "Open", "WEP", "WPA_PSK", "WPA2_PSK", "WPA_WPA2_PSK", "WPA2_ENTERPRISE" ] results = [] for entry in resp.resp_scan_result.entries: results += [{ "ssid": entry.ssid.decode('latin-1').rstrip('\x00'), "bssid": utils.str_to_hexstr(entry.bssid.decode('latin-1')), "channel": entry.channel, "rssi": entry.rssi, "auth": authmode_str[entry.auth] }] print_verbose(security_ctx, "ScanResult SSID : " + str(results[-1]["ssid"])) print_verbose(security_ctx, "ScanResult BSSID : " + str(results[-1]["bssid"])) print_verbose(security_ctx, "ScanResult Channel : " + str(results[-1]["channel"])) print_verbose(security_ctx, "ScanResult RSSI : " + str(results[-1]["rssi"])) print_verbose(security_ctx, "ScanResult AUTH : " + str(results[-1]["auth"])) return results
def new_msgid(self): if self._msg_id_counter >= self._msg_id_counter_stop: self._reset_msgid() else: self._msg_id_counter = (self._msg_id_counter + 1) return tobytes('{0:08x}'.format( self._msg_id_counter)) + self._msg_id_base
def setup0_response(self, response_data): # Interpret SessionResp0 response packet setup_resp = proto.session_pb2.SessionData() setup_resp.ParseFromString(tobytes(response_data)) self._print_verbose("Security version:\t" + str(setup_resp.sec_ver)) if setup_resp.sec_ver != session_pb2.SecScheme1: print("Incorrect sec scheme") exit(1) self.device_public_key = setup_resp.sec1.sr0.device_pubkey # Device random is the initialization vector device_random = setup_resp.sec1.sr0.device_random self._print_verbose("Device Public Key:\t" + utils.str_to_hexstr(self.device_public_key.decode('latin-1'))) self._print_verbose("Device Random:\t" + utils.str_to_hexstr(device_random.decode('latin-1'))) # Calculate Curve25519 shared key using Client private key and Device public key sharedK = self.client_private_key.exchange(X25519PublicKey.from_public_bytes(self.device_public_key)) self._print_verbose("Shared Key:\t" + utils.str_to_hexstr(sharedK.decode('latin-1'))) # If PoP is provided, XOR SHA256 of PoP with the previously # calculated Shared Key to form the actual Shared Key if len(self.pop) > 0: # Calculate SHA256 of PoP h = hashes.Hash(hashes.SHA256(), backend=default_backend()) h.update(self.pop) digest = h.finalize() # XOR with and update Shared Key sharedK = xor(sharedK, digest) self._print_verbose("New Shared Key XORed with PoP:\t" + utils.str_to_hexstr(sharedK.decode('latin-1'))) # Initialize the encryption engine with Shared Key and initialization vector cipher = Cipher(algorithms.AES(sharedK), modes.CTR(device_random), backend=default_backend()) self.cipher = cipher.encryptor()
def setup0_response(self, response_data): # Interpret protocomm security0 response packet setup_resp = proto.session_pb2.SessionData() setup_resp.ParseFromString(tobytes(response_data)) # Check if security scheme matches if setup_resp.sec_ver != proto.session_pb2.SecScheme0: print("Incorrect sec scheme")
def custom_data_request(security_ctx, data): # Encrypt the custom data enc_cmd = security_ctx.encrypt_data(tobytes(data)) print_verbose( security_ctx, 'Client -> Device (CustomData cmd) ' + utils.str_to_hexstr(enc_cmd)) return enc_cmd
def custom_config_response(security_ctx, response_data): # Interpret protobuf response packet decrypt = security_ctx.decrypt_data(tobytes(response_data)) cmd_resp = proto.custom_config_pb2.CustomConfigResponse() cmd_resp.ParseFromString(decrypt) print_verbose(security_ctx, "CustomConfig status " + str(cmd_resp.status)) return cmd_resp.status
def process_invalid_content(self, task, data, url): """If feedparser reports error, save the received data and log error.""" if data is None: log.critical('Received empty page - no content') return else: data = tobytes(data) ext = 'xml' if b'<html>' in data.lower(): log.critical('Received content is HTML page, not an RSS feed') ext = 'html' if b'login' in data.lower() or b'username' in data.lower(): log.critical('Received content looks a bit like login page') if b'error' in data.lower(): log.critical('Received content looks a bit like error page') received = os.path.join(task.manager.config_base, 'received') if not os.path.isdir(received): os.mkdir(received) filename = task.name sourcename = urlparse(url).netloc if sourcename: filename += '-' + sourcename filename = pathscrub(filename, filename=True) filepath = os.path.join(received, '%s.%s' % (filename, ext)) with open(filepath, 'wb') as f: f.write(data) log.critical('I have saved the invalid content to %s for you to view', filepath)
def get_prop_count_response(response_data): resp = local_ctrl_pb2.LocalCtrlMessage() resp.ParseFromString(tobytes(response_data)) if (resp.resp_get_prop_count.status == 0): return resp.resp_get_prop_count.count else: return 0
def hexstr_to_str(hexstr): # Prepend 0 (if needed) to make the hexstr length an even number if len(hexstr) % 2 == 1: hexstr = '0' + hexstr # Interpret consecutive pairs of hex characters as 8 bit ASCII codes # and append characters corresponding to each code to form the string return binascii.unhexlify(tobytes(hexstr)).decode()
def config_get_status_response(security_ctx, response_data): # Interpret protobuf response packet from GetStatus command decrypted_message = security_ctx.decrypt_data(tobytes(response_data)) cmd_resp1 = proto.wifi_config_pb2.WiFiConfigPayload() cmd_resp1.ParseFromString(decrypted_message) print_verbose(security_ctx, 'Response type ' + str(cmd_resp1.msg)) print_verbose(security_ctx, 'Response status ' + str(cmd_resp1.resp_get_status.status)) if cmd_resp1.resp_get_status.sta_state == 0: print('++++ WiFi state: ' + 'connected ++++') return 'connected' elif cmd_resp1.resp_get_status.sta_state == 1: print('++++ WiFi state: ' + 'connecting... ++++') return 'connecting' elif cmd_resp1.resp_get_status.sta_state == 2: print('++++ WiFi state: ' + 'disconnected ++++') return 'disconnected' elif cmd_resp1.resp_get_status.sta_state == 3: print('++++ WiFi state: ' + 'connection failed ++++') if cmd_resp1.resp_get_status.fail_reason == 0: print('++++ Failure reason: ' + 'Incorrect Password ++++') elif cmd_resp1.resp_get_status.fail_reason == 1: print('++++ Failure reason: ' + 'Incorrect SSID ++++') return 'failed' return 'unknown'
def setup0_response(self, response_data): # Interpret SessionResp0 response packet setup_resp = proto.session_pb2.SessionData() setup_resp.ParseFromString(tobytes(response_data)) self._print_verbose('Security version:\t' + str(setup_resp.sec_ver)) if setup_resp.sec_ver != session_pb2.SecScheme1: print('Incorrect sec scheme') exit(1) self.device_public_key = setup_resp.sec1.sr0.device_pubkey # Device random is the initialization vector device_random = setup_resp.sec1.sr0.device_random self._print_verbose('Device Public Key:\t' + utils.str_to_hexstr(self.device_public_key.decode('latin-1'))) self._print_verbose('Device Random:\t' + utils.str_to_hexstr(device_random.decode('latin-1'))) # Calculate Curve25519 shared key using Client private key and Device public key sharedK = self.client_private_key.exchange(X25519PublicKey.from_public_bytes(self.device_public_key)) self._print_verbose('Shared Key:\t' + utils.str_to_hexstr(sharedK.decode('latin-1'))) # If PoP is provided, XOR SHA256 of PoP with the previously # calculated Shared Key to form the actual Shared Key if len(self.pop) > 0: # Calculate SHA256 of PoP h = hashes.Hash(hashes.SHA256(), backend=default_backend()) h.update(self.pop) digest = h.finalize() # XOR with and update Shared Key sharedK = xor(sharedK, digest) self._print_verbose('New Shared Key XORed with PoP:\t' + utils.str_to_hexstr(sharedK.decode('latin-1'))) # Initialize the encryption engine with Shared Key and initialization vector cipher = Cipher(algorithms.AES(sharedK), modes.CTR(device_random), backend=default_backend()) self.cipher = cipher.encryptor()
def custom_config_request(security_ctx, info, version): # Form protobuf request packet from custom-config data cmd = proto.custom_config_pb2.CustomConfigRequest() cmd.info = tobytes(info) cmd.version = version enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()).decode('latin-1') print_verbose(security_ctx, "Client -> Device (CustomConfig cmd) " + utils.str_to_hexstr(enc_cmd)) return enc_cmd
def __init__(self, symbol="NONE", time=0, price=0, order_type=0, amount=0): self.symbol = tobytes(symbol) self.time = time self.price = price self.bid = price self.ask = price self.order_type = order_type self.amount = amount
def get_prop_count_response(security_ctx, response_data): decrypt = security_ctx.decrypt_data(tobytes(response_data)) resp = local_ctrl_pb2.LocalCtrlMessage() resp.ParseFromString(decrypt) if (resp.resp_get_prop_count.status == 0): return resp.resp_get_prop_count.count else: return 0
def scan_start_response(security_ctx, response_data): # Interpret protobuf response packet from ScanStart command dec_resp = security_ctx.decrypt_data(tobytes(response_data)) resp = proto.wifi_scan_pb2.WiFiScanPayload() resp.ParseFromString(dec_resp) print_verbose(security_ctx, 'ScanStart status ' + str(resp.status)) if resp.status != 0: raise RuntimeError
def custom_cloud_config_response(security_ctx, response_data): # Interpret protobuf response packet decrypt = security_ctx.decrypt_data(tobytes(response_data)) cmd_resp = proto.custom_cloud_config_pb2.CloudConfigPayload() cmd_resp.ParseFromString(decrypt) print_verbose(security_ctx, "CustomConfig msg value " + str(cmd_resp.msg)) print_verbose(security_ctx, "CustomConfig Status " + str(cmd_resp.resp_get_set_details.Status)) print_verbose(security_ctx, "CustomConfig Device Secret " + str(cmd_resp.resp_get_set_details.DeviceSecret)) return cmd_resp.resp_get_set_details.Status, cmd_resp.resp_get_set_details.DeviceSecret
def _send_post_request(self, path, data): try: self.conn.request('POST', path, tobytes(data), self.headers) response = self.conn.getresponse() if response.status == 200: return response.read().decode('latin-1') except Exception as err: raise RuntimeError('Connection Failure : ' + str(err)) raise RuntimeError('Server responded with error code ' + str(response.status))
def new_msgid( self ): # message id 就是 channel id ; 看 channel.Channel()._channel_id if self._msg_id_counter >= self._msg_id_counter_stop: self._reset_msgid() else: self._msg_id_counter = (self._msg_id_counter + 1) return tobytes('{0:08x}'.format( self._msg_id_counter)) + self._msg_id_base
def scan_status_response(security_ctx, response_data): # Interpret protobuf response packet from ScanStatus command dec_resp = security_ctx.decrypt_data(tobytes(response_data)) resp = proto.wifi_scan_pb2.WiFiScanPayload() resp.ParseFromString(dec_resp) print_verbose(security_ctx, "ScanStatus status " + str(resp.status)) if resp.status != 0: raise RuntimeError return {"finished": resp.resp_scan_status.scan_finished, "count": resp.resp_scan_status.result_count}
def _send_post_request(self, path, data): try: self.conn.request("POST", path, tobytes(data), self.headers) response = self.conn.getresponse() if response.status == 200: return response.read().decode('latin-1') except Exception as err: raise RuntimeError("Connection Failure : " + str(err)) raise RuntimeError("Server responded with error code " + str(response.status))
def encrypt(self, text): # setting iv because the underlying AES module misbehaves # on certain platforms encryptor = AES.new(self.key, self.mode, IV=b'0' * 16) text = tobytes(text) if len(text) % 16: text += b' ' * (16 - len(text) % 16) return encryptor.encrypt(text)
def get_task_context(self): if self.trace_id is None: # just an ugly code to generate a beautiful little hash. self._locals.trace_id = '<{0}>'.format(hashlib.md5( tobytes(str(random.random())[3:]) ).hexdigest()[0:6].upper()) print(self._identity, 'get_task_context! [make a new one]', self.trace_id) self._log.append(('new', self.trace_id)) else: print(self._identity, 'get_task_context! [reuse]', self.trace_id) self._log.append(('reuse', self.trace_id)) return { 'trace_id': self.trace_id }
def encode_prop_value(prop, value): try: if prop["type"] == PROP_TYPE_TIMESTAMP: return struct.pack('q', value) elif prop["type"] == PROP_TYPE_INT32: return struct.pack('i', value) elif prop["type"] == PROP_TYPE_BOOLEAN: return struct.pack('?', value) elif prop["type"] == PROP_TYPE_STRING: return tobytes(value) return value except struct.error as e: print(e) return None
def setup1_response(self, response_data): # Interpret SessionResp1 response packet setup_resp = proto.session_pb2.SessionData() setup_resp.ParseFromString(tobytes(response_data)) # Ensure security scheme matches if setup_resp.sec_ver == session_pb2.SecScheme1: # Read encrypyed device verify string device_verify = setup_resp.sec1.sr1.device_verify_data self._print_verbose('Device verify:\t' + utils.str_to_hexstr(device_verify.decode('latin-1'))) # Decrypt the device verify string enc_client_pubkey = self.cipher.update(setup_resp.sec1.sr1.device_verify_data) self._print_verbose('Enc client pubkey:\t ' + utils.str_to_hexstr(enc_client_pubkey.decode('latin-1'))) # Match decryped string with client public key if enc_client_pubkey != self.client_public_key: print('Mismatch in device verify') return -2 else: print('Unsupported security protocol') return -1
def setup1_response(self, response_data): # Interpret SessionResp1 response packet setup_resp = proto.session_pb2.SessionData() setup_resp.ParseFromString(tobytes(response_data)) # Ensure security scheme matches if setup_resp.sec_ver == session_pb2.SecScheme1: # Read encrypyed device verify string device_verify = setup_resp.sec1.sr1.device_verify_data self._print_verbose("Device verify:\t" + utils.str_to_hexstr(device_verify.decode('latin-1'))) # Decrypt the device verify string enc_client_pubkey = self.cipher.update(setup_resp.sec1.sr1.device_verify_data) self._print_verbose("Enc client pubkey:\t " + utils.str_to_hexstr(enc_client_pubkey.decode('latin-1'))) # Match decryped string with client public key if enc_client_pubkey != self.client_public_key: print("Mismatch in device verify") return -2 else: print("Unsupported security protocol") return -1
def config_get_status_response(security_ctx, response_data): # Interpret protobuf response packet from GetStatus command decrypted_message = security_ctx.decrypt_data(tobytes(response_data)) cmd_resp1 = proto.wifi_config_pb2.WiFiConfigPayload() cmd_resp1.ParseFromString(decrypted_message) print_verbose(security_ctx, "Response type " + str(cmd_resp1.msg)) print_verbose(security_ctx, "Response status " + str(cmd_resp1.resp_get_status.status)) if cmd_resp1.resp_get_status.sta_state == 0: print("++++ WiFi state: " + "connected ++++") elif cmd_resp1.resp_get_status.sta_state == 1: print("++++ WiFi state: " + "connecting... ++++") elif cmd_resp1.resp_get_status.sta_state == 2: print("++++ WiFi state: " + "disconnected ++++") elif cmd_resp1.resp_get_status.sta_state == 3: print("++++ WiFi state: " + "connection failed ++++") if cmd_resp1.resp_get_status.fail_reason == 0: print("++++ Failure reason: " + "Incorrect Password ++++") elif cmd_resp1.resp_get_status.fail_reason == 1: print("++++ Failure reason: " + "Incorrect SSID ++++") return cmd_resp1.resp_get_status.sta_state
def _reset_msgid(self): self._msg_id_base = tobytes(uuid.uuid4().hex)[8:] self._msg_id_counter = random.randrange(0, 2 ** 32) self._msg_id_counter_stop = random.randrange(self._msg_id_counter, 2 ** 32)
def new_msgid(self): if self._msg_id_counter >= self._msg_id_counter_stop: self._reset_msgid() else: self._msg_id_counter = (self._msg_id_counter + 1) return tobytes('{0:08x}'.format(self._msg_id_counter)) + self._msg_id_base
def encrypt(self, text): # Padding to blocksize of AES text = tobytes(text) if len(text) % 16: text += b' ' * (16 - len(text) % 16) return self.core.encrypt(tobytes(text))
def __init__(self, pop, verbose): # Initialize state of the security1 FSM self.session_state = security_state.REQUEST1 self.pop = tobytes(pop) self.verbose = verbose Security.__init__(self, self.security1_session)