0

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
bbartling
  • 3,288
  • 9
  • 43
  • 88

1 Answers1

3

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

stasiekz
  • 1,775
  • 5
  • 22
  • Thanks for the answer post. If I were to use nginx proxy to handle the SSL/TLS with a Flask App, would my POST payload be encrypted via nginx? Thus this step of what I am trying to do here with fernet encrypting is sort not necessary....? – bbartling Aug 29 '21 at 17:56
  • @HenryHub The only reason to use such encryption here that comes to my mind is that you for instance don't trust the owner / maintainer of the application you are sending data to and that they obviously don't know the key you use for encryption and decryption of the data. SSL/TLS encrypts the data only on its way to the server and once it reaches the server it is up to the website owner what happens to the data. – stasiekz Aug 29 '21 at 19:53
  • @HenryHub Setting up SSL/TLS connection serves mainly the purpose of ensuring that the data exchanged between user's computer and your website is encrypted thus can't be eavesdropped on its way from the e.g. internet browser to the server hosting the website nor changed because its integrity is validated. Also user can make sure that given website is the authentic one based on its certificate. If these are the reasons you want to use encryption then you don't need to encrypt manually. – stasiekz Aug 29 '21 at 20:04
  • Thanks for the tips that all makes sense. I also made the website, so there isn't a need of being worried about not trusting the owner. Its actually just a REST api, no web pages or HTML. Is this a good place to start with nginx and Flask? I've never utilized nginx before. https://lemariva.com/blog/2020/11/nginx-docker-flask-and-lets-encrypt-ssl – bbartling Aug 30 '21 at 12:16