Last active
November 8, 2019 05:15
-
-
Save hassaku/0e43101b23ea85a7f0f1b58c9e9dd620 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
http://localhost:5000/encrypt