Skip to content

Instantly share code, notes, and snippets.

@hassaku
Last active November 8, 2019 05:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hassaku/0e43101b23ea85a7f0f1b58c9e9dd620 to your computer and use it in GitHub Desktop.
Save hassaku/0e43101b23ea85a7f0f1b58c9e9dd620 to your computer and use it in GitHub Desktop.
# coding: utf-8
"""
ユースケース:
夫婦が離婚した場合、子の養育費は主に二人の収入によって決定する。
養育費を計算したいが、互いに自分の年収を相手に知らせたくない。
このとき、秘密計算によって互いの年収を知ることなく養育費を計算する。
"""
from flask import Flask, request, jsonify
import requests
import pickle
import numpy as np
from operator import add
from functools import reduce
from Pyfhel import Pyfhel, PyCtxt, PyPtxt
import base64
app = Flask(__name__)
# FHEの初期化
he = Pyfhel()
he.contextGen(p=6, m=8192)
he.keyGen()
HOST = "localhost"
PORT = 5000
URL = "http://{}:{}".format(HOST, PORT)
TABLE = np.array([
[6, 4, 2, 1],
[8, 6, 4, 3],
[10, 8, 6, 5],
[12, 10, 8, 7],
])
def cipher2base64(c):
c.save('tmp.cipher')
ff = open('tmp.cipher', 'rb')
file = ff.read()
ff.close()
#return str(base64.b64encode(file))
byte_data = str(file).encode('utf-8')
return base64.b64encode(byte_data)
def base642cipher(enc):
byte_data = str(enc).encode('utf-8')
dec = base64.b64decode(byte_data)
ff = open('tmp.cipher', 'wb')
ff.write(dec)
ff.close()
return PyCtxt().load('tmp.cipher')
@app.route('/encrypt', methods=["GET", "POST"])
def encrypt():
if request.method == "GET":
return """
<form action="/encrypt" method="POST">
<input name="income">収入(万円) ※1~1000</input><br>
<input name="family_id">家族ID</input><br>
<select name="is_husband">
<option value="1">義務者</option>
<option value="2">権利者</option>
</select>
<br>
<input type="submit" value="送信する">
</form>"""
else:
#posted = request.get_json()
#income = posted["income"]
#family_id = posted["family_id"]
#is_husband = posted["is_husband"]
income = request.form["income"]
family_id = request.form["family_id"]
is_husband = request.form["is_husband"]
#assert int(income) > 0
#assert int(income) < 1000
if int(income) <= 400:
income_index = 0
elif int(income) <= 500:
income_index = 1
elif int(income) <= 600:
income_index = 2
else:
income_index = 3
# TODO convert income to table
if is_husband == "1":
values = [0] * len(TABLE)
values[income_index] = 1
else:
values = TABLE[:, income_index].tolist()
encrypted_income = [he.encryptInt(val) for val in values]
cipher_data[(family_id, is_husband, False)] = encrypted_income
# post
res = requests.post(url="{}/calc".format(URL),
#data=','.join(encrypted_income),
#data={"family_id": family_id, "is_husband": is_husband, "encrypted": encrypted_income},
data=pickle.dumps({"family_id": family_id, "is_husband": is_husband}),#, "encrypted": ','.join(encrypted_income)}),
headers={'Content-Type': 'application/octet-stream'})
back_link = "<a href={}/encrypt>戻る<a>".format(URL)
encrypted = pickle.loads(res.content)
#print('#', encrypted)
if encrypted == {}:
return "もう一方の結果を待ってから、再度送信してください。<br>" + back_link
#decs = [sk.decrypt(val) for val in encrypted]
decs = he.decryptInt(cipher_data[(family_id, is_husband, True)])
#return jsonify({"result": decs})
return "養育費は{}万円です。<br>".format(decs) + back_link
# This should be running on another server
storage = {}
cipher_data = {}
@app.route('/calc', methods=["POST"])
def calc():
data = pickle.loads(request.data)
#data = request.data
family_id = data["family_id"]
is_husband = data["is_husband"]
if family_id not in storage.keys():
storage[family_id] = {"husband": None, "wife": None}
if is_husband == "1":
storage[family_id]["husband"] = cipher_data[(family_id, is_husband, False)]#[base642cipher(c) for c in data["encrypted"]]
else:
storage[family_id]["wife"] = cipher_data[(family_id, is_husband, False)] #[base642cipher(c) for c in data["encrypted"]]
if (storage[family_id]["husband"] == None) or (storage[family_id]["wife"] == None):
return pickle.dumps({})
enc1 = storage[family_id]["husband"]
enc2 = storage[family_id]["wife"]
# encrypted calculation
enc3 = reduce(add, map(lambda x, y: x * y, enc1, enc2))
cipher_data[(family_id, is_husband, True)] = enc3
return pickle.dumps('hoge')
if __name__ == "__main__":
app.run(host=HOST, port=PORT)
@hassaku
Copy link
Author

hassaku commented Nov 8, 2019

$ python team5_chld_support_cost.py

http://localhost:5000/encrypt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment