ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

様々な言語からmBaaSを扱うために署名作成アルゴリズムを考える【Go言語編】

f:id:mbaasdevrel:20190222160911j:plain

プログラムからmBaaSを操作する際にはAPIを利用しますが、その時に肝になるのが署名文字列の作成です。パスなどをつなげて、SHA256でハッシュ値を作ったりと非常に面倒な処理が必要です。

アプリ側であればSDKを使ってもらえれば問題ありません。問題はサーバサイドで、オフィシャルではNode.js、非公式ではRubyとPHPくらいしかライブラリがありません。

そこで今回は一番面倒と思われる署名作成処理について、他の言語での実装方法について解説します。今回はGo言語です。

必要な引数について

署名を作成する際には以下の情報が必要です。

変数 名前 説明
method HTTPメソッド GETやPOSTといった文字列です
fqdn FQDN 通常はmbaas.api.nifcloud.com、スクリプトの場合はscript.mbaas.api.nifcloud.comになります
path リクエストするAPIのパス /2013-09-01/classes/TestClassなどです
queries クエリストリング クエリストリングです。今回はマップで作成しています
applicationKey アプリケーションキー 管理画面で取得できるアプリケーションキーです
signatureMethod シグネチャメソッド HmacSHA256という文字列固定です
signatureVersion シグネチャバージョン 2という文字列固定です
timestamp タイムスタンプ APIリクエスト時の時間です
clientKey クライアントキー 管理画面で取得できるクライアントキーです

生成前の変数について

まず上記の情報を揃えます。各値は検証のため、REST API リファレンス : シグネチャの生成方法 | ニフクラ mobile backendに合わせています。

method := "GET"
fqdn := "mbaas.api.nifcloud.com"
path := "/2013-09-01/classes/TestClass"
queries := make(map[string]map[string]string)
queries["where"] = make(map[string]string)
queries["where"]["testKey"] = "testValue"
applicationKey := "6145f91061916580c742f806bab67649d10f45920246ff459404c46f00ff3e56"
clientKey := "1343d198b510a0315db1c03f3aa0e32418b7a743f8e4b47cbff670601345cf75"
signatureMethod := "HmacSHA256"
signatureVersion := "2"
timestamp := time.Date(2013, 12, 02, 02, 44, 35, 452e6, time.UTC)

マップの作成

最初に署名用文字列を作ります。これはメソッドやFQDNなどをキー名と値でつないだ文字列になります。

// マップを作成
arySig := make(map[string]string)
// 基本的な項目の設定
arySig["SignatureMethod"] = signatureMethod
arySig["SignatureVersion"] = signatureVersion
arySig["X-NCMB-Application-Key"] = applicationKey
arySig["X-NCMB-Timestamp"] = timestamp.Format("2006-01-02T15:04:05.000Z")

クエリーをURLエンコーディング

クエリー文字列(元々はマップ)をJSON化し、URLエンコーディングします。

// クエリ文字列のエスケープ
if (len(queries) > 0) {
  for key, params := range queries {
    j, _ := json.Marshal(params)
    arySig[key] = url.QueryEscape(string(j))
  }
}

自然順序付け・昇順で並び替え

arySigをソートします。

// ソートするために配列に入れ替え
ary := []string{}
for val := range arySig {
   ary = append(ary, val)
}
sort.Strings(ary)
params := []string{}
for _, name := range ary {
  params = append(params, name + "=" + arySig[name])
}

署名用文字列を作成

そして署名用文字列を作ります。最終的に改行でつなぐので、まず配列で作成します。

// シグネチャ用文字列の作成
signature := []string{}
signature = append(signature, method)
signature = append(signature, fqdn)
signature = append(signature, path)
signature = append(signature, strings.Join(params, "&"))

署名作成

最後に署名を作成します。これはHMACを使ってSHA256でハッシュを作成します。そしてそのハッシュをBASE64エンコーディングしたものが該当文字列になります。

// ハッシュ値の作成
mac := hmac.New(sha256.New, []byte(clientKey))
mac.Write([]byte(strings.Join(signature, "\n")))
// 署名文字列の返却
base64.StdEncoding.EncodeToString(mac.Sum(nil))

ここまでの操作で署名用文字列の生成が完了します。

検証

今回の条件で署名文字列が AltGkQgXurEV7u0qMd+87ud7BKuueldoCjaMgVc9Bes= になれば成功です。この基本的なコードさえマスターすれば、どのAPIへのアクセスでも利用できるはずです。

まとめ

今回のコードはGolangでNCMB用の署名文字列を生成するにアップロードしてあります。Go言語からNCMBを利用される際の参考にしてください。

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。