Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change pairing process #38

Merged
merged 2 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions server/src/Auth/firebase.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
def sign_in_with_email_and_password(api_key, email, password):
"""
Firebaseで認証を行う(SDKの signInWithEmailAndPassword と同値)

:param api_key:
:param email:
:param password:
Expand Down
44 changes: 44 additions & 0 deletions server/src/Pairing/PairingModel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import hashlib
from DB import DB

db = DB()
device_keys = db.device_keys


def generate_major_minor(public_key):
"""
majorとminorをpublic_keyから生成する

:param public_key: str
:return major, minor: (int, int)
"""

temp = public_key
while True:
major, minor = generate(temp)
device_key = device_keys.find_one({'major': major, 'minor': minor})
if not device_key:
break
temp = hashlib.sha256(temp.encode()).hexdigest()

return major, minor


def generate(key):
forward = key[:32]
backward = key[32:]

forward_hash = hashlib.sha256(forward.encode()).hexdigest()
backward_hash = hashlib.sha256(backward.encode()).hexdigest()

# 16bitのuintに変換
major = int(forward_hash, 16) % 2**16
minor = int(backward_hash, 16) % 2**16

return major, minor


if __name__ == '__main__':
public_key = 'a' * 64
print(generate(public_key))
# (42311, 42311)
35 changes: 25 additions & 10 deletions server/src/Pairing/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from flask import Blueprint, request, jsonify
from DB import DB
from crypto.generate import generate_ed25519_keypair
from Pairing import PairingModel
from flask_jwt_extended import create_access_token

PAIRING_BP = Blueprint('pairing', __name__, url_prefix='/pairing')
Expand All @@ -13,8 +14,8 @@
pairings = db.pairings


@PAIRING_BP.route('/generate_device_key', methods=['POST'])
def generate_device_key():
@PAIRING_BP.route('/generate_major_minor', methods=['POST'])
def generate_major_minor():
uid = request.json['uid']
if not uid:
return jsonify({'error': 'Missing uid'}), 400
Expand All @@ -24,40 +25,54 @@ def generate_device_key():

private_key, public_key = generate_ed25519_keypair()

major, minor = PairingModel.generate_major_minor(public_key)

device_keys.insert_one({
'uid': uid,
'private_key': private_key,
'public_key': public_key
'public_key': public_key,
'major': major,
'minor': minor
})

return jsonify({'private_key': private_key, 'public_key': public_key}), 200
return jsonify({
'private_key': private_key,
'public_key': public_key,
'major': major,
'minor': minor
}), 200


@PAIRING_BP.route('/register_pairing', methods=['POST'])
def register_pairing():
token = request.json['token']
if not token:
return jsonify({'error': 'Missing token'}), 400
public_key = request.json['public_key']
if not public_key:
return jsonify({'error': 'Missing public_key'}), 400
major = request.json['major']
if not major:
return jsonify({'error': 'Missing major'}), 400
minor = request.json['minor']
if not minor:
return jsonify({'error': 'Missing minor'}), 400

user = users.find_one({'token': token})
if not user:
return jsonify({'error': 'Invalid token'}), 400

device_key = device_keys.find_one({'public_key': public_key})
device_key = device_keys.find_one({'major': major, 'minor': minor})
if not device_key:
return jsonify({'error': 'Invalid public_key'}), 400
return jsonify({'error': 'Invalid major,minor'}), 400

pairings.delete_many({'uid': user['uid']})
pairings.delete_many({'public_key': device_key['public_key']})
pairings.delete_many({'private_key': device_key['private_key']})

pairings.insert_one({
'uid': user['uid'],
'private_key': device_key['private_key'],
'public_key': device_key['public_key'],
'private_key': device_key['private_key']
'major': major,
'minor': minor
})

return jsonify({'done': 'pairing'}), 200
Expand Down
14 changes: 9 additions & 5 deletions server/src/StreetPass/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@

@STREETPASS_BP.route('/received_beacon', methods=['POST'])
def received_beacon():
received_public_key = request.json['received_public_key']
if not received_public_key:
return jsonify({'error': 'Missing received_public_key'}), 400
received_major = request.json['received_major']
if not received_major:
return jsonify({'error': 'Missing received_major'}), 400
received_minor = request.json['received_minor']
if not received_minor:
return jsonify({'error': 'Missing received_minor'}), 400
private_key = request.json['private_key']
if not private_key:
return jsonify({'error': 'Missing private_key'}), 400

received_user = pairings.find_one({'public_key': received_public_key})
received_user = pairings.find_one(
{'major': received_major, 'minor': received_minor})
if not received_user:
return jsonify({'error': 'Invalid received_public_key'}), 400
return jsonify({'error': 'Invalid received_major_minor'}), 400
sent_user = pairings.find_one({'private_key': private_key})
if not sent_user:
return jsonify({'error': 'Invalid private_key'}), 400
Expand Down
74 changes: 56 additions & 18 deletions server/tests/test_pairing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,44 @@

private_key = ''
public_key = ''
major = ''
minor = ''
token = ''
email = ''.join(random.choices(string.ascii_lowercase +
string.digits, k=20))+'@test.org'


def test_generate_device_key_success(baseurl):
def test_generate_major_minor_success(baseurl):
global private_key
global public_key
url = baseurl+'/pairing/generate_device_key'
global major
global minor
url = baseurl+'/pairing/generate_major_minor'
res = requests.post(url, json={
'uid': 'test_uid',
})
assert res.status_code == 200
private_key = res.json()['private_key']
public_key = res.json()['public_key']
assert private_key
public_key = res.json()['public_key']
assert public_key
major = res.json()['major']
assert major
minor = res.json()['minor']
assert minor


def test_generate_device_key_missing_uid(baseurl):
url = baseurl+'/pairing/generate_device_key'
def test_generate_major_minor_missing_uid(baseurl):
url = baseurl+'/pairing/generate_major_minor'
res = requests.post(url, json={
'uid': '',
})
assert res.status_code == 400
assert res.json()['error'] == 'Missing uid'


def test_generate_device_key_already_exists(baseurl):
url = baseurl+'/pairing/generate_device_key'
def test_generate_major_minor_already_exists(baseurl):
url = baseurl+'/pairing/generate_major_minor'
res = requests.post(url, json={
'uid': 'test_uid',
})
Expand All @@ -56,12 +64,13 @@ def get_token(baseurl):

def test_register_pairing_success(baseurl):
global token
global public_key
global major, minor
url = baseurl+'/pairing/register_pairing'
token = get_token(baseurl)
res = requests.post(url, json={
'token': token,
'public_key': public_key
'major': major,
'minor': minor
})
assert res.status_code == 200
assert res.json()['done'] == 'pairing'
Expand All @@ -73,52 +82,81 @@ def test_register_pairing_success(baseurl):

user = users.find_one({'token': token})
pairing = pairings.find_one(
{'uid': user['uid'], 'public_key': public_key, 'private_key': private_key})
{'uid': user['uid'], 'major': major, 'minor': minor})
assert pairing


def test_register_pairing_missing_token(baseurl):
global public_key
global major, minor
url = baseurl+'/pairing/register_pairing'
res = requests.post(url, json={
'token': '',
'public_key': public_key
'major': major,
'minor': minor
})
assert res.status_code == 400
assert res.json()['error'] == 'Missing token'


def test_register_pairing_missing_public_key(baseurl):
def test_register_pairing_missing_major(baseurl):
global token
global minor
url = baseurl+'/pairing/register_pairing'
res = requests.post(url, json={
'token': token,
'major': '',
'minor': minor
})
assert res.status_code == 400
assert res.json()['error'] == 'Missing major'


def test_register_pairing_missing_minor(baseurl):
global token
global major
url = baseurl+'/pairing/register_pairing'
res = requests.post(url, json={
'token': token,
'public_key': ''
'major': major,
'minor': ''
})
assert res.status_code == 400
assert res.json()['error'] == 'Missing public_key'
assert res.json()['error'] == 'Missing minor'


def test_register_pairing_invalid_token(baseurl):
global public_key
global major, minor
url = baseurl+'/pairing/register_pairing'
res = requests.post(url, json={
'token': 'invalidToken',
'public_key': public_key
'major': major,
'minor': minor
})
assert res.status_code == 400
assert res.json()['error'] == 'Invalid token'


def test_register_pairing_invalid_public_key(baseurl):
def test_register_pairing_invalid_major_minor(baseurl):
global token
global major, minor
url = baseurl+'/pairing/register_pairing'
res = requests.post(url, json={
'token': token,
'public_key': 'invalidPublicKey'
'major': 'invalidMajor',
'minor': minor
})
assert res.status_code == 400
assert res.json()['error'] == 'Invalid major,minor'

res = requests.post(url, json={
'token': token,
'major': major,
'minor': 'invalidMinor'
})
assert res.status_code == 400
assert res.json()['error'] == 'Invalid public_key'
assert res.json()['error'] == 'Invalid major,minor'


def test_auth_check_success(baseurl):
Expand Down
Loading