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 ")
"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')) logging.info("End signature")
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') logging.info("Wrapped dek: " + dek_encrypted) logging.info("End KMS encryption API call")
">>>>>>>>>>> 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, key_id=args.recipient_key_id, dek_wrapped=dek_wrapped)
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()