RESTでSESAMEのスイカ鍵をちょっとセキュアに

#SESAMEのAPIはすばらしいけど、、、
sesame miniを買ったのです。そしてSESAMEのBlog（ https://ameblo.jp/candyhouse-inc/entry-12413908790.html ）で紹介されていたラズパイ＆SUICAの組合せで動かしていました。こいつは素晴らしい。玄関先にNFCリーダつけたラズパイをおいておけば、スマホのアプリを起動する手間すらいらない。iphoneをピットかざすだけでスイカを読み取って鍵があきます。

ただ、ある日気づいたんです。これ、いろいろ大切な情報が平文で入ってますよね、、、

#ちょっとでもセキュアに
セキュリティはもう奥が深すぎて僕にはとても手が及ばないです。
せめて外においているラズパイに大切な情報が平文ってのだけどうにかしよう。ということで考えたのが以下。我が家には室内にもnature remo代わりのラズパイが可動してるのでそいつを利用します。
![SUIKAGI ASIS-TOBE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388857/029d96f8-ab53-a281-89b4-038ab680d08e.png)

#RESTを使ってみたかった
今回RasberryPi間の情報のやりとりはRESTを使ってみました。SESAMEのAPIもRESTですし、僕自身仕事でRESTREST連呼してるので使ったかったんです。
参考にしたのはこちら
https://qiita.com/Morinikiz/items/c2af4ffa180856d1bf30

#さてプログラミング
今回は２台のラズパイにそれぞれサーバのプログラムとクライアントのプログラムが必要になります。

##ラズパイ宅内側
RESTとSESAME Blogをがっちゃんこです。
SUICAのIdmが一致しなかった場合は404、ここは適当アタックを避けるために遅延を入れたほうがいいのかも。

```python:suikagi-takunai.py
# -*- coding: utf-8 -*-
from flask import Flask, jsonify, abort, make_response

import requests
import json


# login CANDY HOUSE account and get token
url = "https://api.candyhouse.co/v1/accounts/login"
head = {"Content-type": "application/json"}
payload = {"email":"a@bcd.com", "password":"abcd"}
response = requests.post(url, headers=head, data=json.dumps(payload))
token = response.json()["authorization"]

api = Flask(__name__)

@api.route('/getIdｍ/<string:userId>', methods=['GET'])
def get_idm(userId):

    if (userId == "0139XXXXXXXXXXXX") or (userId == "0139XXXXXXXXXXXX"):
        result = 'OK' + userId
        print result
        
        # unlock Sesame with token
        url_control = "https://api.candyhouse.co/v1/sesames/XXXXXXXXXXX/control"
        head_control = {"X-Authorization": token, "Content-type": "application/json"}
        payload_control = {"type":"unlock"}
        response_control = requests.post(url_control, headers=head_control, data=json.dumps(payload_control))

    else :
        abort(404)

    return make_response(jsonify(result))

@api.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)

if __name__ == '__main__':
    api.run(host='192.168.XXX.XXX', port=XXXX)
```

Linux系ならCURL使えば簡単にデバックできます。さすがREST。

```
curl -i http://192.168.XXX.XXX:XXXX/getIdm/YYYYYY
```

##ラズパイ玄関外
先程のsesameBlogを元にラズパイをnfc認識するように設定してください
https://ameblo.jp/candyhouse-inc/entry-12413908790.html

そんでブログのページのコードを改造

```python:suikagi-genkan.py
# -*- coding: utf-8 -*-
import requests
import binascii
import nfc
import time
from threading import Thread, Timer


# Suica待ち受けの1サイクル秒
TIME_cycle = 1.0
# Suica待ち受けの反応インターバル秒
TIME_interval = 0.2
# タッチされてから次の待ち受けを開始するまで無効化する秒
TIME_wait = 3

# NFC接続リクエストのための準備
# 212F(FeliCa)で設定
target_req_suica = nfc.clf.RemoteTarget("212F")
# 0003(Suica)
target_req_suica.sensf_req = bytearray.fromhex("0000030000")

print 'Waiting for SUICA...'
while True:
    # USBに接続されたNFCリーダに接続してインスタンス化
    clf = nfc.ContactlessFrontend('usb')
    # Suica待ち受け開始
    # clf.sense( [リモートターゲット], [検索回数], [検索の間隔] )
    target_res = clf.sense(target_req_suica, iterations=int(TIME_cycle//TIME_interval)+1 , interval=TIME_interval)
    
    if target_res != None:
        tag = nfc.tag.activate_tt3(clf, target_res)
        tag.sys = 3
        
        #IDmを取り出す
        idm = binascii.hexlify(tag.idm)

        #REST用のurlを生成
        url = "http://192.168.XXX.XXX:XXXX/getIdm/" + idm

        response = requests.get(url)
        print(response.text)
                
        print 'sleep ' + str(TIME_wait) + ' seconds'
        time.sleep(TIME_wait)
    #end if
    
    clf.close()

#end while
```

##これから
文中でもちらと書きましたがこのままではidmはしから試されかねないので、idmが不正だったときに遅延させる仕組みとか、宅外のラズパイのステータスをLEDで表示したりとかさせたいです。