def decrypt_data(): aes_cipher = AESCipher(client.secret_key) encrypted_uri = self.handler.request.headers.get( 'X-Api-Encrypted-Uri') if encrypted_uri: request.uri = aes_cipher.decrypt(utf8(encrypted_uri)) logger.debug('decrypted uri %s' % request.uri) encrypted_headers = self.handler.request.headers.get( 'X-Api-Encrypted-Headers') if encrypted_headers: headers_str = aes_cipher.decrypt(utf8(encrypted_headers)) headers = dict(json.loads(headers_str)) logger.debug('raw headers %s' % request.headers) for k, v in headers.iteritems(): # 要全部使用 text_type,否则会出现有的为 str,有的为 unicode # 导致422错误 request.headers[text_type(k)] = text_type(v) logger.debug('decrypted headers %s' % request.headers) if request.body and len(request.body) > 0: logger.debug('解密 body') logger.debug(request.body) request.body = aes_cipher.decrypt(utf8(request.body))
def decrypt_data(): aes_cipher = AESCipher(client.secret_key) encrypted_uri = self.handler.request.headers.get('X-Api-Encrypted-Uri') if encrypted_uri: request.uri = aes_cipher.decrypt(utf8(encrypted_uri)) logger.debug('decrypted uri %s' % request.uri) # 因为修改了 uri,需要重新生成 query_arguments request.path, sep, request.query = request.uri.partition('?') request.arguments = parse_qs_bytes(request.query, keep_blank_values=True) request.query_arguments = copy.deepcopy(request.arguments) encrypted_headers = self.handler.request.headers.get('X-Api-Encrypted-Headers') if encrypted_headers: headers_str = aes_cipher.decrypt(utf8(encrypted_headers)) headers = dict(json_decode(headers_str)) # logger.debug('raw headers %s' % request.headers) for k, v in iteritems(headers): # 要全部使用 text_type,否则会出现有的为 str,有的为 unicode # 导致422错误 request.headers[text_type(k)] = text_type(v) # logger.debug('decrypted headers %s' % request.headers) if request.body and len(request.body) > 0: logger.debug('解密 body') logger.debug(request.body) request.body = aes_cipher.decrypt(utf8(request.body)) # 因为修改了 body,需要重新 _parse_body request._parse_body()
def getKey(self, cmd=False): if os.path.isfile('wallets/' + self.name + '.privkey'): with open('wallets/' + self.name + '.privkey', 'r', encoding='utf-8') as key: encKey = key.read() enc = AESCipher(self.phrase) try: self.key = enc.decrypt(encKey) except UnicodeDecodeError: print(color.E('\nIncorrect passphrase for wallet!\n')) else: self.key = False print(color.E('\nWallet not found!\n'))
def decrypt_data(self, body): try: aes_cipher = AESCipher(self.secret_key) if body and len(body) > 0: logger.debug('解密 body') logger.debug(body.encode('hex')) body = aes_cipher.decrypt(utf8(body)) # logger.debug(body.decode('hex')) except Exception as e: logger.error('解密数据出错') logger.error(e) logger.error(traceback.format_exc()) return None return body
def decrypt_data(self, body): try: aes_cipher = AESCipher(self.secret_key) if body and len(body) > 0: logger.debug('解密 body') body = aes_cipher.decrypt(utf8(body)) # logger.debug(body.decode('hex')) except Exception as e: logger.error('解密数据出错') logger.error(e) logger.error(traceback.format_exc()) return None # 由于 requests 的 content 不是 unicode 类型, 为了兼容, 这里改成 utf8 if isinstance(body, text_type): body = body.encode('utf-8') return body
def callback(message): logging.info("********** Start PubsubMessage ") message.ack() logging.info('Received message ID: {}'.format(message.message_id)) logging.info('Received message publish_time: {}'.format( message.publish_time)) if args.mode == 'decrypt': try: ac = AESCipher(key) logging.info("Loaded Key: " + ac.printKeyInfo()) decrypted_data = ac.decrypt(message.data, associated_data='') logging.info('Decrypted data ' + decrypted_data) logging.info("ACK message") message.ack() except Exception as e: logging.info("Unable to decrypt message; NACK pubsub message " + str(e)) message.nack() logging.info("End AES decryption") if args.mode == 'verify': try: logging.info("Starting HMAC") hmac = message.attributes.get('signature') hh = HMACFunctions(key) logging.info("Loaded Key: " + hh.printKeyInfo()) logging.info("Verify message: " + str(message.data)) logging.info(' With HMAC: ' + str(hmac)) hashed = hh.hash(message.data) if (hh.verify(message.data, base64.b64decode(hashed))): logging.info("Message authenticity verified") message.ack() else: logging.error("Unable to verify message") message.nack() except Exception as e: logging.info("Unable to verify message; NACK pubsub message " + str(e)) message.nack() logging.info("********** End PubsubMessage ")
def callback(message): logging.info("********** Start PubsubMessage ") logging.info('Received message ID: {}'.format(message.message_id)) logging.info('Received message publish_time: {}'.format( message.publish_time)) if args.mode == "verify": try: key_id = message.attributes['key_id'] service_account = message.attributes['service_account'] signature = message.attributes['signature'] m = hashlib.sha256() m.update(message.data) data_to_verify = m.digest() logging.info("Attempting to verify message: " + str(message.data)) logging.info("data_to_verify " + base64.b64encode(data_to_verify).decode('utf-8')) logging.info("Verify message with signature: " + str(signature)) logging.info(" Using service_account/key_id: " + service_account + " " + key_id) cert_url = 'https://www.googleapis.com/service_accounts/v1/metadata/x509/' + service_account r = requests.get(cert_url) pem = r.json().get(key_id) v = crypt.RSAVerifier.from_string(pem) if v.verify(data_to_verify, base64.b64decode(signature)): logging.info("Message integrity verified") message.ack() else: logging.info("Unable to verify message") message.nack() logging.info("********** End PubsubMessage ") except Exception as e: logging.info("Unable to verify message; NACK pubsub message " + str(e)) message.nack() if args.mode == "decrypt": try: key_id = message.attributes['key_id'] msg_service_account = message.attributes['service_account'] logging.info("Attempting to decrypt message: " + str(message.data)) logging.info(" Using service_account/key_id: " + msg_service_account + " " + key_id) if args.cert_service_account == None: logging.error( "********** cert_service_account must be specified to decrypt " ) message.nack() sys.exit() credentials = Credentials.from_service_account_file( args.cert_service_account) key_key_id = credentials._signer._key_id key_service_account_email = credentials.service_account_email if (msg_service_account != key_service_account_email): logging.info( "Service Account specified in command line does not match message payload service account" ) logging.info(msg_service_account + " --- " + args.cert_service_account) message.nack() return else: private_key = credentials._signer._key rs = RSACipher(private_key=private_key) try: logging.debug( 'Received message attributes["dek_wrapped"]: {}'. format(message.attributes['dek_wrapped'])) dek_wrapped = message.attributes['dek_wrapped'] logging.info('Wrapped DEK ' + dek_wrapped) dek_cleartext = rs.decrypt(dek_wrapped) logging.info('Decrypted DEK ' + dek_cleartext) dek = AESCipher(encoded_key=dek_cleartext) logging.info(dek.printKeyInfo()) plaintext = dek.decrypt(message.data, associated_data="") except ValueError: logging.error( "dek_wrapped not sent, attempting to decrypt with svc account rsa key" ) plaintext = rs.decrypt(message.data) except Exception as e: logging.error("Error Decrypting payload " + str(e)) message.nack() return logging.info("Decrypted Message payload: " + plaintext) message.ack() except Exception as e: logging.info("Unable to decrypt message; NACK pubsub message " + str(e)) message.nack() logging.info("********** End PubsubMessage ")
class ClientConnector(Protocol): """Handle one connection to a client. Its functions include: - Initiate connection to client. - Send an authentication message to client to start transmission. - Receive encrypted data packets from client, separated by split_char. - Decrypt data packets. Get the ID (first 2 bytes of decrypted text). Create a connection to HTTP proxy for each unique ID. - Forward request to HTTP proxy. Encrypt and send back the response. - Close connection to HTTP proxy for a given ID if a packet of the ID with close_char is received. """ def __init__(self, initiator): self.initiator = initiator self.main_pw = self.initiator.main_pw # control characters self.split_char = chr(27) + chr(28) + "%X" % struct.unpack( 'B', self.main_pw[-2:-1])[0] + "%X" % struct.unpack( 'B', self.main_pw[-3:-2])[0] + chr(31) self.client_pub = self.initiator.client_pub self.session_pw = urandom(16) self.cipher = AESCipher(self.session_pw, self.main_pw) self.authenticated = False self.buffer = "" self.latency = 10000 self.i = initiator.register() self.idchar = (str(self.i) if 10 <= self.i <= 99 else '0' + str(self.i)) self.cronjob = None self.cancel_job = None def generate_auth_msg(self): """Generate encrypted message. For auth and init. The message is in the form server_sign(main_pw) (HEX) + client_pub(session_pw) + id Total length is 512 + 256 + 2 = 770 bytes """ pw_enc = self.client_pub.encrypt(self.session_pw, None)[0] return '\r\n'.join( (self.initiator.signature_to_client, pw_enc, self.idchar, repr(self.initiator.client_recv_index_dict[self.i]))) def ping_send(self): """Send the initial ping message to the client at a certain interval. Ping mechanism (S for server, C for client, t-i for i-th timestamp): packet 0: S->C, t-0 packet 1: C->S, t-0 + t-1 packet 2: S->C, t-1 In this way, both server and client get the round-trip latency. Packet format (before encryption): "1" (1 byte) (type flag for ping) seq (1 byte) (0, 1 or 2) timestamp (11 or 22 bytes) (time in milliseconds, in hexagon) """ raw_packet = "1" + "0" + get_timestamp() to_write = self.cipher.encrypt(raw_packet) + self.split_char if self.authenticated: #logging.debug("send ping0") self.transport.write(to_write) interval = random.randint(500, 1500) / 100 if self.initiator.obfs_level == 3: RESET_INTERVAL = 5 else: RESET_INTERVAL = 2 self.cronjob = reactor.callLater(interval, self.ping_send) self.cancel_job = reactor.callLater(RESET_INTERVAL, self.close) def ping_recv(self, msg): """Parse ping 1 (without flag & seq) and send ping 2.""" #logging.debug("recv ping1") self.cancel_job.cancel() time0 = parse_timestamp(msg[:11]) self.latency = int(time() * 1000) - time0 logging.debug("latency: %dms" % self.latency) raw_packet = "1" + "2" + msg[11:] to_write = self.cipher.encrypt(raw_packet) + self.split_char if self.transport: #logging.debug("send ping2") self.transport.write(to_write) def connectionMade(self): """Event handler of being successfully connected to the client.""" logging.info("connected to client " + addr_to_str(self.transport.getPeer())) self.transport.write(self.generate_auth_msg() + self.split_char) def dataReceived(self, recv_data): """Event handler of receiving some data from client. Split, decrypt and hand them back to Control. """ # Avoid repetition caused by ping # logging.debug("received %d bytes from client " % len(recv_data) + # addr_to_str(self.transport.getPeer())) self.buffer += recv_data # a list of encrypted data packages # the last item may be incomplete recv = self.buffer.split(self.split_char) # leave the last (may be incomplete) item intact for text_enc in recv[:-1]: text_dec = self.cipher.decrypt(text_enc) # flag is 0 for normal data packet, 1 for ping packet, 2 for auth flag = int(text_dec[0]) if flag == 0: self.initiator.client_recv(text_dec[1:], self) elif flag == 2: auth_str = "AUTHENTICATED" + self.idchar if text_dec[1:].startswith(auth_str): max_recved_idx = eval(text_dec[1:].lstrip(auth_str)) self.authenticate_success() self.initiator.retransmit_clientconn_reload( self, max_recved_idx) else: self.close() else: # strip off type and seq (both are always 1) self.ping_recv(text_dec[2:]) self.buffer = recv[-1] # incomplete message def authenticate_success(self): self.authenticated = True logging.debug("Authentication confirm string received.") self.initiator.add_cli(self) self.ping_send() def close(self): '''a secure way to abort the connection''' try: self.cronjob.cancel() except Exception: pass # self.initiator.remove_cli(self) self.transport.loseConnection() def connectionLost(self, reason): """Event handler of losing the connection to the client. Call Control to handle it. """ if self.authenticated: logging.info("client connection lost: " + addr_to_str(self.transport.getPeer())) self.authenticated = False self.initiator.client_lost(self.i) def write(self, data, conn_id, index): """Encrypt and write data the client. Encrypted packets should be separated by split_char. Raw packet structure: type (1 byte) (0 for normal data packet) id (2 bytes) index (6 bytes) data """ if index < 100000: index = '0' * (6 - len(str(index))) + str(index) else: index = str(index) # get current time with base 36 as a string in a certain length . to_write = self.cipher.encrypt("0" + conn_id + index + data) +\ self.split_char logging.debug( "sending %d bytes to client %s with id %s" % (len(data), addr_to_str(self.transport.getPeer()), conn_id)) self.transport.write(to_write)
class ClientConnector(Protocol): """Handle one connection to a client. Its functions include: - Initiate connection to client. - Send an authentication message to client to start transmission. - Receive encrypted data packets from client, separated by split_char. - Decrypt data packets. Get the ID (first 2 bytes of decrypted text). Create a connection to HTTP proxy for each unique ID. - Forward request to HTTP proxy. Encrypt and send back the response. - Close connection to HTTP proxy for a given ID if a packet of the ID with close_char is received. """ def __init__(self, initiator): self.initiator = initiator self.main_pw = self.initiator.main_pw # control characters # self.split_char = chr(27) + chr(28) + chr(29) + chr(30) + chr(31) self.split_char = chr(27) + chr(28) + "%X" % struct.unpack('B', self.main_pw[-2:-1])[ 0] + "%X" % struct.unpack('B', self.main_pw[-3:-2])[0] + chr(31) self.pri = self.initiator.initiator.pri self.client_pub = self.initiator.client_pub self.session_pw = urandom(16) self.cipher = AESCipher(self.session_pw, self.main_pw) self.authenticated = False self.buffer = "" self.latency = 10000 self.idchar = initiator.register() self.cronjob = None self.cancel_job = None def generate_auth_msg(self): """Generate encrypted message. The message is in the form server_sign(main_pw) (HEX) + client_pub(session_pw) + id Total length is 512 + 256 + 2 = 770 bytes """ hex_sign = '%X' % self.pri.sign(self.main_pw, None)[0] pw_enc = self.client_pub.encrypt(self.session_pw, None)[0] return hex_sign + pw_enc + self.idchar def ping_send(self): """Send the initial ping message to the client at a certain interval. Ping mechanism (S for server, C for client, t-i for i-th timestamp): packet 0: S->C, t-0 packet 1: C->S, t-0 + t-1 packet 2: S->C, t-1 In this way, both server and client get the round-trip latency. Packet format (before encryption): "1" (1 byte) (type flag for ping) seq (1 byte) (0, 1 or 2) timestamp (11 or 22 bytes) (time in milliseconds, in hexagon) """ raw_packet = "1" + "0" + get_timestamp() to_write = self.cipher.encrypt(raw_packet) + self.split_char if self.authenticated: #logging.debug("send ping0") self.transport.write(to_write) interval = random.randint(500, 1500) / 100 if self.initiator.obfs_level == 3: RESET_INTERVAL = 5 else: RESET_INTERVAL = 2 self.cronjob = reactor.callLater(interval, self.ping_send) self.cancel_job = reactor.callLater(RESET_INTERVAL, self.close) def ping_recv(self, msg): """Parse ping 1 (without flag & seq) and send ping 2.""" #logging.debug("recv ping1") self.cancel_job.cancel() time0 = parse_timestamp(msg[:11]) self.latency = int(time() * 1000) - time0 logging.debug("latency: %dms" % self.latency) raw_packet = "1" + "2" + msg[11:] to_write = self.cipher.encrypt(raw_packet) + self.split_char if self.transport: #logging.debug("send ping2") self.transport.write(to_write) def connectionMade(self): """Event handler of being successfully connected to the client.""" logging.info("connected to client " + addr_to_str(self.transport.getPeer())) self.transport.write(self.generate_auth_msg()) def dataReceived(self, recv_data): """Event handler of receiving some data from client. Split, decrypt and hand them back to Control. """ # Avoid repetition caused by ping # logging.debug("received %d bytes from client " % len(recv_data) + # addr_to_str(self.transport.getPeer())) self.buffer += recv_data # a list of encrypted data packages # the last item may be incomplete recv = self.buffer.split(self.split_char) # leave the last (may be incomplete) item intact for text_enc in recv[:-1]: text_dec = self.cipher.decrypt(text_enc) # flag is 0 for normal data packet, 1 for ping packet flag = int(text_dec[0]) if flag == 0: self.initiator.client_recv(text_dec[1:]) elif flag == 2: if text_dec[1:] == "AUTHENTICATED" + self.idchar: self.authenticate_success() else: self.close() else: # strip off type and seq (both are always 1) self.ping_recv(text_dec[2:]) self.buffer = recv[-1] # incomplete message def authenticate_success(self): self.authenticated = True logging.debug("Authentication confirm string received.") self.initiator.add_cli(self) self.ping_send() def close(self): '''a secure way to abort the connection''' try: self.cronjob.cancel() except Exception: pass self.transport.loseConnection() def connectionLost(self, reason): """Event handler of losing the connection to the client. Call Control to handle it. """ if self.authenticated: logging.info("client connection lost: " + addr_to_str(self.transport.getPeer())) self.authenticated = False self.initiator.client_lost(self) def write(self, data, conn_id, index): """Encrypt and write data the client. Encrypted packets should be separated by split_char. Raw packet structure: type (1 byte) (0 for normal data packet) id (2 bytes) index (6 bytes) data """ to_write = self.cipher.encrypt("0" + conn_id + index + data) +\ self.split_char logging.debug("sending %d bytes to client %s with id %s" % (len(data), addr_to_str( self.transport.getPeer()), conn_id)) self.transport.write(to_write)
def callback(message): if (args.mode == "verify"): try: logging.info("********** Start PubsubMessage ") logging.info('Received message ID: {}'.format(message.message_id)) logging.info('Received message publish_time: {}'.format( message.publish_time)) logging.info('Received message attributes["kms_key"]: {}'.format( message.attributes['kms_key'])) logging.debug( 'Received message attributes["sign_key_wrapped"]: {}'.format( message.attributes['sign_key_wrapped'])) logging.info('Received message attributes["signature"]: {}'.format( message.attributes['signature'])) signature = message.attributes['signature'] name = message.attributes['kms_key'] sign_key_wrapped = message.attributes['sign_key_wrapped'] try: unwrapped_key = cache[sign_key_wrapped] logging.info("Using Cached DEK") except KeyError: logging.info( ">>>>>>>>>>>>>>>> Starting KMS decryption API call") decrypted_message = kms_client.decrypt( request={ 'name': name, 'ciphertext': base64.b64decode(sign_key_wrapped.encode('utf-8')), 'additional_authenticated_data': tenantID.encode('utf-8') }) logging.info("Decrypted HMAC " + decrypted_message.plaintext.decode('utf-8')) unwrapped_key = HMACFunctions( encoded_key=decrypted_message.plaintext) logging.info(unwrapped_key.printKeyInfo()) cache[sign_key_wrapped] = unwrapped_key logging.info("End KMS decryption API call") logging.debug("Verify message: " + message.data.decode('utf-8')) logging.debug(' With HMAC: ' + signature) sig = unwrapped_key.hash(message.data) if (unwrapped_key.verify(message.data, base64.b64decode(sig))): logging.info("Message authenticity verified") message.ack() else: logging.error("Unable to verify message") message.nack() logging.debug("********** End PubsubMessage ") except Exception as e: logging.info("Unable to decrypt message; NACK pubsub message " + str(e)) message.nack() if (args.mode == "decrypt"): try: logging.info("********** Start PubsubMessage ") logging.info('Received message ID: {}'.format(message.message_id)) logging.info('Received message publish_time: {}'.format( message.publish_time)) logging.info('Received message attributes["kms_key"]: {}'.format( message.attributes['kms_key'])) logging.info( 'Received message attributes["dek_wrapped"]: {}'.format( message.attributes['dek_wrapped'])) dek_wrapped = message.attributes['dek_wrapped'] name = message.attributes['kms_key'] try: dek = cache[dek_wrapped] logging.info("Using Cached DEK") except KeyError: logging.info( ">>>>>>>>>>>>>>>> Starting KMS decryption API call") decrypted_message = kms_client.decrypt( request={ 'name': name, 'ciphertext': base64.b64decode( dek_wrapped.encode('utf-8')), 'additional_authenticated_data': tenantID.encode( 'utf-8') }) logging.info("Decrypted DEK " + decrypted_message.plaintext.decode('utf-8')) dek = AESCipher(encoded_key=decrypted_message.plaintext) logging.info(dek.printKeyInfo()) cache[dek_wrapped] = dek logging.debug("Starting AES decryption") decrypted_data = dek.decrypt(message.data, associated_data=tenantID) logging.debug("End AES decryption") logging.info('Decrypted data ' + decrypted_data) message.ack() logging.debug("ACK message") logging.info("********** End PubsubMessage ") except Exception as e: logging.info("Unable to decrypt message; NACK pubsub message " + str(e)) message.nack()
def callback(message): if (args.mode == "verify"): logging.info("********** Start PubsubMessage ") logging.info('Received message ID: {}'.format(message.message_id)) logging.info('Received message publish_time: {}'.format( message.publish_time)) logging.info('Received message attributes["kms_key"]: {}'.format( message.attributes['kms_key'])) logging.info( 'Received message attributes["sign_key_wrapped"]: {}'.format( message.attributes['sign_key_wrapped'])) logging.info('Received message attributes["signature"]: {}'.format( message.attributes['signature'])) signature = message.attributes['signature'] name = message.attributes['kms_key'] sign_key_wrapped = message.attributes['sign_key_wrapped'] try: unwrapped_key = cache[sign_key_wrapped] except KeyError: logging.info("Starting KMS decryption API call") name = message.attributes['kms_key'] unwrapped_key_struct = kms_client.decrypt( name=name, ciphertext=base64.b64decode( message.attributes['sign_key_wrapped']), additional_authenticated_data=tenantID.encode('utf-8')) unwrapped_key = unwrapped_key_struct.plaintext logging.info("End KMS decryption API call") logging.debug("Verify message: " + message.data.decode('utf-8')) logging.debug(' With HMAC: ' + signature) logging.debug(' With unwrapped key: ' + base64.b64encode(unwrapped_key).decode('utf-8')) cache[sign_key_wrapped] = unwrapped_key hh = HMACFunctions(unwrapped_key) sig = hh.hash(message.data) if (hh.verify(message.data, base64.b64decode(sig))): logging.info("Message authenticity verified") message.ack() else: logging.error("Unable to verify message") message.nack() logging.debug("********** End PubsubMessage ") if (args.mode == "decrypt"): logging.info("********** Start PubsubMessage ") logging.info('Received message ID: {}'.format(message.message_id)) logging.debug('Received message publish_time: {}'.format( message.publish_time)) logging.debug('Received message attributes["kms_key"]: {}'.format( message.attributes['kms_key'])) logging.debug('Received message attributes["dek_wrapped"]: {}'.format( message.attributes['dek_wrapped'])) dek_wrapped = message.attributes['dek_wrapped'] name = message.attributes['kms_key'] try: dek = cache[dek_wrapped] except KeyError: logging.info("Starting KMS decryption API call") name = message.attributes['kms_key'] unwrapped_key_struct = kms_client.decrypt( name=name, ciphertext=base64.b64decode(dek_wrapped), additional_authenticated_data=tenantID.encode('utf-8')) dek = unwrapped_key_struct.plaintext logging.info("End KMS decryption API call") logging.info('Received aes_encryption_key : {}'.format( base64.b64encode(dek).decode('utf-8'))) cache[dek_wrapped] = dek logging.debug("Starting AES decryption") ac = AESCipher(dek) decrypted_data = ac.decrypt(message.data, associated_data="") logging.debug("End AES decryption") logging.info('Decrypted data ' + decrypted_data) message.ack() logging.debug("ACK message") logging.info("********** End PubsubMessage ")