How to Encrypt Data and POST payload as form data to Flask App endpoint

Issue

I am following this tutorial for encrypting and decrypting data with the Python cryptography package and this other SO Post is very similar but doesn’t include sending the data over the internet to an http server which I am curious to figure out how. The tutorials are about using Fernet key as the encrypting method.

So this code below is reading a CSV file of time series data, and the encrypting part works just fine its just how can I package this as form data? Pandas read CSV, to json, and then I think to bytes of data for encrypting, is that possible to package as form and POST it to an HTTP Python Flask app endpoint?

This code runs fine below until it hits the requests.post part to POST the encrypted data:

import pandas as pd
import requests
import time
from cryptography.fernet import Fernet


df = pd.read_csv('event_schedule.xlsx', index_col='Time Block',parse_dates=True)

print(df)

post_this_data = df.to_json(orient="index")
print(post_this_data)


file = open('secret.key','rb')
key = file.read()
file.close()


fernet = Fernet(key)
encrypted=fernet.encrypt(post_this_data.encode())
print('Encrypted Success')
encrypted_list = list(encrypted)

r = requests.post('http://192.168.0.105:5000/update/data', data=encrypted_list)
print(r.text)

Traceback is:

Traceback (most recent call last):
  File "C:\Users\bbartling\OneDrive - Slipstream\Desktop\event_schedule\postingScriptEncrypted.py", line 26, in <module>
    r = requests.post('http://10.200.200.223:5000/update/data', data=encrypted_list)
  File "C:\Python39\lib\site-packages\requests\api.py", line 119, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "C:\Python39\lib\site-packages\requests\api.py", line 61, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Python39\lib\site-packages\requests\sessions.py", line 528, in request
    prep = self.prepare_request(req)
  File "C:\Python39\lib\site-packages\requests\sessions.py", line 456, in prepare_request
    p.prepare(
  File "C:\Python39\lib\site-packages\requests\models.py", line 319, in prepare
    self.prepare_body(data, files, json)
  File "C:\Python39\lib\site-packages\requests\models.py", line 510, in prepare_body
    body = self._encode_params(data)
  File "C:\Python39\lib\site-packages\requests\models.py", line 97, in _encode_params
    for k, vs in to_key_val_list(data):
TypeError: cannot unpack non-iterable int object

Solution

If you want encrypted data to be sent as a form data you would need to send it as dictionary where actual encrypted data is a value.

encrypted = fernet.encrypt(post_this_data.encode())
payload = {'encrypted_data': encrypted}
r = requests.post('http://192.168.0.105:5000/update/data', data=payload)

Then on your Flask endpoint side:


from flask import Flask, request

app = Flask(__name__)


@app.route('/update/data', methods=['POST'])
def index():
    encrypted_data = request.form['encrypted_data']
    # decrypt encrypted_data

Alternatively you can also consider sending encrypted data as a raw request body:

encrypted = fernet.encrypt(post_this_data.encode())
r = requests.post('http://192.168.0.105:5000/update/data', data=encrypted)

Then on your Flask endpoint side:


from flask import Flask, request

app = Flask(__name__)


@app.route('/update/data', methods=['POST'])
def index():
    encrypted_data = request.get_data()
    # decrypt encrypted_data

Answered By – stasiekz

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published