前回に続いて、引き続きプライベートAPIをAPIドキュメントを読んで1から実装していきます。
前回の記事:【Python】プライベートAPIの利用に必要なAPI認証や電子署名をAPIドキュメントから実装する<前編>
以下の情報を HTTP リクエストヘッダに含めます。
ACCESS-KEY: 開発者ページで発行した API keyACCESS-TIMESTAMP: リクエスト時の Unix TimestampACCESS-SIGN: 以下の方法でリクエストごとに生成した署名
ACCESS-SIGNは、ACCESS-TIMESTAMP, HTTP メソッド, リクエストのパス, リクエストボディ を文字列として連結したものを、 API secret で HMAC-SHA256 署名を行った結果です。
https://lightning.bitflyer.com/docs?lang=ja#%E8%AA%8D%E8%A8%BC
とりあえず、リクエストヘッダーに乗せる電子署名の部分で、電子署名するテキストは生成できたので、ここからはいよいよこれを電子署名していきます。使っている変数とかは前回定義したものを引き続き使用しているので、そちらを確認してください。
暗号化の電子署名にはいろいろなフォーマットがありますが、APIドキュメントには「ACCESS-SIGN(電子署名)はACCESS-TIMESTAMP, HTTP メソッド, リクエストのパス, リクエストボディ を文字列として連結したものを、 API secret で HMAC-SHA256 署名を行った結果です。」とあるので、HAMC-SHA256でAPI秘密鍵を使い電子署名を行います。
HMAC-256で電子署名
HMACとは正式名称は「Keyed-Hashing for Message Authentication code」。HMACでは「秘密鍵」と「暗号化のハッシュ関数」を使って計算を行っています。鍵付きのハッシングなどとも呼ばれます。
プライベートAPIを操作する場合には、まず、APIキーとSecret(秘密鍵)を生成します。そして、実際にAPIに送るパラメータとSecretとを併せてハッシュ値を算出し、このハッシュ値をAPIに送るという手順を踏まなければなりません。
送信するのはハッシュ値なので、万が一送信データが漏えいしたとしても、Secretを読む事はできません。これによって、通信の際の第3者へのデータ漏えいリスクを防止しています。
通信の暗号化とハッシュ関数については深い関係性があり、この仕組みはビットコインにも応用されており、現在のIT社会の中で欠かせない存在です。
関連記事:Pythonでハッシュ関数とブロックチェーン分かりやすく学ぶ
PythonでのHMAC-256の署名には「hmac」というライブラリを使用します。
# テキストをhmacと秘密鍵で署名する
text = timestamp + method + path
sign = hmac.new(bytes(API_SECRET.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest()
ちなみに変数textの中身はこんな感じ。UNIXTIMEとAPIのメソッドとPATHを文字列で繋げています。
1574661527.0733738GET/v1/me/getbalance
これを秘密鍵で電子署名するとこんなのになります。
3911004e955822484e07de2b55ffd390fed665554ac3938a3d98c98069e94c8679
こういうあるテキストをハッシュ関数で暗号化(ハッシュ化)した値を「ハッシュ値」と言います。hmacにはいろいろと方式がありますが、現行の方式で一番強いのがSHA256というやつなので、それを使っています。ちなみに、このSHA256という暗号化方式はビットコインのマイニングにも使用されています
そして、この出来上がったハッシュ値をAPIリクエストのヘッダーに乗せます。API鍵とタイムスタンプとコンテンツタイプはもう決まっているので、今回のリクエストヘッダーは以下のようになります。
#ヘッダーの情報
headers = {
"ACCESS-KEY": API_KEY,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-SIGN": sign,
"Content-Type": "application/json"
}
APIリクエストを飛ばす
これで用意は整ったので、APIリクエストを飛ばします。
# 口座残高を取得するAPIリクエストを飛ばす response = requests.get(endpoint + path, headers=headers)
今回は口座残高を取得するので、リクエスト方式は「GET」になります。なので、requests.get()を使います。
そしてリクエスト先のURLは、エンドポイントの「https://api.bitflyer.jp」とAPIリクエストのPATHである「/v1/me/getbalance」を繋げたものになります。
requests.get()引数のheadersはリクエストのヘッダーになるので、さきほど作った辞書型の変数headersを設定します。
import time
import requests
import hmac
import hashlib
# ビットフライヤーのAPI鍵
API_KEY = "自分のAPI鍵"
API_SECRET = "自分のAPI秘密鍵"
# endpointのURL設定する
endpoint = 'https://api.bitflyer.jp'
# タイムスタンプ用のUNIXTIMEを取得する
timestamp = str(time.time())
# 使用するプライベートAPIのmethodとPATHを設定
method = 'GET'
path = '/v1/me/getbalance'
# 署名するテキストを作成
text = timestamp + method + path
print('text', text)
# HMAC-SHA256で電子署名
sign = hmac.new(bytes(API_SECRET.encode('ascii')), bytes(text.encode('ascii')), hashlib.sha256).hexdigest()
print('sign', sign)
#リクエストヘッダーの情報
headers = {
"ACCESS-KEY": API_KEY,
"ACCESS-TIMESTAMP": timestamp,
"ACCESS-SIGN": sign,
"Content-Type": "application/json"
}
# APIリクエストを飛ばす
response = requests.get(endpoint + path, headers=headers)
# レスポンスの中身を表示する
print(response.text)
終わり
この要領が分かれば他のプライベートAPIもラッピングパッケージに頼ることなく、自分で実装できると思います。またこの辺りはビットコインのトランザクションの署名とかにも必要になってくる知識なので、ブロックチェーンに興味ある人とか押さえておきましょう。
参照記事
・http://liibercraft.com/archives/632
・http://www.stockdog.work/fpuy8hrfms
・https://zaihack.com/bitflyer-api-sample/

コメント