def openWallet(): name = input('Wallet Name ("[new]" to create wallet): ') if name != '[new]': if not os.path.isfile('wallets/' + name + '.privkey'): print(color.E('\nWallet not found!\n')) openWallet() phrase = getpass.getpass('Passphrase: ') wallet = Wallet(name, phrase) wallet.getKey() if wallet.key: print(color.I('\nOpened wallet ' + wallet.name + '\n')) print('\nType "help" to view commands\n') walletPrompt(wallet) else: openWallet() else: name = input('New wallet name: ') phrase = getpass.getpass('New passphrase for wallet: ') if not os.path.isfile('wallets/' + name + '.privkey'): newkey = RSA.generate(3072) privkey = newkey.exportKey().decode('utf-8') with open('wallets/' + name + '.privkey', 'a') as privf: enc = AESCipher(phrase) encKey = enc.encrypt(privkey) privf.write(str(encKey)) print(color.I('Wallet created successfully!\n')) openWallet() else: print('Wallet with name "' + name + '" already exists!') openWallet()
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 encrypt_data(body): # 如果请求的使用 AES 加密,则加密返回的数据 logger.debug('使用 AES 加密 body') aes_cipher = AESCipher(client.secret_key) body = aes_cipher.encrypt(utf8(body)) # 更新为加密后的数据 self.handler.clear_write_buffer() self.handler.write(body) self.handler.set_header('X-Api-Encrypt-Type', 'aes')
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 encrypt_data(self): aes_cipher = AESCipher(self.secret_key) headers_str = json_util.dumps(self.request_data.headers) # 加密 Headers 和 url self.request_data.headers = { 'Content-Type': 'application/octet-stream', 'X-Api-Encrypted-Headers': aes_cipher.encrypt(utf8(headers_str)), 'X-Api-Encrypted-Uri': aes_cipher.encrypt(utf8(self.request_data.uri)) } self.request_data.uri = '/?_t=%d&_nonce=%s' % \ (int(time.time()), text_type(random.random())) # 设置一个新的 url url = self.api_server.strip() + self.request_data.uri if self.request_data.body is not None and len(self.request_data.body) > 0: self.request_data.body = aes_cipher.encrypt(utf8(self.request_data.body)) logger.debug(self.request_data.body) return url
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 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 encrypt_data(self): aes_cipher = AESCipher(self.secret_key) headers_str = json_util.dumps(self.request_data.headers) # 加密 Headers 和 url self.request_data.headers = { 'Content-Type': 'application/octet-stream', 'X-Api-Encrypted-Headers': aes_cipher.encrypt(utf8(headers_str)), 'X-Api-Encrypted-Uri': aes_cipher.encrypt(utf8(self.request_data.uri)) } self.request_data.uri = '/?_t=%d&_nonce=%s' % \ (int(time.time()), text_type(random.random())) # 设置一个新的 url url = self.api_server.strip() + self.request_data.uri if self.request_data.body is not None and len( self.request_data.body) > 0: self.request_data.body = aes_cipher.encrypt( utf8(self.request_data.body)) logger.debug(self.request_data.body) return url
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 getcipher(Sessionid): Password = memcache.get(Sessionid + ".Password") IV = memcache.get(Sessionid + ".IV") if Password is None or IV is None: q = Endpoint.query(Endpoint.Sessionid == Sessionid) for rec in q.fetch(1): # logging.warning("Found") Password = str(rec.Password) IV = rec.IV memcache.add(Sessionid + ".Password", Password, 1800) memcache.add(Sessionid + ".IV", IV, 1800) #print("PASSWORD IS" + repr(Password)) #print("IV IS" + repr(IV)) try: cipher = AESCipher(Password, IV) return cipher except Exception: logging.warning("Not Found") return None
logging.debug(" with wrapped signature key " + base64.b64encode(sign_key_wrapped).decode('utf-8') ) logging.debug("End PubSub Publish") logging.info(">>>>>>>>>>> END <<<<<<<<<<<") if args.mode =="encrypt": logging.info(">>>>>>>>>>> Start Encryption with locally generated key. <<<<<<<<<<<") ## Send pubsub messages using two different symmetric keys ## Note, i'm not using the expiringdict here...i'm just picking a DEK, sending N messages using it ## then picking another DEK and sending N messages with that one. ## The subscriber will use a cache of DEK values. If it detects a DEK in the metadata that doesn't ## match whats in its cache, it will use KMS to try to decode it and then keep it in its cache. for x in range(30): logging.info("Rotating symmetric key") ac = AESCipher(encoded_key=None) dek = ac.getKey().encode() logging.debug("Generated dek: " + base64.b64encode(dek).decode() ) logging.info("Starting KMS encryption API call") dek_encrypted = kms_client.encrypt(name=name, plaintext=dek,additional_authenticated_data=tenantID.encode('utf-8')) dek_key_wrapped = dek_encrypted.ciphertext logging.info("Wrapped dek: " + base64.b64encode(dek_key_wrapped).decode('utf-8')) logging.info("End KMS encryption API call") logging.debug("Starting AES encryption") cleartext_message = {
cleartext_message = { "data": "foo".encode(), "attributes": { 'epoch_time': int(time.time()), 'a': "aaa", 'c': "ccc", 'b': "bbb" } } # cleartext_message = canonicaljson.encode_canonical_json(cleartext_message) # logging.info("Canonical JSON message " + cleartext_message.decode('utf-8')) if args.mode == 'encrypt': logging.info("Starting AES encryption") ac = AESCipher(key) msg = ac.encrypt(json.dumps(cleartext_message).encode('utf-8'), associated_data='') logging.info("End AES encryption") logging.info("Start PubSub Publish") publisher.publish(topic_name, data=msg.encode('utf-8')) logging.info("Published Message: " + str(msg)) logging.info("End PubSub Publish") if args.mode == 'sign': logging.info("Starting signature") hh = HMACFunctions(key) msg_hash = hh.hash(json.dumps(cleartext_message).encode('utf-8')) logging.info("End signature") logging.info("Start PubSub Publish")
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)
if args.mode == "encrypt": logging.info( ">>>>>>>>>>> Start Encryption with locally generated key. <<<<<<<<<<<" ) ## Send pubsub messages using two different symmetric keys ## Note, i'm not using the expiringdict here...i'm just picking a DEK, sending N messages using it ## then picking another DEK and sending N messages with that one. ## The subscriber will use a cache of DEK values. If it detects a DEK in the metadata that doesn't ## match whats in its cache, it will use KMS to try to decode it and then keep it in its cache. for x in range(5): logging.info("Rotating symmetric key") # create a new TINK AES DEK and encrypt it with KMS. # (i.,e an encrypted tink keyset) cc = AESCipher(encoded_key=None) dek = cc.getKey() logging.info(cc.printKeyInfo()) logging.debug("Generated dek: " + dek) logging.info("Starting KMS encryption API call") encrypt_response = kms_client.encrypt( request={ 'name': name, 'plaintext': dek.encode('utf-8'), 'additional_authenticated_data': tenantID.encode('utf-8') }) dek_encrypted = base64.b64encode( encrypt_response.ciphertext).decode('utf-8')
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 client_disconect(self): self.client.disconnect() return if __name__ == '__main__': parser = argparse.ArgumentParser(description='Poc of BEAST attack') parser.add_argument('host', help='hostname or IP address "localhost"') parser.add_argument('port', type=int, help='TCP port number') parser.add_argument('-v', "--verbose", help='debug mode, you need a large screen', action="store_true") args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.DEBUG) # this key is unsecure but we doesn't care for the Poc cbc = AESCipher('V38lKILOJmtpQMHp') server = Server(args.host, args.port) client = Client(args.host, args.port+1, cbc) spy = Proxy(args.host, args.port+1) exploit = BEAST(client, cbc) server.connection() spy.connection() exploit.run() spy.disconnect() server.disconnect()
def __desencripta(self, dato): return AESCipher(self.__salt).decrypt(dato)
logging.info( ">>>>>>>>>>> Start Encrypt with Service Account Public Key Reference <<<<<<<<<<<" ) logging.info(' Using remote public key_id = ' + args.recipient_key_id) logging.info( ' For service account at: https://www.googleapis.com/service_accounts/v1/metadata/x509/' + args.recipient) cert_url = 'https://www.googleapis.com/service_accounts/v1/metadata/x509/' + args.recipient r = requests.get(cert_url) pem = r.json().get(args.recipient_key_id) rs = RSACipher(public_key_pem=pem) # Create a new TINK AES key used for data encryption cc = AESCipher(encoded_key=None) dek = cc.getKey() logging.info("Generated DEK: " + cc.printKeyInfo()) # now use the DEK to encrypt the pubsub message encrypted_payload = cc.encrypt( json.dumps(cleartext_message).encode('utf-8'), associated_data="") logging.info("DEK Encrypted Message: " + encrypted_payload) # encrypt the DEK with the service account's key dek_wrapped = rs.encrypt(dek.encode('utf-8')) logging.info("Wrapped DEK " + dek_wrapped.decode('utf-8')) # now publish the dek-encrypted message, the encrypted dek resp = publisher.publish(topic_name, data=encrypted_payload.encode('utf-8'), service_account=args.recipient,
cleartext_message = { "data": "foo".encode(), "attributes": { 'epoch_time': int(time.time()), 'a': "aaa", 'c': "ccc", 'b': "bbb" } } # cleartext_message = canonicaljson.encode_canonical_json(cleartext_message) # logging.info("Canonical JSON message " + cleartext_message.decode('utf-8')) if args.mode == 'encrypt': logging.info("Starting AES encryption") ac = AESCipher(key) logging.info("Loaded Key: " + ac.printKeyInfo()) msg = ac.encrypt(json.dumps(cleartext_message).encode('utf-8'), associated_data='') logging.info("End AES encryption") logging.info("Start PubSub Publish") resp = publisher.publish(topic_name, data=msg.encode('utf-8')) logging.info("Published Message: " + str(msg)) logging.info("Published MessageID: " + resp.result()) logging.info("End PubSub Publish") if args.mode == 'sign': logging.info("Starting signature") hh = HMACFunctions(key) logging.info("Loaded Key: " + hh.printKeyInfo()) msg_hash = hh.hash(json.dumps(cleartext_message).encode('utf-8'))
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): 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 ")
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 ")